| Index: dm/DMSrcSink.cpp
|
| diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
|
| index 38597b6946994c06d8cc24971dc018163ff41b14..fd1331366dd34b07761e57e5c5e91e13dc4cea9f 100644
|
| --- a/dm/DMSrcSink.cpp
|
| +++ b/dm/DMSrcSink.cpp
|
| @@ -355,6 +355,83 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| canvas->drawBitmap(bitmap, 0, 0);
|
| break;
|
| }
|
| + case kSubset_Mode: {
|
| + // Arbitrarily choose a divisor.
|
| + int divisor = 2;
|
| + // Total width/height of the image.
|
| + const int W = codec->getInfo().width();
|
| + const int H = codec->getInfo().height();
|
| + if (divisor > W || divisor > H) {
|
| + return Error::Nonfatal(SkStringPrintf("Cannot codec subset: divisor %d is too big "
|
| + "for %s with dimensions (%d x %d)", divisor,
|
| + fPath.c_str(), W, H));
|
| + }
|
| + // subset dimensions
|
| + // SkWebpCodec, the only one that supports subsets, requires even top/left boundaries.
|
| + const int w = SkAlign2(W / divisor);
|
| + const int h = SkAlign2(H / divisor);
|
| + SkIRect subset;
|
| + SkCodec::Options opts;
|
| + opts.fSubset = ⊂
|
| + SkBitmap subsetBm;
|
| + // We will reuse pixel memory from bitmap.
|
| + void* pixels = bitmap.getPixels();
|
| + // Keep track of left and top (for drawing subsetBm into canvas). We could use
|
| + // fScale * x and fScale * y, but we want integers such that the next subset will start
|
| + // where the last one ended. So we'll add decodeInfo.width() and height().
|
| + int left = 0;
|
| + for (int x = 0; x < W; x += w) {
|
| + int top = 0;
|
| + for (int y = 0; y < H; y+= h) {
|
| + // Do not make the subset go off the edge of the image.
|
| + const int preScaleW = SkTMin(w, W - x);
|
| + const int preScaleH = SkTMin(h, H - y);
|
| + subset.setXYWH(x, y, preScaleW, preScaleH);
|
| + // And scale
|
| + // FIXME: Should we have a version of getScaledDimensions that takes a subset
|
| + // into account?
|
| + decodeInfo = decodeInfo.makeWH(SkScalarRoundToInt(preScaleW * fScale),
|
| + SkScalarRoundToInt(preScaleH * fScale));
|
| + size_t rowBytes = decodeInfo.minRowBytes();
|
| + if (!subsetBm.installPixels(decodeInfo, pixels, rowBytes, colorTable.get(),
|
| + NULL, NULL)) {
|
| + return SkStringPrintf("could not install pixels for %s.", fPath.c_str());
|
| + }
|
| + const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
|
| + &opts, colorPtr, colorCountPtr);
|
| + switch (result) {
|
| + case SkCodec::kSuccess:
|
| + case SkCodec::kIncompleteInput:
|
| + break;
|
| + case SkCodec::kInvalidConversion:
|
| + if (0 == (x|y)) {
|
| + // First subset is okay to return unimplemented.
|
| + return Error::Nonfatal("Incompatible colortype conversion");
|
| + }
|
| + // If the first subset succeeded, a later one should not fail.
|
| + // fall through to failure
|
| + case SkCodec::kUnimplemented:
|
| + if (0 == (x|y)) {
|
| + // First subset is okay to return unimplemented.
|
| + return Error::Nonfatal("subset codec not supported");
|
| + }
|
| + // If the first subset succeeded, why would a later one fail?
|
| + // fall through to failure
|
| + default:
|
| + return SkStringPrintf("subset codec failed to decode (%d, %d, %d, %d) "
|
| + "from %s with dimensions (%d x %d)\t error %d",
|
| + x, y, decodeInfo.width(), decodeInfo.height(),
|
| + fPath.c_str(), W, H, result);
|
| + }
|
| + canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToScalar(top));
|
| + // translate by the scaled height.
|
| + top += decodeInfo.height();
|
| + }
|
| + // translate by the scaled width.
|
| + left += decodeInfo.width();
|
| + }
|
| + return "";
|
| + }
|
| }
|
| return "";
|
| }
|
|
|