OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
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 "DMSrcSink.h" | 8 #include "DMSrcSink.h" |
9 #include "SamplePipeControllers.h" | 9 #include "SamplePipeControllers.h" |
10 #include "SkCodec.h" | 10 #include "SkCodec.h" |
11 #include "SkCommonFlags.h" | 11 #include "SkCommonFlags.h" |
12 #include "SkData.h" | 12 #include "SkData.h" |
13 #include "SkDocument.h" | 13 #include "SkDocument.h" |
14 #include "SkError.h" | 14 #include "SkError.h" |
15 #include "SkFunction.h" | 15 #include "SkFunction.h" |
16 #include "SkImageGenerator.h" | 16 #include "SkImageGenerator.h" |
17 #include "SkMultiPictureDraw.h" | 17 #include "SkMultiPictureDraw.h" |
18 #include "SkNullCanvas.h" | 18 #include "SkNullCanvas.h" |
19 #include "SkOSFile.h" | 19 #include "SkOSFile.h" |
20 #include "SkPictureData.h" | 20 #include "SkPictureData.h" |
21 #include "SkPictureRecorder.h" | 21 #include "SkPictureRecorder.h" |
22 #include "SkRandom.h" | 22 #include "SkRandom.h" |
23 #include "SkRecordDraw.h" | 23 #include "SkRecordDraw.h" |
24 #include "SkRecorder.h" | 24 #include "SkRecorder.h" |
25 #include "SkSVGCanvas.h" | 25 #include "SkSVGCanvas.h" |
26 #include "SkScanlineDecoder.h" | |
27 #include "SkStream.h" | 26 #include "SkStream.h" |
28 #include "SkXMLWriter.h" | 27 #include "SkXMLWriter.h" |
29 #include "SkScaledCodec.h" | 28 #include "SkScaledCodec.h" |
30 | 29 |
31 DEFINE_bool(multiPage, false, "For document-type backends, render the source" | 30 DEFINE_bool(multiPage, false, "For document-type backends, render the source" |
32 " into multiple pages"); | 31 " into multiple pages"); |
33 | 32 |
34 static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) { | 33 static bool lazy_decode_bitmap(const void* src, size_t size, SkBitmap* dst) { |
35 SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size)); | 34 SkAutoTUnref<SkData> encoded(SkData::NewWithCopy(src, size)); |
36 return encoded && SkInstallDiscardablePixelRef(encoded, dst); | 35 return encoded && SkInstallDiscardablePixelRef(encoded, dst); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 {} | 228 {} |
230 | 229 |
231 bool CodecSrc::veto(SinkFlags flags) const { | 230 bool CodecSrc::veto(SinkFlags flags) const { |
232 // No need to test decoding to non-raster or indirect backend. | 231 // No need to test decoding to non-raster or indirect backend. |
233 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferr
ed decode to | 232 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferr
ed decode to |
234 // let the GPU handle it. | 233 // let the GPU handle it. |
235 return flags.type != SinkFlags::kRaster | 234 return flags.type != SinkFlags::kRaster |
236 || flags.approach != SinkFlags::kDirect; | 235 || flags.approach != SinkFlags::kDirect; |
237 } | 236 } |
238 | 237 |
239 SkScanlineDecoder* start_scanline_decoder(SkData* encoded, const SkImageInfo& in
fo, | |
240 SkPMColor* colorPtr, int* colorCountPtr) { | |
241 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(SkScanlineDecoder::NewFromD
ata(encoded)); | |
242 if (nullptr == scanlineDecoder) { | |
243 return nullptr; | |
244 } | |
245 if (SkCodec::kSuccess != scanlineDecoder->start(info, NULL, colorPtr, colorC
ountPtr)) { | |
246 return nullptr; | |
247 } | |
248 return scanlineDecoder.detach(); | |
249 } | |
250 | |
251 Error CodecSrc::draw(SkCanvas* canvas) const { | 238 Error CodecSrc::draw(SkCanvas* canvas) const { |
252 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 239 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
253 if (!encoded) { | 240 if (!encoded) { |
254 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); | 241 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); |
255 } | 242 } |
256 SkAutoTDelete<SkCodec> codec(NULL); | 243 SkAutoTDelete<SkCodec> codec(NULL); |
257 if (kScaledCodec_Mode == fMode) { | 244 if (kScaledCodec_Mode == fMode) { |
258 codec.reset(SkScaledCodec::NewFromData(encoded)); | 245 codec.reset(SkScaledCodec::NewFromData(encoded)); |
259 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled | 246 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled |
260 // codecs for all image types. | 247 // codecs for all image types. |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 case SkCodec::kInvalidConversion: | 326 case SkCodec::kInvalidConversion: |
340 return Error::Nonfatal("Incompatible colortype conversion"); | 327 return Error::Nonfatal("Incompatible colortype conversion"); |
341 default: | 328 default: |
342 // Everything else is considered a failure. | 329 // Everything else is considered a failure. |
343 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str(
)); | 330 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str(
)); |
344 } | 331 } |
345 canvas->drawBitmap(bitmap, 0, 0); | 332 canvas->drawBitmap(bitmap, 0, 0); |
346 break; | 333 break; |
347 } | 334 } |
348 case kScanline_Mode: { | 335 case kScanline_Mode: { |
349 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder( | 336 if (SkCodec::kSuccess != codec->start(decodeInfo, NULL, colorPtr, co
lorCountPtr)) { |
350 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); | |
351 if (nullptr == scanlineDecoder) { | |
352 return Error::Nonfatal("Could not start scanline decoder"); | 337 return Error::Nonfatal("Could not start scanline decoder"); |
353 } | 338 } |
354 | 339 |
355 SkCodec::Result result = SkCodec::kUnimplemented; | 340 SkCodec::Result result = SkCodec::kUnimplemented; |
356 switch (scanlineDecoder->getScanlineOrder()) { | 341 switch (codec->getScanlineOrder()) { |
357 case SkScanlineDecoder::kTopDown_SkScanlineOrder: | 342 case SkCodec::kTopDown_SkScanlineOrder: |
358 case SkScanlineDecoder::kBottomUp_SkScanlineOrder: | 343 case SkCodec::kBottomUp_SkScanlineOrder: |
359 case SkScanlineDecoder::kNone_SkScanlineOrder: | 344 case SkCodec::kNone_SkScanlineOrder: |
360 result = scanlineDecoder->getScanlines(bitmap.getAddr(0, 0), | 345 result = codec->getScanlines(bitmap.getAddr(0, 0), |
361 decodeInfo.height(), bitmap.rowBytes()); | 346 decodeInfo.height(), bitmap.rowBytes()); |
362 break; | 347 break; |
363 case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { | 348 case SkCodec::kOutOfOrder_SkScanlineOrder: { |
364 for (int y = 0; y < decodeInfo.height(); y++) { | 349 for (int y = 0; y < decodeInfo.height(); y++) { |
365 int dstY = scanlineDecoder->getY(); | 350 int dstY = codec->getY(); |
366 void* dstPtr = bitmap.getAddr(0, dstY); | 351 void* dstPtr = bitmap.getAddr(0, dstY); |
367 result = scanlineDecoder->getScanlines(dstPtr, 1, bitmap
.rowBytes()); | 352 result = codec->getScanlines(dstPtr, 1, bitmap.rowBytes(
)); |
368 if (SkCodec::kSuccess != result && SkCodec::kIncompleteI
nput != result) { | 353 if (SkCodec::kSuccess != result && SkCodec::kIncompleteI
nput != result) { |
369 return SkStringPrintf("%s failed with error message
%d", | 354 return SkStringPrintf("%s failed with error message
%d", |
370 fPath.c_str(), (int) result); | 355 fPath.c_str(), (int) result); |
371 } | 356 } |
372 } | 357 } |
373 break; | 358 break; |
374 } | 359 } |
375 } | 360 } |
376 | 361 |
377 switch (result) { | 362 switch (result) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets | 408 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets |
424 const int currentSubsetWidth = (col + 1 == divisor) ? | 409 const int currentSubsetWidth = (col + 1 == divisor) ? |
425 subsetWidth + extraX : subsetWidth; | 410 subsetWidth + extraX : subsetWidth; |
426 const int x = col * subsetWidth; | 411 const int x = col * subsetWidth; |
427 for (int row = 0; row < divisor; row++) { | 412 for (int row = 0; row < divisor; row++) { |
428 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets | 413 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets |
429 const int currentSubsetHeight = (row + 1 == divisor) ? | 414 const int currentSubsetHeight = (row + 1 == divisor) ? |
430 subsetHeight + extraY : subsetHeight; | 415 subsetHeight + extraY : subsetHeight; |
431 const int y = row * subsetHeight; | 416 const int y = row * subsetHeight; |
432 //create scanline decoder for each subset | 417 //create scanline decoder for each subset |
433 SkAutoTDelete<SkScanlineDecoder> decoder(start_scanline_deco
der(encoded.get(), | 418 if (SkCodec::kSuccess != codec->start(decodeInfo, NULL, colo
rPtr, colorCountPtr) |
434 decodeInfo, colorPtr, colorCountPtr)); | 419 // TODO (msarett): Support this mode for all scanlin
e orderings. |
435 // TODO (msarett): Support this mode for all scanline orderi
ngs. | 420 || SkCodec::kTopDown_SkScanlineOrder != codec->getSc
anlineOrder()) { |
436 if (nullptr == decoder || SkScanlineDecoder::kTopDown_SkScan
lineOrder != | |
437 decoder->getScanlineOrder()) { | |
438 if (x == 0 && y == 0) { | 421 if (x == 0 && y == 0) { |
439 //first try, image may not be compatible | 422 //first try, image may not be compatible |
440 return Error::Nonfatal("Could not start top-down sca
nline decoder"); | 423 return Error::Nonfatal("Could not start top-down sca
nline decoder"); |
441 } else { | 424 } else { |
442 return "Error scanline decoder is nullptr"; | 425 return "Error scanline decoder is nullptr"; |
443 } | 426 } |
444 } | 427 } |
445 //skip to first line of subset | 428 //skip to first line of subset |
446 const SkCodec::Result skipResult = decoder->skipScanlines(y)
; | 429 const SkCodec::Result skipResult = codec->skipScanlines(y); |
447 switch (skipResult) { | 430 switch (skipResult) { |
448 case SkCodec::kSuccess: | 431 case SkCodec::kSuccess: |
449 case SkCodec::kIncompleteInput: | 432 case SkCodec::kIncompleteInput: |
450 break; | 433 break; |
451 default: | 434 default: |
452 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" | 435 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" |
453 "with error message %d", fPath.c_str(), y, (
int) skipResult); | 436 "with error message %d", fPath.c_str(), y, (
int) skipResult); |
454 } | 437 } |
455 //create and set size of subsetBm | 438 //create and set size of subsetBm |
456 SkBitmap subsetBm; | 439 SkBitmap subsetBm; |
457 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); | 440 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); |
458 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); | 441 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); |
459 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); | 442 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); |
460 SkAutoLockPixels autlockSubsetBm(subsetBm, true); | 443 SkAutoLockPixels autlockSubsetBm(subsetBm, true); |
461 const SkCodec::Result subsetResult = | 444 const SkCodec::Result subsetResult = |
462 decoder->getScanlines(buffer, currentSubsetHeight, r
owBytes); | 445 codec->getScanlines(buffer, currentSubsetHeight, row
Bytes); |
463 switch (subsetResult) { | 446 switch (subsetResult) { |
464 case SkCodec::kSuccess: | 447 case SkCodec::kSuccess: |
465 case SkCodec::kIncompleteInput: | 448 case SkCodec::kIncompleteInput: |
466 break; | 449 break; |
467 default: | 450 default: |
468 return SkStringPrintf("%s failed with error message
%d", | 451 return SkStringPrintf("%s failed with error message
%d", |
469 fPath.c_str(), (int) subsetResult); | 452 fPath.c_str(), (int) subsetResult); |
470 } | 453 } |
471 const size_t bpp = decodeInfo.bytesPerPixel(); | 454 const size_t bpp = decodeInfo.bytesPerPixel(); |
472 /* | 455 /* |
(...skipping 19 matching lines...) Expand all Loading... |
492 break; | 475 break; |
493 } | 476 } |
494 case kStripe_Mode: { | 477 case kStripe_Mode: { |
495 const int height = decodeInfo.height(); | 478 const int height = decodeInfo.height(); |
496 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that | 479 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that |
497 // does not align with image blocks. | 480 // does not align with image blocks. |
498 const int stripeHeight = 37; | 481 const int stripeHeight = 37; |
499 const int numStripes = (height + stripeHeight - 1) / stripeHeight; | 482 const int numStripes = (height + stripeHeight - 1) / stripeHeight; |
500 | 483 |
501 // Decode odd stripes | 484 // Decode odd stripes |
502 SkAutoTDelete<SkScanlineDecoder> decoder( | 485 if (SkCodec::kSuccess != codec->start(decodeInfo, NULL, colorPtr, co
lorCountPtr) |
503 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); | 486 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr
der()) { |
504 if (nullptr == decoder || | |
505 SkScanlineDecoder::kTopDown_SkScanlineOrder != decoder->getS
canlineOrder()) { | |
506 // This mode was designed to test the new skip scanlines API in
libjpeg-turbo. | 487 // This mode was designed to test the new skip scanlines API in
libjpeg-turbo. |
507 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is
not interesting | 488 // Jpegs have kTopDown_SkScanlineOrder, and at this time, it is
not interesting |
508 // to run this test for image types that do not have this scanli
ne ordering. | 489 // to run this test for image types that do not have this scanli
ne ordering. |
509 return Error::Nonfatal("Could not start top-down scanline decode
r"); | 490 return Error::Nonfatal("Could not start top-down scanline decode
r"); |
510 } | 491 } |
511 for (int i = 0; i < numStripes; i += 2) { | 492 for (int i = 0; i < numStripes; i += 2) { |
512 // Skip a stripe | 493 // Skip a stripe |
513 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); | 494 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); |
514 SkCodec::Result result = decoder->skipScanlines(linesToSkip); | 495 SkCodec::Result result = codec->skipScanlines(linesToSkip); |
515 switch (result) { | 496 switch (result) { |
516 case SkCodec::kSuccess: | 497 case SkCodec::kSuccess: |
517 case SkCodec::kIncompleteInput: | 498 case SkCodec::kIncompleteInput: |
518 break; | 499 break; |
519 default: | 500 default: |
520 return SkStringPrintf("Cannot skip scanlines for %s.", f
Path.c_str()); | 501 return SkStringPrintf("Cannot skip scanlines for %s.", f
Path.c_str()); |
521 } | 502 } |
522 | 503 |
523 // Read a stripe | 504 // Read a stripe |
524 const int startY = (i + 1) * stripeHeight; | 505 const int startY = (i + 1) * stripeHeight; |
525 const int linesToRead = SkTMin(stripeHeight, height - startY); | 506 const int linesToRead = SkTMin(stripeHeight, height - startY); |
526 if (linesToRead > 0) { | 507 if (linesToRead > 0) { |
527 result = decoder->getScanlines(bitmap.getAddr(0, startY), | 508 result = codec->getScanlines(bitmap.getAddr(0, startY), |
528 linesToRead, bitmap.rowBytes()); | 509 linesToRead, bitmap.rowBytes()); |
529 switch (result) { | 510 switch (result) { |
530 case SkCodec::kSuccess: | 511 case SkCodec::kSuccess: |
531 case SkCodec::kIncompleteInput: | 512 case SkCodec::kIncompleteInput: |
532 break; | 513 break; |
533 default: | 514 default: |
534 return SkStringPrintf("Cannot get scanlines for %s."
, fPath.c_str()); | 515 return SkStringPrintf("Cannot get scanlines for %s."
, fPath.c_str()); |
535 } | 516 } |
536 } | 517 } |
537 } | 518 } |
538 | 519 |
539 // Decode even stripes | 520 // Decode even stripes |
540 const SkCodec::Result startResult = decoder->start(decodeInfo, nullp
tr, colorPtr, | 521 const SkCodec::Result startResult = codec->start(decodeInfo, nullptr
, colorPtr, |
541 colorCountPtr); | 522 colorCountPtr); |
542 if (SkCodec::kSuccess != startResult) { | 523 if (SkCodec::kSuccess != startResult) { |
543 return "Failed to restart scanline decoder with same parameters.
"; | 524 return "Failed to restart scanline decoder with same parameters.
"; |
544 } | 525 } |
545 for (int i = 0; i < numStripes; i += 2) { | 526 for (int i = 0; i < numStripes; i += 2) { |
546 // Read a stripe | 527 // Read a stripe |
547 const int startY = i * stripeHeight; | 528 const int startY = i * stripeHeight; |
548 const int linesToRead = SkTMin(stripeHeight, height - startY); | 529 const int linesToRead = SkTMin(stripeHeight, height - startY); |
549 SkCodec::Result result = decoder->getScanlines(bitmap.getAddr(0,
startY), | 530 SkCodec::Result result = codec->getScanlines(bitmap.getAddr(0, s
tartY), |
550 linesToRead, bitmap.rowBytes()); | 531 linesToRead, bitmap.rowBytes()); |
551 switch (result) { | 532 switch (result) { |
552 case SkCodec::kSuccess: | 533 case SkCodec::kSuccess: |
553 case SkCodec::kIncompleteInput: | 534 case SkCodec::kIncompleteInput: |
554 break; | 535 break; |
555 default: | 536 default: |
556 return SkStringPrintf("Cannot get scanlines for %s.", fP
ath.c_str()); | 537 return SkStringPrintf("Cannot get scanlines for %s.", fP
ath.c_str()); |
557 } | 538 } |
558 | 539 |
559 // Skip a stripe | 540 // Skip a stripe |
560 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) *
stripeHeight); | 541 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) *
stripeHeight); |
561 if (linesToSkip > 0) { | 542 if (linesToSkip > 0) { |
562 result = decoder->skipScanlines(linesToSkip); | 543 result = codec->skipScanlines(linesToSkip); |
563 switch (result) { | 544 switch (result) { |
564 case SkCodec::kSuccess: | 545 case SkCodec::kSuccess: |
565 case SkCodec::kIncompleteInput: | 546 case SkCodec::kIncompleteInput: |
566 break; | 547 break; |
567 default: | 548 default: |
568 return SkStringPrintf("Cannot skip scanlines for %s.
", fPath.c_str()); | 549 return SkStringPrintf("Cannot skip scanlines for %s.
", fPath.c_str()); |
569 } | 550 } |
570 } | 551 } |
571 } | 552 } |
572 canvas->drawBitmap(bitmap, 0, 0); | 553 canvas->drawBitmap(bitmap, 0, 0); |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 skr.visit<void>(i, drawsAsSingletonPictures); | 1243 skr.visit<void>(i, drawsAsSingletonPictures); |
1263 } | 1244 } |
1264 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 1245 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
1265 | 1246 |
1266 canvas->drawPicture(macroPic); | 1247 canvas->drawPicture(macroPic); |
1267 return ""; | 1248 return ""; |
1268 }); | 1249 }); |
1269 } | 1250 } |
1270 | 1251 |
1271 } // namespace DM | 1252 } // namespace DM |
OLD | NEW |