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