1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 9cb93a386Sopenharmony_ci#include "include/core/SkFontMetrics.h" 10cb93a386Sopenharmony_ci#include "include/core/SkFontMgr.h" 11cb93a386Sopenharmony_ci#include "include/core/SkImage.h" 12cb93a386Sopenharmony_ci#include "include/core/SkMallocPixelRef.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPictureRecorder.h" 14cb93a386Sopenharmony_ci#include "include/core/SkTextBlob.h" 15cb93a386Sopenharmony_ci#include "include/core/SkTypeface.h" 16cb93a386Sopenharmony_ci#include "include/effects/SkDashPathEffect.h" 17cb93a386Sopenharmony_ci#include "include/effects/SkImageFilters.h" 18cb93a386Sopenharmony_ci#include "include/effects/SkTableColorFilter.h" 19cb93a386Sopenharmony_ci#include "include/private/SkFixed.h" 20cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 21cb93a386Sopenharmony_ci#include "src/core/SkAnnotationKeys.h" 22cb93a386Sopenharmony_ci#include "src/core/SkAutoMalloc.h" 23cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h" 24cb93a386Sopenharmony_ci#include "src/core/SkOSFile.h" 25cb93a386Sopenharmony_ci#include "src/core/SkPicturePriv.h" 26cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h" 27cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h" 28cb93a386Sopenharmony_ci#include "src/shaders/SkShaderBase.h" 29cb93a386Sopenharmony_ci#include "tests/Test.h" 30cb93a386Sopenharmony_ci#include "tools/Resources.h" 31cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_cistatic const uint32_t kArraySize = 64; 34cb93a386Sopenharmony_cistatic const int kBitmapSize = 256; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciclass SerializationTest { 37cb93a386Sopenharmony_cipublic: 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_citemplate<typename T> 40cb93a386Sopenharmony_cistatic void TestAlignment(T* testObj, skiatest::Reporter* reporter) { 41cb93a386Sopenharmony_ci // Test memory read/write functions directly 42cb93a386Sopenharmony_ci unsigned char dataWritten[1024]; 43cb93a386Sopenharmony_ci size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten); 44cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory); 45cb93a386Sopenharmony_ci size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory); 46cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory); 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci}; 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_citemplate<typename T> struct SerializationUtils { 51cb93a386Sopenharmony_ci // Generic case for flattenables 52cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, const T* flattenable) { 53cb93a386Sopenharmony_ci writer.writeFlattenable(flattenable); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci static void Read(SkReadBuffer& reader, T** flattenable) { 56cb93a386Sopenharmony_ci *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType()); 57cb93a386Sopenharmony_ci } 58cb93a386Sopenharmony_ci}; 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkMatrix> { 61cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) { 62cb93a386Sopenharmony_ci writer.writeMatrix(*matrix); 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci static void Read(SkReadBuffer& reader, SkMatrix* matrix) { 65cb93a386Sopenharmony_ci reader.readMatrix(matrix); 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci}; 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkPath> { 70cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, const SkPath* path) { 71cb93a386Sopenharmony_ci writer.writePath(*path); 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci static void Read(SkReadBuffer& reader, SkPath* path) { 74cb93a386Sopenharmony_ci reader.readPath(path); 75cb93a386Sopenharmony_ci } 76cb93a386Sopenharmony_ci}; 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkRegion> { 79cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, const SkRegion* region) { 80cb93a386Sopenharmony_ci writer.writeRegion(*region); 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci static void Read(SkReadBuffer& reader, SkRegion* region) { 83cb93a386Sopenharmony_ci reader.readRegion(region); 84cb93a386Sopenharmony_ci } 85cb93a386Sopenharmony_ci}; 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkString> { 88cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, const SkString* string) { 89cb93a386Sopenharmony_ci writer.writeString(string->c_str()); 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci static void Read(SkReadBuffer& reader, SkString* string) { 92cb93a386Sopenharmony_ci reader.readString(string); 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci}; 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_citemplate<> struct SerializationUtils<unsigned char> { 97cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) { 98cb93a386Sopenharmony_ci writer.writeByteArray(data, arraySize); 99cb93a386Sopenharmony_ci } 100cb93a386Sopenharmony_ci static bool Read(SkReadBuffer& reader, unsigned char* data, uint32_t arraySize) { 101cb93a386Sopenharmony_ci return reader.readByteArray(data, arraySize); 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci}; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkColor> { 106cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) { 107cb93a386Sopenharmony_ci writer.writeColorArray(data, arraySize); 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci static bool Read(SkReadBuffer& reader, SkColor* data, uint32_t arraySize) { 110cb93a386Sopenharmony_ci return reader.readColorArray(data, arraySize); 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci}; 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkColor4f> { 115cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, SkColor4f* data, uint32_t arraySize) { 116cb93a386Sopenharmony_ci writer.writeColor4fArray(data, arraySize); 117cb93a386Sopenharmony_ci } 118cb93a386Sopenharmony_ci static bool Read(SkReadBuffer& reader, SkColor4f* data, uint32_t arraySize) { 119cb93a386Sopenharmony_ci return reader.readColor4fArray(data, arraySize); 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci}; 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_citemplate<> struct SerializationUtils<int32_t> { 124cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) { 125cb93a386Sopenharmony_ci writer.writeIntArray(data, arraySize); 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci static bool Read(SkReadBuffer& reader, int32_t* data, uint32_t arraySize) { 128cb93a386Sopenharmony_ci return reader.readIntArray(data, arraySize); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci}; 131cb93a386Sopenharmony_ci 132cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkPoint> { 133cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) { 134cb93a386Sopenharmony_ci writer.writePointArray(data, arraySize); 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci static bool Read(SkReadBuffer& reader, SkPoint* data, uint32_t arraySize) { 137cb93a386Sopenharmony_ci return reader.readPointArray(data, arraySize); 138cb93a386Sopenharmony_ci } 139cb93a386Sopenharmony_ci}; 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkPoint3> { 142cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, const SkPoint3* data) { 143cb93a386Sopenharmony_ci writer.writePoint3(*data); 144cb93a386Sopenharmony_ci } 145cb93a386Sopenharmony_ci static void Read(SkReadBuffer& reader, SkPoint3* data) { 146cb93a386Sopenharmony_ci reader.readPoint3(data); 147cb93a386Sopenharmony_ci } 148cb93a386Sopenharmony_ci}; 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_citemplate<> struct SerializationUtils<SkScalar> { 151cb93a386Sopenharmony_ci static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) { 152cb93a386Sopenharmony_ci writer.writeScalarArray(data, arraySize); 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci static bool Read(SkReadBuffer& reader, SkScalar* data, uint32_t arraySize) { 155cb93a386Sopenharmony_ci return reader.readScalarArray(data, arraySize); 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci}; 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_citemplate<typename T, bool testInvalid> struct SerializationTestUtils { 160cb93a386Sopenharmony_ci static void InvalidateData(unsigned char* data) {} 161cb93a386Sopenharmony_ci}; 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_citemplate<> struct SerializationTestUtils<SkString, true> { 164cb93a386Sopenharmony_ci static void InvalidateData(unsigned char* data) { 165cb93a386Sopenharmony_ci data[3] |= 0x80; // Reverse sign of 1st integer 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci}; 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_citemplate<typename T, bool testInvalid> 170cb93a386Sopenharmony_cistatic void TestObjectSerializationNoAlign(T* testObj, skiatest::Reporter* reporter) { 171cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 172cb93a386Sopenharmony_ci SerializationUtils<T>::Write(writer, testObj); 173cb93a386Sopenharmony_ci size_t bytesWritten = writer.bytesWritten(); 174cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci unsigned char dataWritten[1024]; 177cb93a386Sopenharmony_ci writer.writeToMemory(dataWritten); 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_ci SerializationTestUtils<T, testInvalid>::InvalidateData(dataWritten); 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci // Make sure this fails when it should (test with smaller size, but still multiple of 4) 182cb93a386Sopenharmony_ci SkReadBuffer buffer(dataWritten, bytesWritten - 4); 183cb93a386Sopenharmony_ci T obj; 184cb93a386Sopenharmony_ci SerializationUtils<T>::Read(buffer, &obj); 185cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !buffer.isValid()); 186cb93a386Sopenharmony_ci 187cb93a386Sopenharmony_ci // Make sure this succeeds when it should 188cb93a386Sopenharmony_ci SkReadBuffer buffer2(dataWritten, bytesWritten); 189cb93a386Sopenharmony_ci size_t offsetBefore = buffer2.offset(); 190cb93a386Sopenharmony_ci T obj2; 191cb93a386Sopenharmony_ci SerializationUtils<T>::Read(buffer2, &obj2); 192cb93a386Sopenharmony_ci size_t offsetAfter = buffer2.offset(); 193cb93a386Sopenharmony_ci // This should have succeeded, since there are enough bytes to read this 194cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, buffer2.isValid() == !testInvalid); 195cb93a386Sopenharmony_ci // Note: This following test should always succeed, regardless of whether the buffer is valid, 196cb93a386Sopenharmony_ci // since if it is invalid, it will simply skip to the end, as if it had read the whole buffer. 197cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, offsetAfter - offsetBefore == bytesWritten); 198cb93a386Sopenharmony_ci} 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_citemplate<typename T> 201cb93a386Sopenharmony_cistatic void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { 202cb93a386Sopenharmony_ci TestObjectSerializationNoAlign<T, false>(testObj, reporter); 203cb93a386Sopenharmony_ci SerializationTest::TestAlignment(testObj, reporter); 204cb93a386Sopenharmony_ci} 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_citemplate<typename T> 207cb93a386Sopenharmony_cistatic T* TestFlattenableSerialization(T* testObj, bool shouldSucceed, 208cb93a386Sopenharmony_ci skiatest::Reporter* reporter) { 209cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 210cb93a386Sopenharmony_ci SerializationUtils<T>::Write(writer, testObj); 211cb93a386Sopenharmony_ci size_t bytesWritten = writer.bytesWritten(); 212cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_ci SkASSERT(bytesWritten <= 4096); 215cb93a386Sopenharmony_ci unsigned char dataWritten[4096]; 216cb93a386Sopenharmony_ci writer.writeToMemory(dataWritten); 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci // Make sure this fails when it should (test with smaller size, but still multiple of 4) 219cb93a386Sopenharmony_ci SkReadBuffer buffer(dataWritten, bytesWritten - 4); 220cb93a386Sopenharmony_ci T* obj = nullptr; 221cb93a386Sopenharmony_ci SerializationUtils<T>::Read(buffer, &obj); 222cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !buffer.isValid()); 223cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, nullptr == obj); 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ci // Make sure this succeeds when it should 226cb93a386Sopenharmony_ci SkReadBuffer buffer2(dataWritten, bytesWritten); 227cb93a386Sopenharmony_ci const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 228cb93a386Sopenharmony_ci T* obj2 = nullptr; 229cb93a386Sopenharmony_ci SerializationUtils<T>::Read(buffer2, &obj2); 230cb93a386Sopenharmony_ci const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 231cb93a386Sopenharmony_ci if (shouldSucceed) { 232cb93a386Sopenharmony_ci // This should have succeeded, since there are enough bytes to read this 233cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, buffer2.isValid()); 234cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 235cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, obj2); 236cb93a386Sopenharmony_ci } else { 237cb93a386Sopenharmony_ci // If the deserialization was supposed to fail, make sure it did 238cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !buffer.isValid()); 239cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, nullptr == obj2); 240cb93a386Sopenharmony_ci } 241cb93a386Sopenharmony_ci 242cb93a386Sopenharmony_ci return obj2; // Return object to perform further validity tests on it 243cb93a386Sopenharmony_ci} 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_citemplate<typename T> 246cb93a386Sopenharmony_cistatic void TestArraySerialization(T* data, skiatest::Reporter* reporter) { 247cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 248cb93a386Sopenharmony_ci SerializationUtils<T>::Write(writer, data, kArraySize); 249cb93a386Sopenharmony_ci size_t bytesWritten = writer.bytesWritten(); 250cb93a386Sopenharmony_ci // This should write the length (in 4 bytes) and the array 251cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten); 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci unsigned char dataWritten[2048]; 254cb93a386Sopenharmony_ci writer.writeToMemory(dataWritten); 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci // Make sure this fails when it should 257cb93a386Sopenharmony_ci SkReadBuffer buffer(dataWritten, bytesWritten); 258cb93a386Sopenharmony_ci T dataRead[kArraySize]; 259cb93a386Sopenharmony_ci bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2); 260cb93a386Sopenharmony_ci // This should have failed, since the provided size was too small 261cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !success); 262cb93a386Sopenharmony_ci 263cb93a386Sopenharmony_ci // Make sure this succeeds when it should 264cb93a386Sopenharmony_ci SkReadBuffer buffer2(dataWritten, bytesWritten); 265cb93a386Sopenharmony_ci success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize); 266cb93a386Sopenharmony_ci // This should have succeeded, since there are enough bytes to read this 267cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, success); 268cb93a386Sopenharmony_ci} 269cb93a386Sopenharmony_ci 270cb93a386Sopenharmony_cistatic void TestBitmapSerialization(const SkBitmap& validBitmap, 271cb93a386Sopenharmony_ci const SkBitmap& invalidBitmap, 272cb93a386Sopenharmony_ci bool shouldSucceed, 273cb93a386Sopenharmony_ci skiatest::Reporter* reporter) { 274cb93a386Sopenharmony_ci sk_sp<SkImage> validImage(validBitmap.asImage()); 275cb93a386Sopenharmony_ci sk_sp<SkImageFilter> validBitmapSource(SkImageFilters::Image(std::move(validImage))); 276cb93a386Sopenharmony_ci sk_sp<SkImage> invalidImage(invalidBitmap.asImage()); 277cb93a386Sopenharmony_ci sk_sp<SkImageFilter> invalidBitmapSource(SkImageFilters::Image(std::move(invalidImage))); 278cb93a386Sopenharmony_ci sk_sp<SkImageFilter> xfermodeImageFilter( 279cb93a386Sopenharmony_ci SkImageFilters::Blend(SkBlendMode::kSrcOver, 280cb93a386Sopenharmony_ci std::move(invalidBitmapSource), 281cb93a386Sopenharmony_ci std::move(validBitmapSource), nullptr)); 282cb93a386Sopenharmony_ci 283cb93a386Sopenharmony_ci sk_sp<SkImageFilter> deserializedFilter( 284cb93a386Sopenharmony_ci TestFlattenableSerialization<SkImageFilter_Base>( 285cb93a386Sopenharmony_ci (SkImageFilter_Base*)xfermodeImageFilter.get(), shouldSucceed, reporter)); 286cb93a386Sopenharmony_ci 287cb93a386Sopenharmony_ci // Try to render a small bitmap using the invalid deserialized filter 288cb93a386Sopenharmony_ci // to make sure we don't crash while trying to render it 289cb93a386Sopenharmony_ci if (shouldSucceed) { 290cb93a386Sopenharmony_ci SkBitmap bitmap; 291cb93a386Sopenharmony_ci bitmap.allocN32Pixels(24, 24); 292cb93a386Sopenharmony_ci SkCanvas canvas(bitmap); 293cb93a386Sopenharmony_ci canvas.clear(0x00000000); 294cb93a386Sopenharmony_ci SkPaint paint; 295cb93a386Sopenharmony_ci paint.setImageFilter(deserializedFilter); 296cb93a386Sopenharmony_ci canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24))); 297cb93a386Sopenharmony_ci canvas.drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &paint); 298cb93a386Sopenharmony_ci } 299cb93a386Sopenharmony_ci} 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_cistatic void TestColorFilterSerialization(skiatest::Reporter* reporter) { 302cb93a386Sopenharmony_ci uint8_t table[256]; 303cb93a386Sopenharmony_ci for (int i = 0; i < 256; ++i) { 304cb93a386Sopenharmony_ci table[i] = (i * 41) % 256; 305cb93a386Sopenharmony_ci } 306cb93a386Sopenharmony_ci auto filter = SkTableColorFilter::Make(table); 307cb93a386Sopenharmony_ci sk_sp<SkColorFilter> copy( 308cb93a386Sopenharmony_ci TestFlattenableSerialization(as_CFB(filter.get()), true, reporter)); 309cb93a386Sopenharmony_ci} 310cb93a386Sopenharmony_ci 311cb93a386Sopenharmony_cistatic SkBitmap draw_picture(SkPicture& picture) { 312cb93a386Sopenharmony_ci SkBitmap bitmap; 313cb93a386Sopenharmony_ci bitmap.allocN32Pixels(SkScalarCeilToInt(picture.cullRect().width()), 314cb93a386Sopenharmony_ci SkScalarCeilToInt(picture.cullRect().height())); 315cb93a386Sopenharmony_ci SkCanvas canvas(bitmap); 316cb93a386Sopenharmony_ci picture.playback(&canvas); 317cb93a386Sopenharmony_ci return bitmap; 318cb93a386Sopenharmony_ci} 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_cistatic void compare_bitmaps(skiatest::Reporter* reporter, 321cb93a386Sopenharmony_ci const SkBitmap& b1, const SkBitmap& b2) { 322cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, b1.width() == b2.width()); 323cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, b1.height() == b2.height()); 324cb93a386Sopenharmony_ci 325cb93a386Sopenharmony_ci if ((b1.width() != b2.width()) || 326cb93a386Sopenharmony_ci (b1.height() != b2.height())) { 327cb93a386Sopenharmony_ci return; 328cb93a386Sopenharmony_ci } 329cb93a386Sopenharmony_ci 330cb93a386Sopenharmony_ci int pixelErrors = 0; 331cb93a386Sopenharmony_ci for (int y = 0; y < b2.height(); ++y) { 332cb93a386Sopenharmony_ci for (int x = 0; x < b2.width(); ++x) { 333cb93a386Sopenharmony_ci if (b1.getColor(x, y) != b2.getColor(x, y)) 334cb93a386Sopenharmony_ci ++pixelErrors; 335cb93a386Sopenharmony_ci } 336cb93a386Sopenharmony_ci } 337cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0 == pixelErrors); 338cb93a386Sopenharmony_ci} 339cb93a386Sopenharmony_ci 340cb93a386Sopenharmony_cistatic sk_sp<SkData> serialize_typeface_proc(SkTypeface* typeface, void* ctx) { 341cb93a386Sopenharmony_ci // Write out typeface ID followed by entire typeface. 342cb93a386Sopenharmony_ci SkDynamicMemoryWStream stream; 343cb93a386Sopenharmony_ci sk_sp<SkData> data(typeface->serialize(SkTypeface::SerializeBehavior::kDoIncludeData)); 344cb93a386Sopenharmony_ci uint32_t typeface_id = typeface->uniqueID(); 345cb93a386Sopenharmony_ci stream.write(&typeface_id, sizeof(typeface_id)); 346cb93a386Sopenharmony_ci stream.write(data->data(), data->size()); 347cb93a386Sopenharmony_ci return stream.detachAsData(); 348cb93a386Sopenharmony_ci} 349cb93a386Sopenharmony_ci 350cb93a386Sopenharmony_cistatic sk_sp<SkTypeface> deserialize_typeface_proc(const void* data, size_t length, void* ctx) { 351cb93a386Sopenharmony_ci SkStream* stream; 352cb93a386Sopenharmony_ci if (length < sizeof(stream)) { 353cb93a386Sopenharmony_ci return nullptr; 354cb93a386Sopenharmony_ci } 355cb93a386Sopenharmony_ci memcpy(&stream, data, sizeof(stream)); 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci SkFontID id; 358cb93a386Sopenharmony_ci if (!stream->read(&id, sizeof(id))) { 359cb93a386Sopenharmony_ci return nullptr; 360cb93a386Sopenharmony_ci } 361cb93a386Sopenharmony_ci 362cb93a386Sopenharmony_ci sk_sp<SkTypeface> typeface = SkTypeface::MakeDeserialize(stream); 363cb93a386Sopenharmony_ci return typeface; 364cb93a386Sopenharmony_ci} 365cb93a386Sopenharmony_ci 366cb93a386Sopenharmony_cistatic void serialize_and_compare_typeface(sk_sp<SkTypeface> typeface, 367cb93a386Sopenharmony_ci const char* text, 368cb93a386Sopenharmony_ci const SkSerialProcs* serial_procs, 369cb93a386Sopenharmony_ci const SkDeserialProcs* deserial_procs, 370cb93a386Sopenharmony_ci skiatest::Reporter* reporter) { 371cb93a386Sopenharmony_ci // Create a font with the typeface. 372cb93a386Sopenharmony_ci SkPaint paint; 373cb93a386Sopenharmony_ci paint.setColor(SK_ColorGRAY); 374cb93a386Sopenharmony_ci SkFont font(std::move(typeface), 30); 375cb93a386Sopenharmony_ci 376cb93a386Sopenharmony_ci // Paint some text. 377cb93a386Sopenharmony_ci SkPictureRecorder recorder; 378cb93a386Sopenharmony_ci SkIRect canvasRect = SkIRect::MakeWH(kBitmapSize, kBitmapSize); 379cb93a386Sopenharmony_ci SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(canvasRect.width()), 380cb93a386Sopenharmony_ci SkIntToScalar(canvasRect.height())); 381cb93a386Sopenharmony_ci canvas->drawColor(SK_ColorWHITE); 382cb93a386Sopenharmony_ci canvas->drawString(text, 24, 32, font, paint); 383cb93a386Sopenharmony_ci sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); 384cb93a386Sopenharmony_ci 385cb93a386Sopenharmony_ci // Serlialize picture and create its clone from stream. 386cb93a386Sopenharmony_ci SkDynamicMemoryWStream stream; 387cb93a386Sopenharmony_ci picture->serialize(&stream, serial_procs); 388cb93a386Sopenharmony_ci std::unique_ptr<SkStream> inputStream(stream.detachAsStream()); 389cb93a386Sopenharmony_ci sk_sp<SkPicture> loadedPicture(SkPicture::MakeFromStream(inputStream.get(), deserial_procs)); 390cb93a386Sopenharmony_ci 391cb93a386Sopenharmony_ci // Draw both original and clone picture and compare bitmaps -- they should be identical. 392cb93a386Sopenharmony_ci SkBitmap origBitmap = draw_picture(*picture); 393cb93a386Sopenharmony_ci SkBitmap destBitmap = draw_picture(*loadedPicture); 394cb93a386Sopenharmony_ci compare_bitmaps(reporter, origBitmap, destBitmap); 395cb93a386Sopenharmony_ci} 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_cistatic sk_sp<SkTypeface> makeDistortableWithNonDefaultAxes(skiatest::Reporter* reporter) { 398cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("fonts/Distortable.ttf")); 399cb93a386Sopenharmony_ci if (!distortable) { 400cb93a386Sopenharmony_ci REPORT_FAILURE(reporter, "distortable", SkString()); 401cb93a386Sopenharmony_ci return nullptr; 402cb93a386Sopenharmony_ci } 403cb93a386Sopenharmony_ci 404cb93a386Sopenharmony_ci const SkFontArguments::VariationPosition::Coordinate position[] = { 405cb93a386Sopenharmony_ci { SkSetFourByteTag('w','g','h','t'), SK_ScalarSqrt2 }, 406cb93a386Sopenharmony_ci }; 407cb93a386Sopenharmony_ci SkFontArguments params; 408cb93a386Sopenharmony_ci params.setVariationDesignPosition({position, SK_ARRAY_COUNT(position)}); 409cb93a386Sopenharmony_ci 410cb93a386Sopenharmony_ci sk_sp<SkFontMgr> fm = SkFontMgr::RefDefault(); 411cb93a386Sopenharmony_ci 412cb93a386Sopenharmony_ci sk_sp<SkTypeface> typeface = fm->makeFromStream(std::move(distortable), params); 413cb93a386Sopenharmony_ci if (!typeface) { 414cb93a386Sopenharmony_ci return nullptr; // Not all SkFontMgr can makeFromStream(). 415cb93a386Sopenharmony_ci } 416cb93a386Sopenharmony_ci 417cb93a386Sopenharmony_ci int count = typeface->getVariationDesignPosition(nullptr, 0); 418cb93a386Sopenharmony_ci if (count == -1) { 419cb93a386Sopenharmony_ci return nullptr; // The number of axes is unknown. 420cb93a386Sopenharmony_ci } 421cb93a386Sopenharmony_ci 422cb93a386Sopenharmony_ci return typeface; 423cb93a386Sopenharmony_ci} 424cb93a386Sopenharmony_ci 425cb93a386Sopenharmony_cistatic void TestPictureTypefaceSerialization(const SkSerialProcs* serial_procs, 426cb93a386Sopenharmony_ci const SkDeserialProcs* deserial_procs, 427cb93a386Sopenharmony_ci skiatest::Reporter* reporter) { 428cb93a386Sopenharmony_ci if (serial_procs != nullptr) { 429cb93a386Sopenharmony_ci { 430cb93a386Sopenharmony_ci // Load typeface from file to test CreateFromFile with index. 431cb93a386Sopenharmony_ci auto typeface = MakeResourceAsTypeface("fonts/test.ttc", 1); 432cb93a386Sopenharmony_ci if (!typeface) { 433cb93a386Sopenharmony_ci INFOF(reporter, "Could not run fontstream test because test.ttc not found."); 434cb93a386Sopenharmony_ci } else { 435cb93a386Sopenharmony_ci serialize_and_compare_typeface(std::move(typeface), "A!", serial_procs, deserial_procs, 436cb93a386Sopenharmony_ci reporter); 437cb93a386Sopenharmony_ci } 438cb93a386Sopenharmony_ci } 439cb93a386Sopenharmony_ci 440cb93a386Sopenharmony_ci { 441cb93a386Sopenharmony_ci // Load typeface as stream to create with axis settings. 442cb93a386Sopenharmony_ci auto typeface = makeDistortableWithNonDefaultAxes(reporter); 443cb93a386Sopenharmony_ci if (!typeface) { 444cb93a386Sopenharmony_ci INFOF(reporter, "Could not run fontstream test because Distortable.ttf not created."); 445cb93a386Sopenharmony_ci } else { 446cb93a386Sopenharmony_ci serialize_and_compare_typeface(std::move(typeface), "ab", serial_procs, 447cb93a386Sopenharmony_ci deserial_procs, reporter); 448cb93a386Sopenharmony_ci } 449cb93a386Sopenharmony_ci } 450cb93a386Sopenharmony_ci } 451cb93a386Sopenharmony_ci} 452cb93a386Sopenharmony_ci 453cb93a386Sopenharmony_cistatic void TestTypefaceSerialization(skiatest::Reporter* reporter, sk_sp<SkTypeface> typeface) { 454cb93a386Sopenharmony_ci SkDynamicMemoryWStream typefaceWStream; 455cb93a386Sopenharmony_ci typeface->serialize(&typefaceWStream); 456cb93a386Sopenharmony_ci 457cb93a386Sopenharmony_ci std::unique_ptr<SkStream> typefaceStream = typefaceWStream.detachAsStream(); 458cb93a386Sopenharmony_ci sk_sp<SkTypeface> cloneTypeface = SkTypeface::MakeDeserialize(typefaceStream.get()); 459cb93a386Sopenharmony_ci SkASSERT(cloneTypeface); 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_ci SkString name, cloneName; 462cb93a386Sopenharmony_ci typeface->getFamilyName(&name); 463cb93a386Sopenharmony_ci cloneTypeface->getFamilyName(&cloneName); 464cb93a386Sopenharmony_ci 465cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, typeface->countGlyphs() == cloneTypeface->countGlyphs(), 466cb93a386Sopenharmony_ci "Typeface: \"%s\" CloneTypeface: \"%s\"", name.c_str(), cloneName.c_str()); 467cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, typeface->fontStyle() == cloneTypeface->fontStyle(), 468cb93a386Sopenharmony_ci "Typeface: \"%s\" CloneTypeface: \"%s\"", name.c_str(), cloneName.c_str()); 469cb93a386Sopenharmony_ci 470cb93a386Sopenharmony_ci SkFont font(typeface, 12); 471cb93a386Sopenharmony_ci SkFont clone(cloneTypeface, 12); 472cb93a386Sopenharmony_ci SkFontMetrics fontMetrics, cloneMetrics; 473cb93a386Sopenharmony_ci font.getMetrics(&fontMetrics); 474cb93a386Sopenharmony_ci clone.getMetrics(&cloneMetrics); 475cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, fontMetrics == cloneMetrics, 476cb93a386Sopenharmony_ci "Typeface: \"%s\" CloneTypeface: \"%s\"", name.c_str(), cloneName.c_str()); 477cb93a386Sopenharmony_ci} 478cb93a386Sopenharmony_ci 479cb93a386Sopenharmony_ci#ifdef SKIA_COMPILE_DM_ALL 480cb93a386Sopenharmony_ciDEF_TEST(Serialization_Typeface, reporter) { 481cb93a386Sopenharmony_ci SkFont font; 482cb93a386Sopenharmony_ci TestTypefaceSerialization(reporter, font.refTypefaceOrDefault()); 483cb93a386Sopenharmony_ci TestTypefaceSerialization(reporter, ToolUtils::sample_user_typeface()); 484cb93a386Sopenharmony_ci} 485cb93a386Sopenharmony_ci#endif 486cb93a386Sopenharmony_ci 487cb93a386Sopenharmony_cistatic void setup_bitmap_for_canvas(SkBitmap* bitmap) { 488cb93a386Sopenharmony_ci bitmap->allocN32Pixels(kBitmapSize, kBitmapSize); 489cb93a386Sopenharmony_ci} 490cb93a386Sopenharmony_ci 491cb93a386Sopenharmony_cistatic sk_sp<SkImage> make_checkerboard_image() { 492cb93a386Sopenharmony_ci SkBitmap bitmap; 493cb93a386Sopenharmony_ci setup_bitmap_for_canvas(&bitmap); 494cb93a386Sopenharmony_ci 495cb93a386Sopenharmony_ci SkCanvas canvas(bitmap); 496cb93a386Sopenharmony_ci canvas.clear(0x00000000); 497cb93a386Sopenharmony_ci SkPaint darkPaint; 498cb93a386Sopenharmony_ci darkPaint.setColor(0xFF804020); 499cb93a386Sopenharmony_ci SkPaint lightPaint; 500cb93a386Sopenharmony_ci lightPaint.setColor(0xFF244484); 501cb93a386Sopenharmony_ci const int i = kBitmapSize / 8; 502cb93a386Sopenharmony_ci const SkScalar f = SkIntToScalar(i); 503cb93a386Sopenharmony_ci for (int y = 0; y < kBitmapSize; y += i) { 504cb93a386Sopenharmony_ci for (int x = 0; x < kBitmapSize; x += i) { 505cb93a386Sopenharmony_ci canvas.save(); 506cb93a386Sopenharmony_ci canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); 507cb93a386Sopenharmony_ci canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint); 508cb93a386Sopenharmony_ci canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint); 509cb93a386Sopenharmony_ci canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint); 510cb93a386Sopenharmony_ci canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint); 511cb93a386Sopenharmony_ci canvas.restore(); 512cb93a386Sopenharmony_ci } 513cb93a386Sopenharmony_ci } 514cb93a386Sopenharmony_ci return bitmap.asImage(); 515cb93a386Sopenharmony_ci} 516cb93a386Sopenharmony_ci 517cb93a386Sopenharmony_cistatic void draw_something(SkCanvas* canvas) { 518cb93a386Sopenharmony_ci canvas->save(); 519cb93a386Sopenharmony_ci canvas->scale(0.5f, 0.5f); 520cb93a386Sopenharmony_ci canvas->drawImage(make_checkerboard_image(), 0, 0); 521cb93a386Sopenharmony_ci canvas->restore(); 522cb93a386Sopenharmony_ci 523cb93a386Sopenharmony_ci SkPaint paint; 524cb93a386Sopenharmony_ci paint.setAntiAlias(true); 525cb93a386Sopenharmony_ci paint.setColor(SK_ColorRED); 526cb93a386Sopenharmony_ci canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint); 527cb93a386Sopenharmony_ci paint.setColor(SK_ColorBLACK); 528cb93a386Sopenharmony_ci 529cb93a386Sopenharmony_ci SkFont font; 530cb93a386Sopenharmony_ci font.setSize(kBitmapSize/3); 531cb93a386Sopenharmony_ci canvas->drawString("Picture", SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), font, paint); 532cb93a386Sopenharmony_ci} 533cb93a386Sopenharmony_ci 534cb93a386Sopenharmony_cistatic sk_sp<SkImage> render(const SkPicture& p) { 535cb93a386Sopenharmony_ci auto surf = SkSurface::MakeRasterN32Premul(SkScalarRoundToInt(p.cullRect().width()), 536cb93a386Sopenharmony_ci SkScalarRoundToInt(p.cullRect().height())); 537cb93a386Sopenharmony_ci if (!surf) { 538cb93a386Sopenharmony_ci return nullptr; // bounds are empty? 539cb93a386Sopenharmony_ci } 540cb93a386Sopenharmony_ci surf->getCanvas()->clear(SK_ColorWHITE); 541cb93a386Sopenharmony_ci p.playback(surf->getCanvas()); 542cb93a386Sopenharmony_ci return surf->makeImageSnapshot(); 543cb93a386Sopenharmony_ci} 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ciDEF_TEST(Serialization, reporter) { 546cb93a386Sopenharmony_ci // Test matrix serialization 547cb93a386Sopenharmony_ci { 548cb93a386Sopenharmony_ci SkMatrix matrix = SkMatrix::I(); 549cb93a386Sopenharmony_ci TestObjectSerialization(&matrix, reporter); 550cb93a386Sopenharmony_ci } 551cb93a386Sopenharmony_ci 552cb93a386Sopenharmony_ci // Test point3 serialization 553cb93a386Sopenharmony_ci { 554cb93a386Sopenharmony_ci SkPoint3 point; 555cb93a386Sopenharmony_ci TestObjectSerializationNoAlign<SkPoint3, false>(&point, reporter); 556cb93a386Sopenharmony_ci } 557cb93a386Sopenharmony_ci 558cb93a386Sopenharmony_ci // Test path serialization 559cb93a386Sopenharmony_ci { 560cb93a386Sopenharmony_ci SkPath path; 561cb93a386Sopenharmony_ci TestObjectSerialization(&path, reporter); 562cb93a386Sopenharmony_ci } 563cb93a386Sopenharmony_ci 564cb93a386Sopenharmony_ci // Test region serialization 565cb93a386Sopenharmony_ci { 566cb93a386Sopenharmony_ci SkRegion region; 567cb93a386Sopenharmony_ci TestObjectSerialization(®ion, reporter); 568cb93a386Sopenharmony_ci } 569cb93a386Sopenharmony_ci 570cb93a386Sopenharmony_ci // Test color filter serialization 571cb93a386Sopenharmony_ci { 572cb93a386Sopenharmony_ci TestColorFilterSerialization(reporter); 573cb93a386Sopenharmony_ci } 574cb93a386Sopenharmony_ci 575cb93a386Sopenharmony_ci // Test string serialization 576cb93a386Sopenharmony_ci { 577cb93a386Sopenharmony_ci SkString string("string"); 578cb93a386Sopenharmony_ci TestObjectSerializationNoAlign<SkString, false>(&string, reporter); 579cb93a386Sopenharmony_ci TestObjectSerializationNoAlign<SkString, true>(&string, reporter); 580cb93a386Sopenharmony_ci } 581cb93a386Sopenharmony_ci 582cb93a386Sopenharmony_ci // Test rrect serialization 583cb93a386Sopenharmony_ci { 584cb93a386Sopenharmony_ci // SkRRect does not initialize anything. 585cb93a386Sopenharmony_ci // An uninitialized SkRRect can be serialized, 586cb93a386Sopenharmony_ci // but will branch on uninitialized data when deserialized. 587cb93a386Sopenharmony_ci SkRRect rrect; 588cb93a386Sopenharmony_ci SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30); 589cb93a386Sopenharmony_ci SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} }; 590cb93a386Sopenharmony_ci rrect.setRectRadii(rect, corners); 591cb93a386Sopenharmony_ci SerializationTest::TestAlignment(&rrect, reporter); 592cb93a386Sopenharmony_ci } 593cb93a386Sopenharmony_ci 594cb93a386Sopenharmony_ci // Test readByteArray 595cb93a386Sopenharmony_ci { 596cb93a386Sopenharmony_ci unsigned char data[kArraySize] = { 1, 2, 3 }; 597cb93a386Sopenharmony_ci TestArraySerialization(data, reporter); 598cb93a386Sopenharmony_ci } 599cb93a386Sopenharmony_ci 600cb93a386Sopenharmony_ci // Test readColorArray 601cb93a386Sopenharmony_ci { 602cb93a386Sopenharmony_ci SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED }; 603cb93a386Sopenharmony_ci TestArraySerialization(data, reporter); 604cb93a386Sopenharmony_ci } 605cb93a386Sopenharmony_ci 606cb93a386Sopenharmony_ci // Test readColor4fArray 607cb93a386Sopenharmony_ci { 608cb93a386Sopenharmony_ci SkColor4f data[kArraySize] = { 609cb93a386Sopenharmony_ci SkColor4f::FromColor(SK_ColorBLACK), 610cb93a386Sopenharmony_ci SkColor4f::FromColor(SK_ColorWHITE), 611cb93a386Sopenharmony_ci SkColor4f::FromColor(SK_ColorRED), 612cb93a386Sopenharmony_ci { 1.f, 2.f, 4.f, 8.f } 613cb93a386Sopenharmony_ci }; 614cb93a386Sopenharmony_ci TestArraySerialization(data, reporter); 615cb93a386Sopenharmony_ci } 616cb93a386Sopenharmony_ci 617cb93a386Sopenharmony_ci // Test readIntArray 618cb93a386Sopenharmony_ci { 619cb93a386Sopenharmony_ci int32_t data[kArraySize] = { 1, 2, 4, 8 }; 620cb93a386Sopenharmony_ci TestArraySerialization(data, reporter); 621cb93a386Sopenharmony_ci } 622cb93a386Sopenharmony_ci 623cb93a386Sopenharmony_ci // Test readPointArray 624cb93a386Sopenharmony_ci { 625cb93a386Sopenharmony_ci SkPoint data[kArraySize] = { {6, 7}, {42, 128} }; 626cb93a386Sopenharmony_ci TestArraySerialization(data, reporter); 627cb93a386Sopenharmony_ci } 628cb93a386Sopenharmony_ci 629cb93a386Sopenharmony_ci // Test readScalarArray 630cb93a386Sopenharmony_ci { 631cb93a386Sopenharmony_ci SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax }; 632cb93a386Sopenharmony_ci TestArraySerialization(data, reporter); 633cb93a386Sopenharmony_ci } 634cb93a386Sopenharmony_ci 635cb93a386Sopenharmony_ci // Test skipByteArray 636cb93a386Sopenharmony_ci { 637cb93a386Sopenharmony_ci // Valid case with non-empty array: 638cb93a386Sopenharmony_ci { 639cb93a386Sopenharmony_ci unsigned char data[kArraySize] = { 1, 2, 3 }; 640cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 641cb93a386Sopenharmony_ci writer.writeByteArray(data, kArraySize); 642cb93a386Sopenharmony_ci SkAutoMalloc buf(writer.bytesWritten()); 643cb93a386Sopenharmony_ci writer.writeToMemory(buf.get()); 644cb93a386Sopenharmony_ci 645cb93a386Sopenharmony_ci SkReadBuffer reader(buf.get(), writer.bytesWritten()); 646cb93a386Sopenharmony_ci size_t len = ~0; 647cb93a386Sopenharmony_ci const void* arr = reader.skipByteArray(&len); 648cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, arr); 649cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, len == kArraySize); 650cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, memcmp(arr, data, len) == 0); 651cb93a386Sopenharmony_ci } 652cb93a386Sopenharmony_ci 653cb93a386Sopenharmony_ci // Writing a zero length array (can be detected as valid by non-nullptr return): 654cb93a386Sopenharmony_ci { 655cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 656cb93a386Sopenharmony_ci writer.writeByteArray(nullptr, 0); 657cb93a386Sopenharmony_ci SkAutoMalloc buf(writer.bytesWritten()); 658cb93a386Sopenharmony_ci writer.writeToMemory(buf.get()); 659cb93a386Sopenharmony_ci 660cb93a386Sopenharmony_ci SkReadBuffer reader(buf.get(), writer.bytesWritten()); 661cb93a386Sopenharmony_ci size_t len = ~0; 662cb93a386Sopenharmony_ci const void* arr = reader.skipByteArray(&len); 663cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, arr); 664cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, len == 0); 665cb93a386Sopenharmony_ci } 666cb93a386Sopenharmony_ci 667cb93a386Sopenharmony_ci // If the array can't be safely read, should return nullptr: 668cb93a386Sopenharmony_ci { 669cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 670cb93a386Sopenharmony_ci writer.writeUInt(kArraySize); 671cb93a386Sopenharmony_ci SkAutoMalloc buf(writer.bytesWritten()); 672cb93a386Sopenharmony_ci writer.writeToMemory(buf.get()); 673cb93a386Sopenharmony_ci 674cb93a386Sopenharmony_ci SkReadBuffer reader(buf.get(), writer.bytesWritten()); 675cb93a386Sopenharmony_ci size_t len = ~0; 676cb93a386Sopenharmony_ci const void* arr = reader.skipByteArray(&len); 677cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !arr); 678cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, len == 0); 679cb93a386Sopenharmony_ci } 680cb93a386Sopenharmony_ci } 681cb93a386Sopenharmony_ci 682cb93a386Sopenharmony_ci // Test invalid deserializations 683cb93a386Sopenharmony_ci { 684cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize); 685cb93a386Sopenharmony_ci 686cb93a386Sopenharmony_ci SkBitmap validBitmap; 687cb93a386Sopenharmony_ci validBitmap.setInfo(info); 688cb93a386Sopenharmony_ci 689cb93a386Sopenharmony_ci // Create a bitmap with a really large height 690cb93a386Sopenharmony_ci SkBitmap invalidBitmap; 691cb93a386Sopenharmony_ci invalidBitmap.setInfo(info.makeWH(info.width(), 1000000000)); 692cb93a386Sopenharmony_ci 693cb93a386Sopenharmony_ci // The deserialization should succeed, and the rendering shouldn't crash, 694cb93a386Sopenharmony_ci // even when the device fails to initialize, due to its size 695cb93a386Sopenharmony_ci TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); 696cb93a386Sopenharmony_ci } 697cb93a386Sopenharmony_ci 698cb93a386Sopenharmony_ci // Test simple SkPicture serialization 699cb93a386Sopenharmony_ci { 700cb93a386Sopenharmony_ci SkPictureRecorder recorder; 701cb93a386Sopenharmony_ci draw_something(recorder.beginRecording(SkIntToScalar(kBitmapSize), 702cb93a386Sopenharmony_ci SkIntToScalar(kBitmapSize))); 703cb93a386Sopenharmony_ci sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture()); 704cb93a386Sopenharmony_ci 705cb93a386Sopenharmony_ci // Serialize picture 706cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 707cb93a386Sopenharmony_ci SkPicturePriv::Flatten(pict, writer); 708cb93a386Sopenharmony_ci size_t size = writer.bytesWritten(); 709cb93a386Sopenharmony_ci SkAutoTMalloc<unsigned char> data(size); 710cb93a386Sopenharmony_ci writer.writeToMemory(static_cast<void*>(data.get())); 711cb93a386Sopenharmony_ci 712cb93a386Sopenharmony_ci // Deserialize picture 713cb93a386Sopenharmony_ci SkReadBuffer reader(static_cast<void*>(data.get()), size); 714cb93a386Sopenharmony_ci sk_sp<SkPicture> readPict(SkPicturePriv::MakeFromBuffer(reader)); 715cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, reader.isValid()); 716cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, readPict.get()); 717cb93a386Sopenharmony_ci sk_sp<SkImage> img0 = render(*pict); 718cb93a386Sopenharmony_ci sk_sp<SkImage> img1 = render(*readPict); 719cb93a386Sopenharmony_ci if (img0 && img1) { 720cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, ToolUtils::equal_pixels(img0.get(), img1.get())); 721cb93a386Sopenharmony_ci } 722cb93a386Sopenharmony_ci } 723cb93a386Sopenharmony_ci 724cb93a386Sopenharmony_ci TestPictureTypefaceSerialization(nullptr, nullptr, reporter); 725cb93a386Sopenharmony_ci 726cb93a386Sopenharmony_ci SkSerialProcs serial_procs; 727cb93a386Sopenharmony_ci serial_procs.fTypefaceProc = serialize_typeface_proc; 728cb93a386Sopenharmony_ci SkDeserialProcs deserial_procs; 729cb93a386Sopenharmony_ci deserial_procs.fTypefaceProc = deserialize_typeface_proc; 730cb93a386Sopenharmony_ci TestPictureTypefaceSerialization(&serial_procs, &deserial_procs, reporter); 731cb93a386Sopenharmony_ci} 732cb93a386Sopenharmony_ci 733cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 734cb93a386Sopenharmony_ci#include "include/core/SkAnnotation.h" 735cb93a386Sopenharmony_ci 736cb93a386Sopenharmony_cistatic sk_sp<SkPicture> copy_picture_via_serialization(SkPicture* src) { 737cb93a386Sopenharmony_ci SkDynamicMemoryWStream wstream; 738cb93a386Sopenharmony_ci src->serialize(&wstream); 739cb93a386Sopenharmony_ci std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream()); 740cb93a386Sopenharmony_ci return SkPicture::MakeFromStream(rstream.get()); 741cb93a386Sopenharmony_ci} 742cb93a386Sopenharmony_ci 743cb93a386Sopenharmony_cistruct AnnotationRec { 744cb93a386Sopenharmony_ci const SkRect fRect; 745cb93a386Sopenharmony_ci const char* fKey; 746cb93a386Sopenharmony_ci sk_sp<SkData> fValue; 747cb93a386Sopenharmony_ci}; 748cb93a386Sopenharmony_ci 749cb93a386Sopenharmony_ciclass TestAnnotationCanvas : public SkCanvas { 750cb93a386Sopenharmony_ci skiatest::Reporter* fReporter; 751cb93a386Sopenharmony_ci const AnnotationRec* fRec; 752cb93a386Sopenharmony_ci int fCount; 753cb93a386Sopenharmony_ci int fCurrIndex; 754cb93a386Sopenharmony_ci 755cb93a386Sopenharmony_cipublic: 756cb93a386Sopenharmony_ci TestAnnotationCanvas(skiatest::Reporter* reporter, const AnnotationRec rec[], int count) 757cb93a386Sopenharmony_ci : SkCanvas(100, 100) 758cb93a386Sopenharmony_ci , fReporter(reporter) 759cb93a386Sopenharmony_ci , fRec(rec) 760cb93a386Sopenharmony_ci , fCount(count) 761cb93a386Sopenharmony_ci , fCurrIndex(0) 762cb93a386Sopenharmony_ci {} 763cb93a386Sopenharmony_ci 764cb93a386Sopenharmony_ci ~TestAnnotationCanvas() override { 765cb93a386Sopenharmony_ci REPORTER_ASSERT(fReporter, fCount == fCurrIndex); 766cb93a386Sopenharmony_ci } 767cb93a386Sopenharmony_ci 768cb93a386Sopenharmony_ciprotected: 769cb93a386Sopenharmony_ci void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override { 770cb93a386Sopenharmony_ci REPORTER_ASSERT(fReporter, fCurrIndex < fCount); 771cb93a386Sopenharmony_ci REPORTER_ASSERT(fReporter, rect == fRec[fCurrIndex].fRect); 772cb93a386Sopenharmony_ci REPORTER_ASSERT(fReporter, !strcmp(key, fRec[fCurrIndex].fKey)); 773cb93a386Sopenharmony_ci REPORTER_ASSERT(fReporter, value->equals(fRec[fCurrIndex].fValue.get())); 774cb93a386Sopenharmony_ci fCurrIndex += 1; 775cb93a386Sopenharmony_ci } 776cb93a386Sopenharmony_ci}; 777cb93a386Sopenharmony_ci 778cb93a386Sopenharmony_ci/* 779cb93a386Sopenharmony_ci * Test the 3 annotation types by recording them into a picture, serializing, and then playing 780cb93a386Sopenharmony_ci * them back into another canvas. 781cb93a386Sopenharmony_ci */ 782cb93a386Sopenharmony_ciDEF_TEST(Annotations, reporter) { 783cb93a386Sopenharmony_ci SkPictureRecorder recorder; 784cb93a386Sopenharmony_ci SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(100, 100)); 785cb93a386Sopenharmony_ci 786cb93a386Sopenharmony_ci const char* str0 = "rect-with-url"; 787cb93a386Sopenharmony_ci const SkRect r0 = SkRect::MakeWH(10, 10); 788cb93a386Sopenharmony_ci sk_sp<SkData> d0(SkData::MakeWithCString(str0)); 789cb93a386Sopenharmony_ci SkAnnotateRectWithURL(recordingCanvas, r0, d0.get()); 790cb93a386Sopenharmony_ci 791cb93a386Sopenharmony_ci const char* str1 = "named-destination"; 792cb93a386Sopenharmony_ci const SkRect r1 = SkRect::MakeXYWH(5, 5, 0, 0); // collapsed to a point 793cb93a386Sopenharmony_ci sk_sp<SkData> d1(SkData::MakeWithCString(str1)); 794cb93a386Sopenharmony_ci SkAnnotateNamedDestination(recordingCanvas, {r1.x(), r1.y()}, d1.get()); 795cb93a386Sopenharmony_ci 796cb93a386Sopenharmony_ci const char* str2 = "link-to-destination"; 797cb93a386Sopenharmony_ci const SkRect r2 = SkRect::MakeXYWH(20, 20, 5, 6); 798cb93a386Sopenharmony_ci sk_sp<SkData> d2(SkData::MakeWithCString(str2)); 799cb93a386Sopenharmony_ci SkAnnotateLinkToDestination(recordingCanvas, r2, d2.get()); 800cb93a386Sopenharmony_ci 801cb93a386Sopenharmony_ci const AnnotationRec recs[] = { 802cb93a386Sopenharmony_ci { r0, SkAnnotationKeys::URL_Key(), std::move(d0) }, 803cb93a386Sopenharmony_ci { r1, SkAnnotationKeys::Define_Named_Dest_Key(), std::move(d1) }, 804cb93a386Sopenharmony_ci { r2, SkAnnotationKeys::Link_Named_Dest_Key(), std::move(d2) }, 805cb93a386Sopenharmony_ci }; 806cb93a386Sopenharmony_ci 807cb93a386Sopenharmony_ci sk_sp<SkPicture> pict0(recorder.finishRecordingAsPicture()); 808cb93a386Sopenharmony_ci sk_sp<SkPicture> pict1(copy_picture_via_serialization(pict0.get())); 809cb93a386Sopenharmony_ci 810cb93a386Sopenharmony_ci TestAnnotationCanvas canvas(reporter, recs, SK_ARRAY_COUNT(recs)); 811cb93a386Sopenharmony_ci canvas.drawPicture(pict1); 812cb93a386Sopenharmony_ci} 813cb93a386Sopenharmony_ci 814cb93a386Sopenharmony_ciDEF_TEST(WriteBuffer_storage, reporter) { 815cb93a386Sopenharmony_ci enum { 816cb93a386Sopenharmony_ci kSize = 32 817cb93a386Sopenharmony_ci }; 818cb93a386Sopenharmony_ci int32_t storage[kSize/4]; 819cb93a386Sopenharmony_ci char src[kSize]; 820cb93a386Sopenharmony_ci sk_bzero(src, kSize); 821cb93a386Sopenharmony_ci 822cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer(storage, kSize); 823cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.usingInitialStorage()); 824cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.bytesWritten() == 0); 825cb93a386Sopenharmony_ci writer.write(src, kSize - 4); 826cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.usingInitialStorage()); 827cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize - 4); 828cb93a386Sopenharmony_ci writer.writeInt(0); 829cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.usingInitialStorage()); 830cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize); 831cb93a386Sopenharmony_ci 832cb93a386Sopenharmony_ci writer.reset(storage, kSize-4); 833cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.usingInitialStorage()); 834cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.bytesWritten() == 0); 835cb93a386Sopenharmony_ci writer.write(src, kSize - 4); 836cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.usingInitialStorage()); 837cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize - 4); 838cb93a386Sopenharmony_ci writer.writeInt(0); 839cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !writer.usingInitialStorage()); // this is the change 840cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize); 841cb93a386Sopenharmony_ci} 842cb93a386Sopenharmony_ci 843cb93a386Sopenharmony_ciDEF_TEST(WriteBuffer_external_memory_textblob, reporter) { 844cb93a386Sopenharmony_ci SkFont font; 845cb93a386Sopenharmony_ci font.setTypeface(SkTypeface::MakeDefault()); 846cb93a386Sopenharmony_ci 847cb93a386Sopenharmony_ci SkTextBlobBuilder builder; 848cb93a386Sopenharmony_ci int glyph_count = 5; 849cb93a386Sopenharmony_ci const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f); 850cb93a386Sopenharmony_ci // allocRun() allocates only the glyph buffer. 851cb93a386Sopenharmony_ci std::fill(run.glyphs, run.glyphs + glyph_count, 0); 852cb93a386Sopenharmony_ci auto blob = builder.make(); 853cb93a386Sopenharmony_ci SkSerialProcs procs; 854cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> storage; 855cb93a386Sopenharmony_ci size_t blob_size = 0u; 856cb93a386Sopenharmony_ci size_t storage_size = 0u; 857cb93a386Sopenharmony_ci 858cb93a386Sopenharmony_ci blob_size = SkAlign4(blob->serialize(procs)->size()); 859cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, blob_size > 4u); 860cb93a386Sopenharmony_ci storage_size = blob_size - 4; 861cb93a386Sopenharmony_ci storage.realloc(storage_size); 862cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, blob->serialize(procs, storage.get(), storage_size) == 0u); 863cb93a386Sopenharmony_ci storage_size = blob_size; 864cb93a386Sopenharmony_ci storage.realloc(storage_size); 865cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, blob->serialize(procs, storage.get(), storage_size) != 0u); 866cb93a386Sopenharmony_ci} 867cb93a386Sopenharmony_ci 868cb93a386Sopenharmony_ciDEF_TEST(WriteBuffer_external_memory_flattenable, reporter) { 869cb93a386Sopenharmony_ci SkScalar intervals[] = {1.f, 1.f}; 870cb93a386Sopenharmony_ci auto path_effect = SkDashPathEffect::Make(intervals, 2, 0); 871cb93a386Sopenharmony_ci size_t path_size = SkAlign4(path_effect->serialize()->size()); 872cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path_size > 4u); 873cb93a386Sopenharmony_ci SkAutoTMalloc<uint8_t> storage; 874cb93a386Sopenharmony_ci 875cb93a386Sopenharmony_ci size_t storage_size = path_size - 4; 876cb93a386Sopenharmony_ci storage.realloc(storage_size); 877cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path_effect->serialize(storage.get(), storage_size) == 0u); 878cb93a386Sopenharmony_ci 879cb93a386Sopenharmony_ci storage_size = path_size; 880cb93a386Sopenharmony_ci storage.realloc(storage_size); 881cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, path_effect->serialize(storage.get(), storage_size) != 0u); 882cb93a386Sopenharmony_ci} 883cb93a386Sopenharmony_ci 884cb93a386Sopenharmony_ciDEF_TEST(ReadBuffer_empty, reporter) { 885cb93a386Sopenharmony_ci SkBinaryWriteBuffer writer; 886cb93a386Sopenharmony_ci writer.writeInt(123); 887cb93a386Sopenharmony_ci writer.writeDataAsByteArray(SkData::MakeEmpty().get()); 888cb93a386Sopenharmony_ci writer.writeInt(321); 889cb93a386Sopenharmony_ci 890cb93a386Sopenharmony_ci size_t size = writer.bytesWritten(); 891cb93a386Sopenharmony_ci SkAutoMalloc storage(size); 892cb93a386Sopenharmony_ci writer.writeToMemory(storage.get()); 893cb93a386Sopenharmony_ci 894cb93a386Sopenharmony_ci SkReadBuffer reader(storage.get(), size); 895cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, reader.readInt() == 123); 896cb93a386Sopenharmony_ci auto data = reader.readByteArrayAsData(); 897cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, data->size() == 0); 898cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, reader.readInt() == 321); 899cb93a386Sopenharmony_ci} 900