| 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->startScanlineDecode(decodeInfo, NULL
, colorPtr, |
| 350 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); | 337 colorCountPtr))
{ |
| 351 if (nullptr == scanlineDecoder) { | |
| 352 return Error::Nonfatal("Could not start scanline decoder"); | 338 return Error::Nonfatal("Could not start scanline decoder"); |
| 353 } | 339 } |
| 354 | 340 |
| 355 SkCodec::Result result = SkCodec::kUnimplemented; | 341 SkCodec::Result result = SkCodec::kUnimplemented; |
| 356 switch (scanlineDecoder->getScanlineOrder()) { | 342 switch (codec->getScanlineOrder()) { |
| 357 case SkScanlineDecoder::kTopDown_SkScanlineOrder: | 343 case SkCodec::kTopDown_SkScanlineOrder: |
| 358 case SkScanlineDecoder::kBottomUp_SkScanlineOrder: | 344 case SkCodec::kBottomUp_SkScanlineOrder: |
| 359 case SkScanlineDecoder::kNone_SkScanlineOrder: | 345 case SkCodec::kNone_SkScanlineOrder: |
| 360 result = scanlineDecoder->getScanlines(bitmap.getAddr(0, 0), | 346 result = codec->getScanlines(bitmap.getAddr(0, 0), |
| 361 decodeInfo.height(), bitmap.rowBytes()); | 347 decodeInfo.height(), bitmap.rowBytes()); |
| 362 break; | 348 break; |
| 363 case SkScanlineDecoder::kOutOfOrder_SkScanlineOrder: { | 349 case SkCodec::kOutOfOrder_SkScanlineOrder: { |
| 364 for (int y = 0; y < decodeInfo.height(); y++) { | 350 for (int y = 0; y < decodeInfo.height(); y++) { |
| 365 int dstY = scanlineDecoder->getY(); | 351 int dstY = codec->nextScanline(); |
| 366 void* dstPtr = bitmap.getAddr(0, dstY); | 352 void* dstPtr = bitmap.getAddr(0, dstY); |
| 367 result = scanlineDecoder->getScanlines(dstPtr, 1, bitmap
.rowBytes()); | 353 result = codec->getScanlines(dstPtr, 1, bitmap.rowBytes(
)); |
| 368 if (SkCodec::kSuccess != result && SkCodec::kIncompleteI
nput != result) { | 354 if (SkCodec::kSuccess != result && SkCodec::kIncompleteI
nput != result) { |
| 369 return SkStringPrintf("%s failed with error message
%d", | 355 return SkStringPrintf("%s failed with error message
%d", |
| 370 fPath.c_str(), (int) result); | 356 fPath.c_str(), (int) result); |
| 371 } | 357 } |
| 372 } | 358 } |
| 373 break; | 359 break; |
| 374 } | 360 } |
| 375 } | 361 } |
| 376 | 362 |
| 377 switch (result) { | 363 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 | 409 //currentSubsetWidth may be larger than subsetWidth for rightmos
t subsets |
| 424 const int currentSubsetWidth = (col + 1 == divisor) ? | 410 const int currentSubsetWidth = (col + 1 == divisor) ? |
| 425 subsetWidth + extraX : subsetWidth; | 411 subsetWidth + extraX : subsetWidth; |
| 426 const int x = col * subsetWidth; | 412 const int x = col * subsetWidth; |
| 427 for (int row = 0; row < divisor; row++) { | 413 for (int row = 0; row < divisor; row++) { |
| 428 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets | 414 //currentSubsetHeight may be larger than subsetHeight for bo
ttom subsets |
| 429 const int currentSubsetHeight = (row + 1 == divisor) ? | 415 const int currentSubsetHeight = (row + 1 == divisor) ? |
| 430 subsetHeight + extraY : subsetHeight; | 416 subsetHeight + extraY : subsetHeight; |
| 431 const int y = row * subsetHeight; | 417 const int y = row * subsetHeight; |
| 432 //create scanline decoder for each subset | 418 //create scanline decoder for each subset |
| 433 SkAutoTDelete<SkScanlineDecoder> decoder(start_scanline_deco
der(encoded.get(), | 419 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeIn
fo, NULL, colorPtr, |
| 434 decodeInfo, colorPtr, colorCountPtr)); | 420 colorCou
ntPtr) |
| 435 // TODO (msarett): Support this mode for all scanline orderi
ngs. | 421 // TODO (msarett): Support this mode for all scanlin
e orderings. |
| 436 if (nullptr == decoder || SkScanlineDecoder::kTopDown_SkScan
lineOrder != | 422 || SkCodec::kTopDown_SkScanlineOrder != codec->getSc
anlineOrder()) { |
| 437 decoder->getScanlineOrder()) { | |
| 438 if (x == 0 && y == 0) { | 423 if (x == 0 && y == 0) { |
| 439 //first try, image may not be compatible | 424 //first try, image may not be compatible |
| 440 return Error::Nonfatal("Could not start top-down sca
nline decoder"); | 425 return Error::Nonfatal("Could not start top-down sca
nline decoder"); |
| 441 } else { | 426 } else { |
| 442 return "Error scanline decoder is nullptr"; | 427 return "Error scanline decoder is nullptr"; |
| 443 } | 428 } |
| 444 } | 429 } |
| 445 //skip to first line of subset | 430 //skip to first line of subset |
| 446 const SkCodec::Result skipResult = decoder->skipScanlines(y)
; | 431 const SkCodec::Result skipResult = codec->skipScanlines(y); |
| 447 switch (skipResult) { | 432 switch (skipResult) { |
| 448 case SkCodec::kSuccess: | 433 case SkCodec::kSuccess: |
| 449 case SkCodec::kIncompleteInput: | 434 case SkCodec::kIncompleteInput: |
| 450 break; | 435 break; |
| 451 default: | 436 default: |
| 452 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" | 437 return SkStringPrintf("%s failed after attempting to
skip %d scanlines" |
| 453 "with error message %d", fPath.c_str(), y, (
int) skipResult); | 438 "with error message %d", fPath.c_str(), y, (
int) skipResult); |
| 454 } | 439 } |
| 455 //create and set size of subsetBm | 440 //create and set size of subsetBm |
| 456 SkBitmap subsetBm; | 441 SkBitmap subsetBm; |
| 457 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); | 442 SkIRect bounds = SkIRect::MakeWH(subsetWidth, subsetHeight); |
| 458 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); | 443 bounds.setXYWH(0, 0, currentSubsetWidth, currentSubsetHeight
); |
| 459 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); | 444 SkAssertResult(largestSubsetBm.extractSubset(&subsetBm, boun
ds)); |
| 460 SkAutoLockPixels autlockSubsetBm(subsetBm, true); | 445 SkAutoLockPixels autlockSubsetBm(subsetBm, true); |
| 461 const SkCodec::Result subsetResult = | 446 const SkCodec::Result subsetResult = |
| 462 decoder->getScanlines(buffer, currentSubsetHeight, r
owBytes); | 447 codec->getScanlines(buffer, currentSubsetHeight, row
Bytes); |
| 463 switch (subsetResult) { | 448 switch (subsetResult) { |
| 464 case SkCodec::kSuccess: | 449 case SkCodec::kSuccess: |
| 465 case SkCodec::kIncompleteInput: | 450 case SkCodec::kIncompleteInput: |
| 466 break; | 451 break; |
| 467 default: | 452 default: |
| 468 return SkStringPrintf("%s failed with error message
%d", | 453 return SkStringPrintf("%s failed with error message
%d", |
| 469 fPath.c_str(), (int) subsetResult); | 454 fPath.c_str(), (int) subsetResult); |
| 470 } | 455 } |
| 471 const size_t bpp = decodeInfo.bytesPerPixel(); | 456 const size_t bpp = decodeInfo.bytesPerPixel(); |
| 472 /* | 457 /* |
| (...skipping 19 matching lines...) Expand all Loading... |
| 492 break; | 477 break; |
| 493 } | 478 } |
| 494 case kStripe_Mode: { | 479 case kStripe_Mode: { |
| 495 const int height = decodeInfo.height(); | 480 const int height = decodeInfo.height(); |
| 496 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that | 481 // This value is chosen arbitrarily. We exercise more cases by choo
sing a value that |
| 497 // does not align with image blocks. | 482 // does not align with image blocks. |
| 498 const int stripeHeight = 37; | 483 const int stripeHeight = 37; |
| 499 const int numStripes = (height + stripeHeight - 1) / stripeHeight; | 484 const int numStripes = (height + stripeHeight - 1) / stripeHeight; |
| 500 | 485 |
| 501 // Decode odd stripes | 486 // Decode odd stripes |
| 502 SkAutoTDelete<SkScanlineDecoder> decoder( | 487 if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL
, colorPtr, |
| 503 start_scanline_decoder(encoded.get(), decodeInfo, colorPtr,
colorCountPtr)); | 488 colorCountPtr) |
| 504 if (nullptr == decoder || | 489 || SkCodec::kTopDown_SkScanlineOrder != codec->getScanlineOr
der()) { |
| 505 SkScanlineDecoder::kTopDown_SkScanlineOrder != decoder->getS
canlineOrder()) { | |
| 506 // This mode was designed to test the new skip scanlines API in
libjpeg-turbo. | 490 // 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 | 491 // 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. | 492 // 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"); | 493 return Error::Nonfatal("Could not start top-down scanline decode
r"); |
| 510 } | 494 } |
| 511 for (int i = 0; i < numStripes; i += 2) { | 495 for (int i = 0; i < numStripes; i += 2) { |
| 512 // Skip a stripe | 496 // Skip a stripe |
| 513 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); | 497 const int linesToSkip = SkTMin(stripeHeight, height - i * stripe
Height); |
| 514 SkCodec::Result result = decoder->skipScanlines(linesToSkip); | 498 SkCodec::Result result = codec->skipScanlines(linesToSkip); |
| 515 switch (result) { | 499 switch (result) { |
| 516 case SkCodec::kSuccess: | 500 case SkCodec::kSuccess: |
| 517 case SkCodec::kIncompleteInput: | 501 case SkCodec::kIncompleteInput: |
| 518 break; | 502 break; |
| 519 default: | 503 default: |
| 520 return SkStringPrintf("Cannot skip scanlines for %s.", f
Path.c_str()); | 504 return SkStringPrintf("Cannot skip scanlines for %s.", f
Path.c_str()); |
| 521 } | 505 } |
| 522 | 506 |
| 523 // Read a stripe | 507 // Read a stripe |
| 524 const int startY = (i + 1) * stripeHeight; | 508 const int startY = (i + 1) * stripeHeight; |
| 525 const int linesToRead = SkTMin(stripeHeight, height - startY); | 509 const int linesToRead = SkTMin(stripeHeight, height - startY); |
| 526 if (linesToRead > 0) { | 510 if (linesToRead > 0) { |
| 527 result = decoder->getScanlines(bitmap.getAddr(0, startY), | 511 result = codec->getScanlines(bitmap.getAddr(0, startY), |
| 528 linesToRead, bitmap.rowBytes()); | 512 linesToRead, bitmap.rowBytes()); |
| 529 switch (result) { | 513 switch (result) { |
| 530 case SkCodec::kSuccess: | 514 case SkCodec::kSuccess: |
| 531 case SkCodec::kIncompleteInput: | 515 case SkCodec::kIncompleteInput: |
| 532 break; | 516 break; |
| 533 default: | 517 default: |
| 534 return SkStringPrintf("Cannot get scanlines for %s."
, fPath.c_str()); | 518 return SkStringPrintf("Cannot get scanlines for %s."
, fPath.c_str()); |
| 535 } | 519 } |
| 536 } | 520 } |
| 537 } | 521 } |
| 538 | 522 |
| 539 // Decode even stripes | 523 // Decode even stripes |
| 540 const SkCodec::Result startResult = decoder->start(decodeInfo, nullp
tr, colorPtr, | 524 const SkCodec::Result startResult = codec->startScanlineDecode(decod
eInfo, nullptr, |
| 541 colorCountPtr); | 525 colorPtr, colorCountPtr); |
| 542 if (SkCodec::kSuccess != startResult) { | 526 if (SkCodec::kSuccess != startResult) { |
| 543 return "Failed to restart scanline decoder with same parameters.
"; | 527 return "Failed to restart scanline decoder with same parameters.
"; |
| 544 } | 528 } |
| 545 for (int i = 0; i < numStripes; i += 2) { | 529 for (int i = 0; i < numStripes; i += 2) { |
| 546 // Read a stripe | 530 // Read a stripe |
| 547 const int startY = i * stripeHeight; | 531 const int startY = i * stripeHeight; |
| 548 const int linesToRead = SkTMin(stripeHeight, height - startY); | 532 const int linesToRead = SkTMin(stripeHeight, height - startY); |
| 549 SkCodec::Result result = decoder->getScanlines(bitmap.getAddr(0,
startY), | 533 SkCodec::Result result = codec->getScanlines(bitmap.getAddr(0, s
tartY), |
| 550 linesToRead, bitmap.rowBytes()); | 534 linesToRead, bitmap.rowBytes()); |
| 551 switch (result) { | 535 switch (result) { |
| 552 case SkCodec::kSuccess: | 536 case SkCodec::kSuccess: |
| 553 case SkCodec::kIncompleteInput: | 537 case SkCodec::kIncompleteInput: |
| 554 break; | 538 break; |
| 555 default: | 539 default: |
| 556 return SkStringPrintf("Cannot get scanlines for %s.", fP
ath.c_str()); | 540 return SkStringPrintf("Cannot get scanlines for %s.", fP
ath.c_str()); |
| 557 } | 541 } |
| 558 | 542 |
| 559 // Skip a stripe | 543 // Skip a stripe |
| 560 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) *
stripeHeight); | 544 const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) *
stripeHeight); |
| 561 if (linesToSkip > 0) { | 545 if (linesToSkip > 0) { |
| 562 result = decoder->skipScanlines(linesToSkip); | 546 result = codec->skipScanlines(linesToSkip); |
| 563 switch (result) { | 547 switch (result) { |
| 564 case SkCodec::kSuccess: | 548 case SkCodec::kSuccess: |
| 565 case SkCodec::kIncompleteInput: | 549 case SkCodec::kIncompleteInput: |
| 566 break; | 550 break; |
| 567 default: | 551 default: |
| 568 return SkStringPrintf("Cannot skip scanlines for %s.
", fPath.c_str()); | 552 return SkStringPrintf("Cannot skip scanlines for %s.
", fPath.c_str()); |
| 569 } | 553 } |
| 570 } | 554 } |
| 571 } | 555 } |
| 572 canvas->drawBitmap(bitmap, 0, 0); | 556 canvas->drawBitmap(bitmap, 0, 0); |
| (...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 skr.visit<void>(i, drawsAsSingletonPictures); | 1246 skr.visit<void>(i, drawsAsSingletonPictures); |
| 1263 } | 1247 } |
| 1264 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 1248 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
| 1265 | 1249 |
| 1266 canvas->drawPicture(macroPic); | 1250 canvas->drawPicture(macroPic); |
| 1267 return ""; | 1251 return ""; |
| 1268 }); | 1252 }); |
| 1269 } | 1253 } |
| 1270 | 1254 |
| 1271 } // namespace DM | 1255 } // namespace DM |
| OLD | NEW |