| 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 |