| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2010 The Android Open Source Project | 2 * Copyright 2010 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkBitmap.h" | 8 #include "SkBitmap.h" |
| 9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
| 10 #include "SkData.h" | 10 #include "SkData.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 void addResource(SkPDFObject* object) { | 34 void addResource(SkPDFObject* object) { |
| 35 fResources.append(1, &object); | 35 fResources.append(1, &object); |
| 36 } | 36 } |
| 37 | 37 |
| 38 private: | 38 private: |
| 39 SkTDArray<SkPDFObject*> fResources; | 39 SkTDArray<SkPDFObject*> fResources; |
| 40 }; | 40 }; |
| 41 | 41 |
| 42 #define DUMMY_TEXT "DCT compessed stream." | 42 #define DUMMY_TEXT "DCT compessed stream." |
| 43 | 43 |
| 44 static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap
) { | |
| 45 *pixelRefOffset = 0; | |
| 46 return SkData::NewWithProc(DUMMY_TEXT, sizeof(DUMMY_TEXT) - 1, NULL, NULL); | |
| 47 } | |
| 48 | |
| 49 static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset, | 44 static bool stream_equals(const SkDynamicMemoryWStream& stream, size_t offset, |
| 50 const void* buffer, size_t len) { | 45 const void* buffer, size_t len) { |
| 51 SkAutoDataUnref data(stream.copyToData()); | 46 SkAutoDataUnref data(stream.copyToData()); |
| 52 if (offset + len > data->size()) { | 47 if (offset + len > data->size()) { |
| 53 return false; | 48 return false; |
| 54 } | 49 } |
| 55 return memcmp(data->bytes() + offset, buffer, len) == 0; | 50 return memcmp(data->bytes() + offset, buffer, len) == 0; |
| 56 } | 51 } |
| 57 | 52 |
| 58 static bool stream_contains(const SkDynamicMemoryWStream& stream, | |
| 59 const char* buffer) { | |
| 60 SkAutoDataUnref data(stream.copyToData()); | |
| 61 size_t len = strlen(buffer); // our buffer does not have EOSs. | |
| 62 | |
| 63 for (size_t offset = 0 ; offset < data->size() - len; offset++) { | |
| 64 if (memcmp(data->bytes() + offset, buffer, len) == 0) { | |
| 65 return true; | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 return false; | |
| 70 } | |
| 71 | |
| 72 static void emit_object(SkPDFObject* object, | 53 static void emit_object(SkPDFObject* object, |
| 73 SkWStream* stream, | 54 SkWStream* stream, |
| 74 SkPDFCatalog* catalog, | 55 SkPDFCatalog* catalog, |
| 75 bool indirect) { | 56 bool indirect) { |
| 76 SkPDFObject* realObject = catalog->getSubstituteObject(object); | 57 SkPDFObject* realObject = catalog->getSubstituteObject(object); |
| 77 if (indirect) { | 58 if (indirect) { |
| 78 stream->writeDecAsText(catalog->getObjectNumber(object)); | 59 stream->writeDecAsText(catalog->getObjectNumber(object)); |
| 79 stream->writeText(" 0 obj\n"); // Generation number is always 0. | 60 stream->writeText(" 0 obj\n"); // Generation number is always 0. |
| 80 realObject->emitObject(stream, catalog); | 61 realObject->emitObject(stream, catalog); |
| 81 stream->writeText("\nendobj\n"); | 62 stream->writeText("\nendobj\n"); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 stub->insert("Value", new SkPDFInt(44))->unref(); | 217 stub->insert("Value", new SkPDFInt(44))->unref(); |
| 237 | 218 |
| 238 SkPDFCatalog catalog((SkPDFDocument::Flags)0); | 219 SkPDFCatalog catalog((SkPDFDocument::Flags)0); |
| 239 catalog.addObject(proxy.get(), false); | 220 catalog.addObject(proxy.get(), false); |
| 240 catalog.setSubstitute(proxy.get(), stub.get()); | 221 catalog.setSubstitute(proxy.get(), stub.get()); |
| 241 | 222 |
| 242 REPORTER_ASSERT(reporter, stub.get() == catalog.getSubstituteObject(proxy)); | 223 REPORTER_ASSERT(reporter, stub.get() == catalog.getSubstituteObject(proxy)); |
| 243 REPORTER_ASSERT(reporter, proxy.get() != catalog.getSubstituteObject(stub)); | 224 REPORTER_ASSERT(reporter, proxy.get() != catalog.getSubstituteObject(stub)); |
| 244 } | 225 } |
| 245 | 226 |
| 246 // Create a bitmap that would be very eficiently compressed in a ZIP. | |
| 247 static void setup_bitmap(SkBitmap* bitmap, int width, int height) { | |
| 248 bitmap->allocN32Pixels(width, height); | |
| 249 bitmap->eraseColor(SK_ColorWHITE); | |
| 250 } | |
| 251 | |
| 252 static void TestImage(skiatest::Reporter* reporter, const SkBitmap& bitmap, | |
| 253 const char* expected, bool useDCTEncoder) { | |
| 254 SkISize pageSize = SkISize::Make(bitmap.width(), bitmap.height()); | |
| 255 SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::
I())); | |
| 256 | |
| 257 if (useDCTEncoder) { | |
| 258 dev->setDCTEncoder(encode_to_dct_data); | |
| 259 } | |
| 260 | |
| 261 SkCanvas c(dev); | |
| 262 c.drawBitmap(bitmap, 0, 0, NULL); | |
| 263 | |
| 264 SkPDFDocument doc; | |
| 265 doc.appendPage(dev); | |
| 266 | |
| 267 SkDynamicMemoryWStream stream; | |
| 268 doc.emitPDF(&stream); | |
| 269 | |
| 270 REPORTER_ASSERT(reporter, stream_contains(stream, expected)); | |
| 271 } | |
| 272 | |
| 273 static void TestUncompressed(skiatest::Reporter* reporter) { | |
| 274 SkBitmap bitmap; | |
| 275 setup_bitmap(&bitmap, 1, 1); | |
| 276 TestImage(reporter, bitmap, | |
| 277 "/Subtype /Image\n" | |
| 278 "/Width 1\n" | |
| 279 "/Height 1\n" | |
| 280 "/ColorSpace /DeviceRGB\n" | |
| 281 "/BitsPerComponent 8\n" | |
| 282 "/Length 3\n" | |
| 283 ">> stream", | |
| 284 true); | |
| 285 } | |
| 286 | |
| 287 static void TestFlateDecode(skiatest::Reporter* reporter) { | |
| 288 #ifndef SK_NO_FLATE | |
| 289 SkBitmap bitmap; | |
| 290 setup_bitmap(&bitmap, 10, 10); | |
| 291 TestImage(reporter, bitmap, | |
| 292 "/Subtype /Image\n" | |
| 293 "/Width 10\n" | |
| 294 "/Height 10\n" | |
| 295 "/ColorSpace /DeviceRGB\n" | |
| 296 "/BitsPerComponent 8\n" | |
| 297 "/Filter /FlateDecode\n" | |
| 298 "/Length 13\n" | |
| 299 ">> stream", | |
| 300 false); | |
| 301 #endif // SK_NO_FLATE | |
| 302 } | |
| 303 | |
| 304 static void TestDCTDecode(skiatest::Reporter* reporter) { | |
| 305 SkBitmap bitmap; | |
| 306 setup_bitmap(&bitmap, 32, 32); | |
| 307 TestImage(reporter, bitmap, | |
| 308 "/Subtype /Image\n" | |
| 309 "/Width 32\n" | |
| 310 "/Height 32\n" | |
| 311 "/ColorSpace /DeviceRGB\n" | |
| 312 "/BitsPerComponent 8\n" | |
| 313 "/Filter /DCTDecode\n" | |
| 314 "/ColorTransform 0\n" | |
| 315 "/Length 21\n" | |
| 316 ">> stream", | |
| 317 true); | |
| 318 } | |
| 319 | |
| 320 static void TestImages(skiatest::Reporter* reporter) { | |
| 321 TestUncompressed(reporter); | |
| 322 TestFlateDecode(reporter); | |
| 323 TestDCTDecode(reporter); | |
| 324 } | |
| 325 | |
| 326 // This test used to assert without the fix submitted for | 227 // This test used to assert without the fix submitted for |
| 327 // http://code.google.com/p/skia/issues/detail?id=1083. | 228 // http://code.google.com/p/skia/issues/detail?id=1083. |
| 328 // SKP files might have invalid glyph ids. This test ensures they are ignored, | 229 // SKP files might have invalid glyph ids. This test ensures they are ignored, |
| 329 // and there is no assert on input data in Debug mode. | 230 // and there is no assert on input data in Debug mode. |
| 330 static void test_issue1083() { | 231 static void test_issue1083() { |
| 331 SkISize pageSize = SkISize::Make(100, 100); | 232 SkISize pageSize = SkISize::Make(100, 100); |
| 332 SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::
I())); | 233 SkAutoTUnref<SkPDFDevice> dev(new SkPDFDevice(pageSize, pageSize, SkMatrix::
I())); |
| 333 | 234 |
| 334 SkCanvas c(dev); | 235 SkCanvas c(dev); |
| 335 SkPaint paint; | 236 SkPaint paint; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 | 320 |
| 420 TestPDFStream(reporter); | 321 TestPDFStream(reporter); |
| 421 | 322 |
| 422 TestCatalog(reporter); | 323 TestCatalog(reporter); |
| 423 | 324 |
| 424 TestObjectRef(reporter); | 325 TestObjectRef(reporter); |
| 425 | 326 |
| 426 TestSubstitute(reporter); | 327 TestSubstitute(reporter); |
| 427 | 328 |
| 428 test_issue1083(); | 329 test_issue1083(); |
| 429 | |
| 430 TestImages(reporter); | |
| 431 } | 330 } |
| 432 | 331 |
| 433 namespace { | 332 namespace { |
| 434 | 333 |
| 435 class DummyImageFilter : public SkImageFilter { | 334 class DummyImageFilter : public SkImageFilter { |
| 436 public: | 335 public: |
| 437 DummyImageFilter(bool visited = false) : SkImageFilter(0, NULL), fVisited(vi
sited) {} | 336 DummyImageFilter(bool visited = false) : SkImageFilter(0, NULL), fVisited(vi
sited) {} |
| 438 ~DummyImageFilter() SK_OVERRIDE {} | 337 ~DummyImageFilter() SK_OVERRIDE {} |
| 439 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, | 338 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, |
| 440 SkBitmap* result, SkIPoint* offset) const SK_OVER
RIDE { | 339 SkBitmap* result, SkIPoint* offset) const SK_OVER
RIDE { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 | 375 |
| 477 // Filter just created; should be unvisited. | 376 // Filter just created; should be unvisited. |
| 478 REPORTER_ASSERT(reporter, !filter->visited()); | 377 REPORTER_ASSERT(reporter, !filter->visited()); |
| 479 SkPaint paint; | 378 SkPaint paint; |
| 480 paint.setImageFilter(filter.get()); | 379 paint.setImageFilter(filter.get()); |
| 481 canvas.drawRect(SkRect::MakeWH(100, 100), paint); | 380 canvas.drawRect(SkRect::MakeWH(100, 100), paint); |
| 482 | 381 |
| 483 // Filter was used in rendering; should be visited. | 382 // Filter was used in rendering; should be visited. |
| 484 REPORTER_ASSERT(reporter, filter->visited()); | 383 REPORTER_ASSERT(reporter, filter->visited()); |
| 485 } | 384 } |
| OLD | NEW |