1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "Resources.h" 9 #include "SkAnnotationKeys.h" 10 #include "SkCanvas.h" 11 #include "SkFixed.h" 12 #include "SkFontDescriptor.h" 13 #include "SkImage.h" 14 #include "SkImageSource.h" 15 #include "SkLightingShader.h" 16 #include "SkMakeUnique.h" 17 #include "SkMallocPixelRef.h" 18 #include "SkNormalSource.h" 19 #include "SkOSFile.h" 20 #include "SkPictureRecorder.h" 21 #include "SkTableColorFilter.h" 22 #include "SkTemplates.h" 23 #include "SkTypeface.h" 24 #include "SkWriteBuffer.h" 25 #include "SkValidatingReadBuffer.h" 26 #include "SkXfermodeImageFilter.h" 27 #include "sk_tool_utils.h" 28 #include "Test.h" 29 30 static const uint32_t kArraySize = 64; 31 static const int kBitmapSize = 256; 32 33 template<typename T> 34 static void TestAlignment(T* testObj, skiatest::Reporter* reporter) { 35 // Test memory read/write functions directly 36 unsigned char dataWritten[1024]; 37 size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten); 38 REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory); 39 size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory); 40 REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory); 41 } 42 43 template<typename T> struct SerializationUtils { 44 // Generic case for flattenables 45 static void Write(SkWriteBuffer& writer, const T* flattenable) { 46 writer.writeFlattenable(flattenable); 47 } 48 static void Read(SkValidatingReadBuffer& reader, T** flattenable) { 49 *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType()); 50 } 51 }; 52 53 template<> struct SerializationUtils<SkMatrix> { 54 static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) { 55 writer.writeMatrix(*matrix); 56 } 57 static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) { 58 reader.readMatrix(matrix); 59 } 60 }; 61 62 template<> struct SerializationUtils<SkPath> { 63 static void Write(SkWriteBuffer& writer, const SkPath* path) { 64 writer.writePath(*path); 65 } 66 static void Read(SkValidatingReadBuffer& reader, SkPath* path) { 67 reader.readPath(path); 68 } 69 }; 70 71 template<> struct SerializationUtils<SkRegion> { 72 static void Write(SkWriteBuffer& writer, const SkRegion* region) { 73 writer.writeRegion(*region); 74 } 75 static void Read(SkValidatingReadBuffer& reader, SkRegion* region) { 76 reader.readRegion(region); 77 } 78 }; 79 80 template<> struct SerializationUtils<SkString> { 81 static void Write(SkWriteBuffer& writer, const SkString* string) { 82 writer.writeString(string->c_str()); 83 } 84 static void Read(SkValidatingReadBuffer& reader, SkString* string) { 85 reader.readString(string); 86 } 87 }; 88 89 template<> struct SerializationUtils<unsigned char> { 90 static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) { 91 writer.writeByteArray(data, arraySize); 92 } 93 static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) { 94 return reader.readByteArray(data, arraySize); 95 } 96 }; 97 98 template<> struct SerializationUtils<SkColor> { 99 static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) { 100 writer.writeColorArray(data, arraySize); 101 } 102 static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) { 103 return reader.readColorArray(data, arraySize); 104 } 105 }; 106 107 template<> struct SerializationUtils<SkColor4f> { 108 static void Write(SkWriteBuffer& writer, SkColor4f* data, uint32_t arraySize) { 109 writer.writeColor4fArray(data, arraySize); 110 } 111 static bool Read(SkValidatingReadBuffer& reader, SkColor4f* data, uint32_t arraySize) { 112 return reader.readColor4fArray(data, arraySize); 113 } 114 }; 115 116 template<> struct SerializationUtils<int32_t> { 117 static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) { 118 writer.writeIntArray(data, arraySize); 119 } 120 static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) { 121 return reader.readIntArray(data, arraySize); 122 } 123 }; 124 125 template<> struct SerializationUtils<SkPoint> { 126 static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) { 127 writer.writePointArray(data, arraySize); 128 } 129 static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) { 130 return reader.readPointArray(data, arraySize); 131 } 132 }; 133 134 template<> struct SerializationUtils<SkScalar> { 135 static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) { 136 writer.writeScalarArray(data, arraySize); 137 } 138 static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) { 139 return reader.readScalarArray(data, arraySize); 140 } 141 }; 142 143 template<typename T, bool testInvalid> struct SerializationTestUtils { 144 static void InvalidateData(unsigned char* data) {} 145 }; 146 147 template<> struct SerializationTestUtils<SkString, true> { 148 static void InvalidateData(unsigned char* data) { 149 data[3] |= 0x80; // Reverse sign of 1st integer 150 } 151 }; 152 153 template<typename T, bool testInvalid> 154 static void TestObjectSerializationNoAlign(T* testObj, skiatest::Reporter* reporter) { 155 SkBinaryWriteBuffer writer; 156 SerializationUtils<T>::Write(writer, testObj); 157 size_t bytesWritten = writer.bytesWritten(); 158 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 159 160 unsigned char dataWritten[1024]; 161 writer.writeToMemory(dataWritten); 162 163 SerializationTestUtils<T, testInvalid>::InvalidateData(dataWritten); 164 165 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 166 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 167 T obj; 168 SerializationUtils<T>::Read(buffer, &obj); 169 REPORTER_ASSERT(reporter, !buffer.isValid()); 170 171 // Make sure this succeeds when it should 172 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 173 size_t offsetBefore = buffer2.offset(); 174 T obj2; 175 SerializationUtils<T>::Read(buffer2, &obj2); 176 size_t offsetAfter = buffer2.offset(); 177 // This should have succeeded, since there are enough bytes to read this 178 REPORTER_ASSERT(reporter, buffer2.isValid() == !testInvalid); 179 // Note: This following test should always succeed, regardless of whether the buffer is valid, 180 // since if it is invalid, it will simply skip to the end, as if it had read the whole buffer. 181 REPORTER_ASSERT(reporter, offsetAfter - offsetBefore == bytesWritten); 182 } 183 184 template<typename T> 185 static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { 186 TestObjectSerializationNoAlign<T, false>(testObj, reporter); 187 TestAlignment(testObj, reporter); 188 } 189 190 template<typename T> 191 static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed, 192 skiatest::Reporter* reporter) { 193 SkBinaryWriteBuffer writer; 194 SerializationUtils<T>::Write(writer, testObj); 195 size_t bytesWritten = writer.bytesWritten(); 196 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 197 198 SkASSERT(bytesWritten <= 4096); 199 unsigned char dataWritten[4096]; 200 writer.writeToMemory(dataWritten); 201 202 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 203 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 204 T* obj = nullptr; 205 SerializationUtils<T>::Read(buffer, &obj); 206 REPORTER_ASSERT(reporter, !buffer.isValid()); 207 REPORTER_ASSERT(reporter, nullptr == obj); 208 209 // Make sure this succeeds when it should 210 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 211 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 212 T* obj2 = nullptr; 213 SerializationUtils<T>::Read(buffer2, &obj2); 214 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 215 if (shouldSucceed) { 216 // This should have succeeded, since there are enough bytes to read this 217 REPORTER_ASSERT(reporter, buffer2.isValid()); 218 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 219 REPORTER_ASSERT(reporter, obj2); 220 } else { 221 // If the deserialization was supposed to fail, make sure it did 222 REPORTER_ASSERT(reporter, !buffer.isValid()); 223 REPORTER_ASSERT(reporter, nullptr == obj2); 224 } 225 226 return obj2; // Return object to perform further validity tests on it 227 } 228 229 template<typename T> 230 static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { 231 SkBinaryWriteBuffer writer; 232 SerializationUtils<T>::Write(writer, data, kArraySize); 233 size_t bytesWritten = writer.bytesWritten(); 234 // This should write the length (in 4 bytes) and the array 235 REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten); 236 237 unsigned char dataWritten[2048]; 238 writer.writeToMemory(dataWritten); 239 240 // Make sure this fails when it should 241 SkValidatingReadBuffer buffer(dataWritten, bytesWritten); 242 T dataRead[kArraySize]; 243 bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2); 244 // This should have failed, since the provided size was too small 245 REPORTER_ASSERT(reporter, !success); 246 247 // Make sure this succeeds when it should 248 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 249 success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize); 250 // This should have succeeded, since there are enough bytes to read this 251 REPORTER_ASSERT(reporter, success); 252 } 253 254 static void TestBitmapSerialization(const SkBitmap& validBitmap, 255 const SkBitmap& invalidBitmap, 256 bool shouldSucceed, 257 skiatest::Reporter* reporter) { 258 sk_sp<SkImage> validImage(SkImage::MakeFromBitmap(validBitmap)); 259 sk_sp<SkImageFilter> validBitmapSource(SkImageSource::Make(std::move(validImage))); 260 sk_sp<SkImage> invalidImage(SkImage::MakeFromBitmap(invalidBitmap)); 261 sk_sp<SkImageFilter> invalidBitmapSource(SkImageSource::Make(std::move(invalidImage))); 262 sk_sp<SkImageFilter> xfermodeImageFilter( 263 SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver, 264 std::move(invalidBitmapSource), 265 std::move(validBitmapSource), nullptr)); 266 267 sk_sp<SkImageFilter> deserializedFilter( 268 TestFlattenableSerialization<SkImageFilter>( 269 xfermodeImageFilter.get(), shouldSucceed, reporter)); 270 271 // Try to render a small bitmap using the invalid deserialized filter 272 // to make sure we don't crash while trying to render it 273 if (shouldSucceed) { 274 SkBitmap bitmap; 275 bitmap.allocN32Pixels(24, 24); 276 SkCanvas canvas(bitmap); 277 canvas.clear(0x00000000); 278 SkPaint paint; 279 paint.setImageFilter(deserializedFilter); 280 canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24))); 281 canvas.drawBitmap(bitmap, 0, 0, &paint); 282 } 283 } 284 285 static void TestXfermodeSerialization(skiatest::Reporter* reporter) { 286 for (size_t i = 0; i <= SkXfermode::kLastMode; ++i) { 287 if (i == SkXfermode::kSrcOver_Mode) { 288 // skip SrcOver, as it is allowed to return nullptr from Create() 289 continue; 290 } 291 auto mode(SkXfermode::Make(static_cast<SkXfermode::Mode>(i))); 292 REPORTER_ASSERT(reporter, mode); 293 sk_sp<SkXfermode> copy( 294 TestFlattenableSerialization<SkXfermode>(mode.get(), true, reporter)); 295 } 296 } 297 298 static void TestColorFilterSerialization(skiatest::Reporter* reporter) { 299 uint8_t table[256]; 300 for (int i = 0; i < 256; ++i) { 301 table[i] = (i * 41) % 256; 302 } 303 auto colorFilter(SkTableColorFilter::Make(table)); 304 sk_sp<SkColorFilter> copy( 305 TestFlattenableSerialization<SkColorFilter>(colorFilter.get(), true, reporter)); 306 } 307 308 static SkBitmap draw_picture(SkPicture& picture) { 309 SkBitmap bitmap; 310 bitmap.allocN32Pixels(SkScalarCeilToInt(picture.cullRect().width()), 311 SkScalarCeilToInt(picture.cullRect().height())); 312 SkCanvas canvas(bitmap); 313 picture.playback(&canvas); 314 return bitmap; 315 } 316 317 static void compare_bitmaps(skiatest::Reporter* reporter, 318 const SkBitmap& b1, const SkBitmap& b2) { 319 REPORTER_ASSERT(reporter, b1.width() == b2.width()); 320 REPORTER_ASSERT(reporter, b1.height() == b2.height()); 321 SkAutoLockPixels autoLockPixels1(b1); 322 SkAutoLockPixels autoLockPixels2(b2); 323 324 if ((b1.width() != b2.width()) || 325 (b1.height() != b2.height())) { 326 return; 327 } 328 329 int pixelErrors = 0; 330 for (int y = 0; y < b2.height(); ++y) { 331 for (int x = 0; x < b2.width(); ++x) { 332 if (b1.getColor(x, y) != b2.getColor(x, y)) 333 ++pixelErrors; 334 } 335 } 336 REPORTER_ASSERT(reporter, 0 == pixelErrors); 337 } 338 static void serialize_and_compare_typeface(sk_sp<SkTypeface> typeface, const char* text, 339 skiatest::Reporter* reporter) 340 { 341 // Create a paint with the typeface. 342 SkPaint paint; 343 paint.setColor(SK_ColorGRAY); 344 paint.setTextSize(SkIntToScalar(30)); 345 paint.setTypeface(std::move(typeface)); 346 347 // Paint some text. 348 SkPictureRecorder recorder; 349 SkIRect canvasRect = SkIRect::MakeWH(kBitmapSize, kBitmapSize); 350 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(canvasRect.width()), 351 SkIntToScalar(canvasRect.height()), 352 nullptr, 0); 353 canvas->drawColor(SK_ColorWHITE); 354 canvas->drawText(text, 2, 24, 32, paint); 355 sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); 356 357 // Serlialize picture and create its clone from stream. 358 SkDynamicMemoryWStream stream; 359 picture->serialize(&stream); 360 std::unique_ptr<SkStream> inputStream(stream.detachAsStream()); 361 sk_sp<SkPicture> loadedPicture(SkPicture::MakeFromStream(inputStream.get())); 362 363 // Draw both original and clone picture and compare bitmaps -- they should be identical. 364 SkBitmap origBitmap = draw_picture(*picture); 365 SkBitmap destBitmap = draw_picture(*loadedPicture); 366 compare_bitmaps(reporter, origBitmap, destBitmap); 367 } 368 369 static void TestPictureTypefaceSerialization(skiatest::Reporter* reporter) { 370 { 371 // Load typeface from file to test CreateFromFile with index. 372 SkString filename = GetResourcePath("/fonts/test.ttc"); 373 sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFile(filename.c_str(), 1)); 374 if (!typeface) { 375 INFOF(reporter, "Could not run fontstream test because test.ttc not found."); 376 } else { 377 serialize_and_compare_typeface(std::move(typeface), "A!", reporter); 378 } 379 } 380 381 { 382 // Load typeface as stream to create with axis settings. 383 std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("/fonts/Distortable.ttf")); 384 if (!distortable) { 385 INFOF(reporter, "Could not run fontstream test because Distortable.ttf not found."); 386 } else { 387 SkFixed axis = SK_FixedSqrt2; 388 sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData( 389 skstd::make_unique<SkFontData>(std::move(distortable), 0, &axis, 1))); 390 if (!typeface) { 391 INFOF(reporter, "Could not run fontstream test because Distortable.ttf not created."); 392 } else { 393 serialize_and_compare_typeface(std::move(typeface), "abc", reporter); 394 } 395 } 396 } 397 } 398 399 static void setup_bitmap_for_canvas(SkBitmap* bitmap) { 400 bitmap->allocN32Pixels(kBitmapSize, kBitmapSize); 401 } 402 403 static void make_checkerboard_bitmap(SkBitmap& bitmap) { 404 setup_bitmap_for_canvas(&bitmap); 405 406 SkCanvas canvas(bitmap); 407 canvas.clear(0x00000000); 408 SkPaint darkPaint; 409 darkPaint.setColor(0xFF804020); 410 SkPaint lightPaint; 411 lightPaint.setColor(0xFF244484); 412 const int i = kBitmapSize / 8; 413 const SkScalar f = SkIntToScalar(i); 414 for (int y = 0; y < kBitmapSize; y += i) { 415 for (int x = 0; x < kBitmapSize; x += i) { 416 canvas.save(); 417 canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); 418 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint); 419 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint); 420 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint); 421 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint); 422 canvas.restore(); 423 } 424 } 425 } 426 427 static void draw_something(SkCanvas* canvas) { 428 SkPaint paint; 429 SkBitmap bitmap; 430 make_checkerboard_bitmap(bitmap); 431 432 canvas->save(); 433 canvas->scale(0.5f, 0.5f); 434 canvas->drawBitmap(bitmap, 0, 0, nullptr); 435 canvas->restore(); 436 437 paint.setAntiAlias(true); 438 439 paint.setColor(SK_ColorRED); 440 canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint); 441 paint.setColor(SK_ColorBLACK); 442 paint.setTextSize(SkIntToScalar(kBitmapSize/3)); 443 canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint); 444 } 445 446 DEF_TEST(Serialization, reporter) { 447 // Test matrix serialization 448 { 449 SkMatrix matrix = SkMatrix::I(); 450 TestObjectSerialization(&matrix, reporter); 451 } 452 453 // Test path serialization 454 { 455 SkPath path; 456 TestObjectSerialization(&path, reporter); 457 } 458 459 // Test region serialization 460 { 461 SkRegion region; 462 TestObjectSerialization(®ion, reporter); 463 } 464 465 // Test xfermode serialization 466 { 467 TestXfermodeSerialization(reporter); 468 } 469 470 // Test color filter serialization 471 { 472 TestColorFilterSerialization(reporter); 473 } 474 475 // Test string serialization 476 { 477 SkString string("string"); 478 TestObjectSerializationNoAlign<SkString, false>(&string, reporter); 479 TestObjectSerializationNoAlign<SkString, true>(&string, reporter); 480 } 481 482 // Test rrect serialization 483 { 484 // SkRRect does not initialize anything. 485 // An uninitialized SkRRect can be serialized, 486 // but will branch on uninitialized data when deserialized. 487 SkRRect rrect; 488 SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30); 489 SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} }; 490 rrect.setRectRadii(rect, corners); 491 TestAlignment(&rrect, reporter); 492 } 493 494 // Test readByteArray 495 { 496 unsigned char data[kArraySize] = { 1, 2, 3 }; 497 TestArraySerialization(data, reporter); 498 } 499 500 // Test readColorArray 501 { 502 SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED }; 503 TestArraySerialization(data, reporter); 504 } 505 506 // Test readColor4fArray 507 { 508 SkColor4f data[kArraySize] = { 509 SkColor4f::FromColor(SK_ColorBLACK), 510 SkColor4f::FromColor(SK_ColorWHITE), 511 SkColor4f::FromColor(SK_ColorRED), 512 { 1.f, 2.f, 4.f, 8.f } 513 }; 514 TestArraySerialization(data, reporter); 515 } 516 517 // Test readIntArray 518 { 519 int32_t data[kArraySize] = { 1, 2, 4, 8 }; 520 TestArraySerialization(data, reporter); 521 } 522 523 // Test readPointArray 524 { 525 SkPoint data[kArraySize] = { {6, 7}, {42, 128} }; 526 TestArraySerialization(data, reporter); 527 } 528 529 // Test readScalarArray 530 { 531 SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax }; 532 TestArraySerialization(data, reporter); 533 } 534 535 // Test invalid deserializations 536 { 537 SkImageInfo info = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize); 538 539 SkBitmap validBitmap; 540 validBitmap.setInfo(info); 541 542 // Create a bitmap with a really large height 543 SkBitmap invalidBitmap; 544 invalidBitmap.setInfo(info.makeWH(info.width(), 1000000000)); 545 546 // The deserialization should succeed, and the rendering shouldn't crash, 547 // even when the device fails to initialize, due to its size 548 TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); 549 } 550 551 // Test simple SkPicture serialization 552 { 553 SkPictureRecorder recorder; 554 draw_something(recorder.beginRecording(SkIntToScalar(kBitmapSize), 555 SkIntToScalar(kBitmapSize), 556 nullptr, 0)); 557 sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture()); 558 559 // Serialize picture 560 SkBinaryWriteBuffer writer; 561 pict->flatten(writer); 562 size_t size = writer.bytesWritten(); 563 SkAutoTMalloc<unsigned char> data(size); 564 writer.writeToMemory(static_cast<void*>(data.get())); 565 566 // Deserialize picture 567 SkValidatingReadBuffer reader(static_cast<void*>(data.get()), size); 568 sk_sp<SkPicture> readPict(SkPicture::MakeFromBuffer(reader)); 569 REPORTER_ASSERT(reporter, reader.isValid()); 570 REPORTER_ASSERT(reporter, readPict.get()); 571 } 572 573 TestPictureTypefaceSerialization(reporter); 574 575 // Test SkLightingShader/NormalMapSource serialization 576 { 577 const int kTexSize = 2; 578 579 SkLights::Builder builder; 580 581 builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f), 582 SkVector3::Make(1.0f, 0.0f, 0.0f))); 583 builder.setAmbientLightColor(SkColor3f::Make(0.2f, 0.2f, 0.2f)); 584 585 sk_sp<SkLights> fLights = builder.finish(); 586 587 SkBitmap diffuse = sk_tool_utils::create_checkerboard_bitmap( 588 kTexSize, kTexSize, 589 sk_tool_utils::color_to_565(0x0), 590 sk_tool_utils::color_to_565(0xFF804020), 591 8); 592 593 SkRect bitmapBounds = SkRect::MakeIWH(diffuse.width(), diffuse.height()); 594 595 SkMatrix matrix; 596 SkRect r = SkRect::MakeWH(SkIntToScalar(kTexSize), SkIntToScalar(kTexSize)); 597 matrix.setRectToRect(bitmapBounds, r, SkMatrix::kFill_ScaleToFit); 598 599 SkMatrix ctm; 600 ctm.setRotate(45); 601 SkBitmap normals; 602 normals.allocN32Pixels(kTexSize, kTexSize); 603 604 sk_tool_utils::create_frustum_normal_map(&normals, SkIRect::MakeWH(kTexSize, kTexSize)); 605 sk_sp<SkShader> normalMap = SkShader::MakeBitmapShader(normals, SkShader::kClamp_TileMode, 606 SkShader::kClamp_TileMode, &matrix); 607 sk_sp<SkNormalSource> normalSource = SkNormalSource::MakeFromNormalMap(std::move(normalMap), 608 ctm); 609 sk_sp<SkShader> diffuseShader = SkShader::MakeBitmapShader(diffuse, 610 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &matrix); 611 612 sk_sp<SkShader> lightingShader = SkLightingShader::Make(diffuseShader, 613 normalSource, 614 fLights); 615 sk_sp<SkShader>(TestFlattenableSerialization(lightingShader.get(), true, reporter)); 616 617 lightingShader = SkLightingShader::Make(std::move(diffuseShader), 618 nullptr, 619 fLights); 620 sk_sp<SkShader>(TestFlattenableSerialization(lightingShader.get(), true, reporter)); 621 622 lightingShader = SkLightingShader::Make(nullptr, 623 std::move(normalSource), 624 fLights); 625 sk_sp<SkShader>(TestFlattenableSerialization(lightingShader.get(), true, reporter)); 626 627 lightingShader = SkLightingShader::Make(nullptr, 628 nullptr, 629 fLights); 630 sk_sp<SkShader>(TestFlattenableSerialization(lightingShader.get(), true, reporter)); 631 } 632 633 // Test NormalBevelSource serialization 634 { 635 sk_sp<SkNormalSource> bevelSource = SkNormalSource::MakeBevel( 636 SkNormalSource::BevelType::kLinear, 2.0f, 5.0f); 637 638 sk_sp<SkNormalSource>(TestFlattenableSerialization(bevelSource.get(), true, reporter)); 639 // TODO test equality? 640 641 } 642 } 643 644 /////////////////////////////////////////////////////////////////////////////////////////////////// 645 #include "SkAnnotation.h" 646 647 static sk_sp<SkPicture> copy_picture_via_serialization(SkPicture* src) { 648 SkDynamicMemoryWStream wstream; 649 src->serialize(&wstream); 650 std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream()); 651 return SkPicture::MakeFromStream(rstream.get()); 652 } 653 654 struct AnnotationRec { 655 const SkRect fRect; 656 const char* fKey; 657 sk_sp<SkData> fValue; 658 }; 659 660 class TestAnnotationCanvas : public SkCanvas { 661 skiatest::Reporter* fReporter; 662 const AnnotationRec* fRec; 663 int fCount; 664 int fCurrIndex; 665 666 public: 667 TestAnnotationCanvas(skiatest::Reporter* reporter, const AnnotationRec rec[], int count) 668 : SkCanvas(100, 100) 669 , fReporter(reporter) 670 , fRec(rec) 671 , fCount(count) 672 , fCurrIndex(0) 673 {} 674 675 ~TestAnnotationCanvas() { 676 REPORTER_ASSERT(fReporter, fCount == fCurrIndex); 677 } 678 679 protected: 680 void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { 681 REPORTER_ASSERT(fReporter, fCurrIndex < fCount); 682 REPORTER_ASSERT(fReporter, rect == fRec[fCurrIndex].fRect); 683 REPORTER_ASSERT(fReporter, !strcmp(key, fRec[fCurrIndex].fKey)); 684 REPORTER_ASSERT(fReporter, value->equals(fRec[fCurrIndex].fValue.get())); 685 fCurrIndex += 1; 686 } 687 }; 688 689 /* 690 * Test the 3 annotation types by recording them into a picture, serializing, and then playing 691 * them back into another canvas. 692 */ 693 DEF_TEST(Annotations, reporter) { 694 SkPictureRecorder recorder; 695 SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(100, 100)); 696 697 const char* str0 = "rect-with-url"; 698 const SkRect r0 = SkRect::MakeWH(10, 10); 699 sk_sp<SkData> d0(SkData::MakeWithCString(str0)); 700 SkAnnotateRectWithURL(recordingCanvas, r0, d0.get()); 701 702 const char* str1 = "named-destination"; 703 const SkRect r1 = SkRect::MakeXYWH(5, 5, 0, 0); // collapsed to a point 704 sk_sp<SkData> d1(SkData::MakeWithCString(str1)); 705 SkAnnotateNamedDestination(recordingCanvas, {r1.x(), r1.y()}, d1.get()); 706 707 const char* str2 = "link-to-destination"; 708 const SkRect r2 = SkRect::MakeXYWH(20, 20, 5, 6); 709 sk_sp<SkData> d2(SkData::MakeWithCString(str2)); 710 SkAnnotateLinkToDestination(recordingCanvas, r2, d2.get()); 711 712 const AnnotationRec recs[] = { 713 { r0, SkAnnotationKeys::URL_Key(), std::move(d0) }, 714 { r1, SkAnnotationKeys::Define_Named_Dest_Key(), std::move(d1) }, 715 { r2, SkAnnotationKeys::Link_Named_Dest_Key(), std::move(d2) }, 716 }; 717 718 sk_sp<SkPicture> pict0(recorder.finishRecordingAsPicture()); 719 sk_sp<SkPicture> pict1(copy_picture_via_serialization(pict0.get())); 720 721 TestAnnotationCanvas canvas(reporter, recs, SK_ARRAY_COUNT(recs)); 722 canvas.drawPicture(pict1); 723 } 724