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 "SkBitmapDevice.h" 9 #include "SkBitmapSource.h" 10 #include "SkCanvas.h" 11 #include "SkMallocPixelRef.h" 12 #include "SkPictureRecorder.h" 13 #include "SkTemplates.h" 14 #include "SkWriteBuffer.h" 15 #include "SkValidatingReadBuffer.h" 16 #include "SkXfermodeImageFilter.h" 17 #include "Test.h" 18 19 static const uint32_t kArraySize = 64; 20 static const int kBitmapSize = 256; 21 22 template<typename T> 23 static void TestAlignment(T* testObj, skiatest::Reporter* reporter) { 24 // Test memory read/write functions directly 25 unsigned char dataWritten[1024]; 26 size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten); 27 REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory); 28 size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory); 29 REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory); 30 } 31 32 template<typename T> struct SerializationUtils { 33 // Generic case for flattenables 34 static void Write(SkWriteBuffer& writer, const T* flattenable) { 35 writer.writeFlattenable(flattenable); 36 } 37 static void Read(SkValidatingReadBuffer& reader, T** flattenable) { 38 *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType()); 39 } 40 }; 41 42 template<> struct SerializationUtils<SkMatrix> { 43 static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) { 44 writer.writeMatrix(*matrix); 45 } 46 static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) { 47 reader.readMatrix(matrix); 48 } 49 }; 50 51 template<> struct SerializationUtils<SkPath> { 52 static void Write(SkWriteBuffer& writer, const SkPath* path) { 53 writer.writePath(*path); 54 } 55 static void Read(SkValidatingReadBuffer& reader, SkPath* path) { 56 reader.readPath(path); 57 } 58 }; 59 60 template<> struct SerializationUtils<SkRegion> { 61 static void Write(SkWriteBuffer& writer, const SkRegion* region) { 62 writer.writeRegion(*region); 63 } 64 static void Read(SkValidatingReadBuffer& reader, SkRegion* region) { 65 reader.readRegion(region); 66 } 67 }; 68 69 template<> struct SerializationUtils<SkString> { 70 static void Write(SkWriteBuffer& writer, const SkString* string) { 71 writer.writeString(string->c_str()); 72 } 73 static void Read(SkValidatingReadBuffer& reader, SkString* string) { 74 reader.readString(string); 75 } 76 }; 77 78 template<> struct SerializationUtils<unsigned char> { 79 static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) { 80 writer.writeByteArray(data, arraySize); 81 } 82 static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) { 83 return reader.readByteArray(data, arraySize); 84 } 85 }; 86 87 template<> struct SerializationUtils<SkColor> { 88 static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) { 89 writer.writeColorArray(data, arraySize); 90 } 91 static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) { 92 return reader.readColorArray(data, arraySize); 93 } 94 }; 95 96 template<> struct SerializationUtils<int32_t> { 97 static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) { 98 writer.writeIntArray(data, arraySize); 99 } 100 static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) { 101 return reader.readIntArray(data, arraySize); 102 } 103 }; 104 105 template<> struct SerializationUtils<SkPoint> { 106 static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) { 107 writer.writePointArray(data, arraySize); 108 } 109 static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) { 110 return reader.readPointArray(data, arraySize); 111 } 112 }; 113 114 template<> struct SerializationUtils<SkScalar> { 115 static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) { 116 writer.writeScalarArray(data, arraySize); 117 } 118 static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) { 119 return reader.readScalarArray(data, arraySize); 120 } 121 }; 122 123 template<typename T, bool testInvalid> struct SerializationTestUtils { 124 static void InvalidateData(unsigned char* data) {} 125 }; 126 127 template<> struct SerializationTestUtils<SkString, true> { 128 static void InvalidateData(unsigned char* data) { 129 data[3] |= 0x80; // Reverse sign of 1st integer 130 } 131 }; 132 133 template<typename T, bool testInvalid> 134 static void TestObjectSerializationNoAlign(T* testObj, skiatest::Reporter* reporter) { 135 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 136 SerializationUtils<T>::Write(writer, testObj); 137 size_t bytesWritten = writer.bytesWritten(); 138 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 139 140 unsigned char dataWritten[1024]; 141 writer.writeToMemory(dataWritten); 142 143 SerializationTestUtils<T, testInvalid>::InvalidateData(dataWritten); 144 145 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 146 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 147 T obj; 148 SerializationUtils<T>::Read(buffer, &obj); 149 REPORTER_ASSERT(reporter, !buffer.isValid()); 150 151 // Make sure this succeeds when it should 152 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 153 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 154 T obj2; 155 SerializationUtils<T>::Read(buffer2, &obj2); 156 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 157 // This should have succeeded, since there are enough bytes to read this 158 REPORTER_ASSERT(reporter, buffer2.isValid() == !testInvalid); 159 // Note: This following test should always succeed, regardless of whether the buffer is valid, 160 // since if it is invalid, it will simply skip to the end, as if it had read the whole buffer. 161 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 162 } 163 164 template<typename T> 165 static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { 166 TestObjectSerializationNoAlign<T, false>(testObj, reporter); 167 TestAlignment(testObj, reporter); 168 } 169 170 template<typename T> 171 static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed, 172 skiatest::Reporter* reporter) { 173 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 174 SerializationUtils<T>::Write(writer, testObj); 175 size_t bytesWritten = writer.bytesWritten(); 176 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten); 177 178 unsigned char dataWritten[1024]; 179 SkASSERT(bytesWritten <= sizeof(dataWritten)); 180 writer.writeToMemory(dataWritten); 181 182 // Make sure this fails when it should (test with smaller size, but still multiple of 4) 183 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4); 184 T* obj = NULL; 185 SerializationUtils<T>::Read(buffer, &obj); 186 REPORTER_ASSERT(reporter, !buffer.isValid()); 187 REPORTER_ASSERT(reporter, NULL == obj); 188 189 // Make sure this succeeds when it should 190 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 191 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); 192 T* obj2 = NULL; 193 SerializationUtils<T>::Read(buffer2, &obj2); 194 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); 195 if (shouldSucceed) { 196 // This should have succeeded, since there are enough bytes to read this 197 REPORTER_ASSERT(reporter, buffer2.isValid()); 198 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); 199 REPORTER_ASSERT(reporter, NULL != obj2); 200 } else { 201 // If the deserialization was supposed to fail, make sure it did 202 REPORTER_ASSERT(reporter, !buffer.isValid()); 203 REPORTER_ASSERT(reporter, NULL == obj2); 204 } 205 206 return obj2; // Return object to perform further validity tests on it 207 } 208 209 template<typename T> 210 static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { 211 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 212 SerializationUtils<T>::Write(writer, data, kArraySize); 213 size_t bytesWritten = writer.bytesWritten(); 214 // This should write the length (in 4 bytes) and the array 215 REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten); 216 217 unsigned char dataWritten[1024]; 218 writer.writeToMemory(dataWritten); 219 220 // Make sure this fails when it should 221 SkValidatingReadBuffer buffer(dataWritten, bytesWritten); 222 T dataRead[kArraySize]; 223 bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2); 224 // This should have failed, since the provided size was too small 225 REPORTER_ASSERT(reporter, !success); 226 227 // Make sure this succeeds when it should 228 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); 229 success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize); 230 // This should have succeeded, since there are enough bytes to read this 231 REPORTER_ASSERT(reporter, success); 232 } 233 234 static void TestBitmapSerialization(const SkBitmap& validBitmap, 235 const SkBitmap& invalidBitmap, 236 bool shouldSucceed, 237 skiatest::Reporter* reporter) { 238 SkAutoTUnref<SkBitmapSource> validBitmapSource(SkBitmapSource::Create(validBitmap)); 239 SkAutoTUnref<SkBitmapSource> invalidBitmapSource(SkBitmapSource::Create(invalidBitmap)); 240 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode)); 241 SkAutoTUnref<SkXfermodeImageFilter> xfermodeImageFilter( 242 SkXfermodeImageFilter::Create(mode, invalidBitmapSource, validBitmapSource)); 243 244 SkAutoTUnref<SkImageFilter> deserializedFilter( 245 TestFlattenableSerialization<SkImageFilter>( 246 xfermodeImageFilter, shouldSucceed, reporter)); 247 248 // Try to render a small bitmap using the invalid deserialized filter 249 // to make sure we don't crash while trying to render it 250 if (shouldSucceed) { 251 SkBitmap bitmap; 252 bitmap.allocN32Pixels(24, 24); 253 SkCanvas canvas(bitmap); 254 canvas.clear(0x00000000); 255 SkPaint paint; 256 paint.setImageFilter(deserializedFilter); 257 canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24))); 258 canvas.drawBitmap(bitmap, 0, 0, &paint); 259 } 260 } 261 262 static bool setup_bitmap_for_canvas(SkBitmap* bitmap) { 263 SkImageInfo info = SkImageInfo::Make( 264 kBitmapSize, kBitmapSize, kN32_SkColorType, kPremul_SkAlphaType); 265 return bitmap->allocPixels(info); 266 } 267 268 static bool make_checkerboard_bitmap(SkBitmap& bitmap) { 269 bool success = setup_bitmap_for_canvas(&bitmap); 270 271 SkCanvas canvas(bitmap); 272 canvas.clear(0x00000000); 273 SkPaint darkPaint; 274 darkPaint.setColor(0xFF804020); 275 SkPaint lightPaint; 276 lightPaint.setColor(0xFF244484); 277 const int i = kBitmapSize / 8; 278 const SkScalar f = SkIntToScalar(i); 279 for (int y = 0; y < kBitmapSize; y += i) { 280 for (int x = 0; x < kBitmapSize; x += i) { 281 canvas.save(); 282 canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); 283 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint); 284 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint); 285 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint); 286 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint); 287 canvas.restore(); 288 } 289 } 290 291 return success; 292 } 293 294 static bool drawSomething(SkCanvas* canvas) { 295 SkPaint paint; 296 SkBitmap bitmap; 297 bool success = make_checkerboard_bitmap(bitmap); 298 299 canvas->save(); 300 canvas->scale(0.5f, 0.5f); 301 canvas->drawBitmap(bitmap, 0, 0, NULL); 302 canvas->restore(); 303 304 const char beforeStr[] = "before circle"; 305 const char afterStr[] = "after circle"; 306 307 paint.setAntiAlias(true); 308 309 paint.setColor(SK_ColorRED); 310 canvas->drawData(beforeStr, sizeof(beforeStr)); 311 canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint); 312 canvas->drawData(afterStr, sizeof(afterStr)); 313 paint.setColor(SK_ColorBLACK); 314 paint.setTextSize(SkIntToScalar(kBitmapSize/3)); 315 canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint); 316 317 return success; 318 } 319 320 DEF_TEST(Serialization, reporter) { 321 // Test matrix serialization 322 { 323 SkMatrix matrix = SkMatrix::I(); 324 TestObjectSerialization(&matrix, reporter); 325 } 326 327 // Test path serialization 328 { 329 SkPath path; 330 TestObjectSerialization(&path, reporter); 331 } 332 333 // Test region serialization 334 { 335 SkRegion region; 336 TestObjectSerialization(®ion, reporter); 337 } 338 339 // Test string serialization 340 { 341 SkString string("string"); 342 TestObjectSerializationNoAlign<SkString, false>(&string, reporter); 343 TestObjectSerializationNoAlign<SkString, true>(&string, reporter); 344 } 345 346 // Test rrect serialization 347 { 348 // SkRRect does not initialize anything. 349 // An uninitialized SkRRect can be serialized, 350 // but will branch on uninitialized data when deserialized. 351 SkRRect rrect; 352 SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30); 353 SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} }; 354 rrect.setRectRadii(rect, corners); 355 TestAlignment(&rrect, reporter); 356 } 357 358 // Test readByteArray 359 { 360 unsigned char data[kArraySize] = { 1, 2, 3 }; 361 TestArraySerialization(data, reporter); 362 } 363 364 // Test readColorArray 365 { 366 SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED }; 367 TestArraySerialization(data, reporter); 368 } 369 370 // Test readIntArray 371 { 372 int32_t data[kArraySize] = { 1, 2, 4, 8 }; 373 TestArraySerialization(data, reporter); 374 } 375 376 // Test readPointArray 377 { 378 SkPoint data[kArraySize] = { {6, 7}, {42, 128} }; 379 TestArraySerialization(data, reporter); 380 } 381 382 // Test readScalarArray 383 { 384 SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax }; 385 TestArraySerialization(data, reporter); 386 } 387 388 // Test invalid deserializations 389 { 390 SkImageInfo info = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize); 391 392 SkBitmap validBitmap; 393 validBitmap.setInfo(info); 394 395 // Create a bitmap with a really large height 396 info.fHeight = 1000000000; 397 SkBitmap invalidBitmap; 398 invalidBitmap.setInfo(info); 399 400 // The deserialization should succeed, and the rendering shouldn't crash, 401 // even when the device fails to initialize, due to its size 402 TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter); 403 } 404 405 // Test simple SkPicture serialization 406 { 407 SkPictureRecorder recorder; 408 bool didDraw = drawSomething(recorder.beginRecording(kBitmapSize, kBitmapSize, NULL, 0)); 409 REPORTER_ASSERT(reporter, didDraw); 410 SkAutoTUnref<SkPicture> pict(recorder.endRecording()); 411 412 // Serialize picture 413 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag); 414 pict->flatten(writer); 415 size_t size = writer.bytesWritten(); 416 SkAutoTMalloc<unsigned char> data(size); 417 writer.writeToMemory(static_cast<void*>(data.get())); 418 419 // Deserialize picture 420 SkValidatingReadBuffer reader(static_cast<void*>(data.get()), size); 421 SkAutoTUnref<SkPicture> readPict( 422 SkPicture::CreateFromBuffer(reader)); 423 REPORTER_ASSERT(reporter, NULL != readPict.get()); 424 } 425 } 426