| 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" |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 return flags.type != SinkFlags::kRaster | 242 return flags.type != SinkFlags::kRaster |
| 243 || flags.approach != SinkFlags::kDirect; | 243 || flags.approach != SinkFlags::kDirect; |
| 244 } | 244 } |
| 245 | 245 |
| 246 Error CodecSrc::draw(SkCanvas* canvas) const { | 246 Error CodecSrc::draw(SkCanvas* canvas) const { |
| 247 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 247 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
| 248 if (!encoded) { | 248 if (!encoded) { |
| 249 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); | 249 return SkStringPrintf("Couldn't read %s.", fPath.c_str()); |
| 250 } | 250 } |
| 251 SkAutoTDelete<SkCodec> codec(NULL); | 251 SkAutoTDelete<SkCodec> codec(NULL); |
| 252 if (kScaledCodec_Mode == fMode) { | 252 if (kScaledCodec_Mode == fMode || kSubset_Mode == fMode) { |
| 253 codec.reset(SkScaledCodec::NewFromData(encoded)); | 253 codec.reset(SkScaledCodec::NewFromData(encoded)); |
| 254 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled | 254 // TODO (msarett): This should fall through to a fatal error once we sup
port scaled |
| 255 // codecs for all image types. | 255 // codecs for all image types. |
| 256 if (nullptr == codec.get()) { | 256 if (nullptr == codec.get()) { |
| 257 return Error::Nonfatal(SkStringPrintf("Couldn't create scaled codec
for %s.", | 257 return Error::Nonfatal(SkStringPrintf("Couldn't create scaled codec
for %s.", |
| 258 fPath.c_str())); | 258 fPath.c_str())); |
| 259 } | 259 } |
| 260 } else { | 260 } else { |
| 261 codec.reset(SkCodec::NewFromData(encoded)); | 261 codec.reset(SkCodec::NewFromData(encoded)); |
| 262 } | 262 } |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 int divisor = 2; | 505 int divisor = 2; |
| 506 // Total width/height of the image. | 506 // Total width/height of the image. |
| 507 const int W = codec->getInfo().width(); | 507 const int W = codec->getInfo().width(); |
| 508 const int H = codec->getInfo().height(); | 508 const int H = codec->getInfo().height(); |
| 509 if (divisor > W || divisor > H) { | 509 if (divisor > W || divisor > H) { |
| 510 return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divi
sor %d is too big " | 510 return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divi
sor %d is too big " |
| 511 "for %s with dimensions (%
d x %d)", divisor, | 511 "for %s with dimensions (%
d x %d)", divisor, |
| 512 fPath.c_str(), W, H)); | 512 fPath.c_str(), W, H)); |
| 513 } | 513 } |
| 514 // subset dimensions | 514 // subset dimensions |
| 515 // SkWebpCodec, the only one that supports subsets, requires even to
p/left boundaries. | 515 const int w = W / divisor; |
| 516 const int w = SkAlign2(W / divisor); | 516 const int h = H / divisor; |
| 517 const int h = SkAlign2(H / divisor); | |
| 518 SkIRect subset; | 517 SkIRect subset; |
| 518 SkISize scaledSize; |
| 519 SkIRect scaledSubset; |
| 519 SkCodec::Options opts; | 520 SkCodec::Options opts; |
| 520 opts.fSubset = ⊂ | 521 opts.fSubset = ⊂ |
| 522 opts.fScaledDimensions = &scaledSize; |
| 523 opts.fScaledSubset = &scaledSubset; |
| 521 SkBitmap subsetBm; | 524 SkBitmap subsetBm; |
| 522 // We will reuse pixel memory from bitmap. | 525 // We will reuse pixel memory from bitmap. |
| 523 void* pixels = bitmap.getPixels(); | 526 void* pixels = bitmap.getPixels(); |
| 524 // Keep track of left and top (for drawing subsetBm into canvas). We
could use | 527 // Keep track of left and top (for drawing subsetBm into canvas). We
could use |
| 525 // fScale * x and fScale * y, but we want integers such that the nex
t subset will start | 528 // fScale * x and fScale * y, but we want integers such that the nex
t subset will start |
| 526 // where the last one ended. So we'll add decodeInfo.width() and hei
ght(). | 529 // where the last one ended. So we'll add decodeInfo.width() and hei
ght(). |
| 527 int left = 0; | 530 int left = 0; |
| 528 for (int x = 0; x < W; x += w) { | 531 for (int x = 0; x < W; x += w) { |
| 529 int top = 0; | 532 int top = 0; |
| 530 for (int y = 0; y < H; y+= h) { | 533 for (int y = 0; y < H; y+= h) { |
| 531 // Do not make the subset go off the edge of the image. | 534 // Do not make the subset go off the edge of the image. |
| 532 const int preScaleW = SkTMin(w, W - x); | 535 const int preScaleW = SkTMin(w, W - x); |
| 533 const int preScaleH = SkTMin(h, H - y); | 536 const int preScaleH = SkTMin(h, H - y); |
| 534 subset.setXYWH(x, y, preScaleW, preScaleH); | 537 subset.setXYWH(x, y, preScaleW, preScaleH); |
| 535 // And scale | 538 // And scale |
| 536 // FIXME: Should we have a version of getScaledDimensions th
at takes a subset | 539 if (!codec->getScaledSubsetDimensions(fScale, opts)) { |
| 537 // into account? | 540 return Error::Nonfatal("Subsetting not supported.\n"); |
| 538 decodeInfo = decodeInfo.makeWH( | 541 } |
| 539 SkTMax(1, SkScalarRoundToInt(preScaleW * fScale)), | 542 decodeInfo = decodeInfo.makeWH(scaledSubset.width(), scaledS
ubset.height()); |
| 540 SkTMax(1, SkScalarRoundToInt(preScaleH * fScale))); | |
| 541 size_t rowBytes = decodeInfo.minRowBytes(); | 543 size_t rowBytes = decodeInfo.minRowBytes(); |
| 542 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co
lorTable.get(), | 544 if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, co
lorTable.get(), |
| 543 nullptr, nullptr)) { | 545 nullptr, nullptr)) { |
| 544 return SkStringPrintf("could not install pixels for %s."
, fPath.c_str()); | 546 return SkStringPrintf("could not install pixels for %s."
, fPath.c_str()); |
| 545 } | 547 } |
| 546 const SkCodec::Result result = codec->getPixels(decodeInfo,
pixels, rowBytes, | 548 const SkCodec::Result result = codec->getPixels(decodeInfo,
pixels, rowBytes, |
| 547 &opts, colorPtr, colorCountPtr); | 549 &opts, colorPtr, colorCountPtr); |
| 548 switch (result) { | 550 switch (result) { |
| 549 case SkCodec::kSuccess: | 551 case SkCodec::kSuccess: |
| 550 case SkCodec::kIncompleteInput: | 552 case SkCodec::kIncompleteInput: |
| 551 break; | 553 break; |
| 552 case SkCodec::kInvalidConversion: | 554 case SkCodec::kInvalidConversion: |
| 553 if (0 == (x|y)) { | 555 if (0 == (x|y)) { |
| 554 // First subset is okay to return unimplemented. | 556 // First subset is okay to return invalid conver
sion. |
| 555 return Error::Nonfatal("Incompatible colortype c
onversion"); | 557 return Error::Nonfatal("Incompatible colortype c
onversion"); |
| 556 } | 558 } |
| 557 // If the first subset succeeded, a later one should
not fail. | 559 // If the first subset succeeded, a later one should
not fail. |
| 558 // fall through to failure | 560 // fall through to failure |
| 559 case SkCodec::kUnimplemented: | |
| 560 if (0 == (x|y)) { | |
| 561 // First subset is okay to return unimplemented. | |
| 562 return Error::Nonfatal("subset codec not support
ed"); | |
| 563 } | |
| 564 // If the first subset succeeded, why would a later
one fail? | |
| 565 // fall through to failure | |
| 566 default: | 561 default: |
| 567 return SkStringPrintf("subset codec failed to decode
(%d, %d, %d, %d) " | 562 return SkStringPrintf("subset codec failed to decode
(%d, %d, %d, %d) " |
| 568 "from %s with dimensions (%d x
%d)\t error %d", | 563 "from %s with dimensions (%d x
%d)\t error %d", |
| 569 x, y, decodeInfo.width(), deco
deInfo.height(), | 564 x, y, decodeInfo.width(), deco
deInfo.height(), |
| 570 fPath.c_str(), W, H, result); | 565 fPath.c_str(), W, H, result); |
| 571 } | 566 } |
| 572 canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToSca
lar(top)); | 567 canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToSca
lar(top)); |
| 573 // translate by the scaled height. | 568 // translate by the scaled height. |
| 574 top += decodeInfo.height(); | 569 top += decodeInfo.height(); |
| 575 } | 570 } |
| 576 // translate by the scaled width. | 571 // translate by the scaled width. |
| 577 left += decodeInfo.width(); | 572 left += decodeInfo.width(); |
| 578 } | 573 } |
| 579 return ""; | 574 return ""; |
| 580 } | 575 } |
| 581 } | 576 } |
| 582 return ""; | 577 return ""; |
| 583 } | 578 } |
| 584 | 579 |
| 585 SkISize CodecSrc::size() const { | 580 SkISize CodecSrc::size() const { |
| 586 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); | 581 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str())); |
| 587 SkAutoTDelete<SkCodec> codec(nullptr); | 582 SkAutoTDelete<SkCodec> codec(nullptr); |
| 588 | 583 |
| 589 if (kScaledCodec_Mode == fMode) { | 584 if (kScaledCodec_Mode == fMode || kSubset_Mode == fMode) { |
| 590 codec.reset(SkScaledCodec::NewFromData(encoded)); | 585 codec.reset(SkScaledCodec::NewFromData(encoded)); |
| 591 } else { | 586 } else { |
| 592 codec.reset(SkCodec::NewFromData(encoded)); | 587 codec.reset(SkCodec::NewFromData(encoded)); |
| 593 } | 588 } |
| 594 | 589 |
| 595 if (nullptr == codec) { | 590 if (nullptr == codec) { |
| 596 return SkISize::Make(0, 0); | 591 return SkISize::Make(0, 0); |
| 597 } | 592 } |
| 598 return codec->getScaledDimensions(fScale); | 593 return codec->getScaledDimensions(fScale); |
| 599 } | 594 } |
| (...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 skr.visit<void>(i, drawsAsSingletonPictures); | 1195 skr.visit<void>(i, drawsAsSingletonPictures); |
| 1201 } | 1196 } |
| 1202 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); | 1197 SkAutoTUnref<SkPicture> macroPic(macroRec.endRecordingAsPicture()); |
| 1203 | 1198 |
| 1204 canvas->drawPicture(macroPic); | 1199 canvas->drawPicture(macroPic); |
| 1205 return ""; | 1200 return ""; |
| 1206 }); | 1201 }); |
| 1207 } | 1202 } |
| 1208 | 1203 |
| 1209 } // namespace DM | 1204 } // namespace DM |
| OLD | NEW |