| Index: dm/DMSrcSink.cpp
|
| diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
|
| index a98ba41d18823542f20c00a5d3c02b55019f7b31..1155395f4042c34745a9d86285f5f3f6bc5529fd 100644
|
| --- a/dm/DMSrcSink.cpp
|
| +++ b/dm/DMSrcSink.cpp
|
| @@ -275,7 +275,7 @@ bool CodecSrc::veto(SinkFlags flags) const {
|
| }
|
|
|
| // Allows us to test decodes to non-native 8888.
|
| -void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType) {
|
| +static void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType) {
|
| if (CodecSrc::kNonNative8888_Always_DstColorType != dstColorType) {
|
| return;
|
| }
|
| @@ -288,7 +288,7 @@ void swap_rb_if_necessary(SkBitmap& bitmap, CodecSrc::DstColorType dstColorType)
|
|
|
| // FIXME: Currently we cannot draw unpremultiplied sources. skbug.com/3338 and skbug.com/3339.
|
| // This allows us to still test unpremultiplied decodes.
|
| -void premultiply_if_necessary(SkBitmap& bitmap) {
|
| +static void premultiply_if_necessary(SkBitmap& bitmap) {
|
| if (kUnpremul_SkAlphaType != bitmap.alphaType()) {
|
| return;
|
| }
|
| @@ -316,8 +316,8 @@ void premultiply_if_necessary(SkBitmap& bitmap) {
|
| bitmap.setAlphaType(kPremul_SkAlphaType);
|
| }
|
|
|
| -bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
|
| - CodecSrc::DstColorType dstColorType) {
|
| +static bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
|
| + CodecSrc::DstColorType dstColorType) {
|
| switch (dstColorType) {
|
| case CodecSrc::kIndex8_Always_DstColorType:
|
| if (kRGB_565_SkColorType == canvasColorType) {
|
| @@ -354,6 +354,17 @@ bool get_decode_info(SkImageInfo* decodeInfo, SkColorType canvasColorType,
|
| return true;
|
| }
|
|
|
| +static void draw_to_canvas(SkCanvas* canvas, const SkImageInfo& info, void* pixels, size_t rowBytes,
|
| + SkPMColor* colorPtr, int colorCount, CodecSrc::DstColorType dstColorType,
|
| + SkScalar left = 0, SkScalar top = 0) {
|
| + SkAutoTUnref<SkColorTable> colorTable(new SkColorTable(colorPtr, colorCount));
|
| + SkBitmap bitmap;
|
| + bitmap.installPixels(info, pixels, rowBytes, colorTable.get(), nullptr, nullptr);
|
| + premultiply_if_necessary(bitmap);
|
| + swap_rb_if_necessary(bitmap, dstColorType);
|
| + canvas->drawBitmap(bitmap, left, top);
|
| +}
|
| +
|
| Error CodecSrc::draw(SkCanvas* canvas) const {
|
| SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
|
| if (!encoded) {
|
| @@ -383,24 +394,15 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| }
|
| decodeInfo = decodeInfo.makeWH(size.width(), size.height());
|
|
|
| - // Construct a color table for the decode if necessary
|
| - SkAutoTUnref<SkColorTable> colorTable(nullptr);
|
| - SkPMColor* colorPtr = nullptr;
|
| - int* colorCountPtr = nullptr;
|
| - int maxColors = 256;
|
| - if (kIndex_8_SkColorType == decodeInfo.colorType()) {
|
| - SkPMColor colors[256];
|
| - colorTable.reset(new SkColorTable(colors, maxColors));
|
| - colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
|
| - colorCountPtr = &maxColors;
|
| - }
|
| + const int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
|
| + const size_t rowBytes = size.width() * bpp;
|
| + SkAutoMalloc pixels(decodeInfo.getSafeSize(rowBytes));
|
| + SkPMColor colorPtr[256];
|
| + int colorCount = 256;
|
|
|
| - SkBitmap bitmap;
|
| - SkPixelRefFactory* factory = nullptr;
|
| - SkMallocPixelRef::ZeroedPRFactory zeroFactory;
|
| SkCodec::Options options;
|
| if (kCodecZeroInit_Mode == fMode) {
|
| - factory = &zeroFactory;
|
| + memset(pixels.get(), 0, size.height() * rowBytes);
|
| options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
|
| }
|
|
|
| @@ -409,16 +411,12 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| kBGRA_8888_SkColorType == decodeInfo.colorType()) {
|
| bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
|
| }
|
| - if (!bitmap.tryAllocPixels(bitmapInfo, factory, colorTable.get())) {
|
| - return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
|
| - decodeInfo.width(), decodeInfo.height());
|
| - }
|
|
|
| switch (fMode) {
|
| case kCodecZeroInit_Mode:
|
| case kCodec_Mode: {
|
| - switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options,
|
| - colorPtr, colorCountPtr)) {
|
| + switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options,
|
| + colorPtr, &colorCount)) {
|
| case SkCodec::kSuccess:
|
| // We consider incomplete to be valid, since we should still decode what is
|
| // available.
|
| @@ -428,19 +426,18 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| // Everything else is considered a failure.
|
| return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
|
| }
|
| - premultiply_if_necessary(bitmap);
|
| - swap_rb_if_necessary(bitmap, fDstColorType);
|
| - canvas->drawBitmap(bitmap, 0, 0);
|
| +
|
| + draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, colorPtr, colorCount,
|
| + fDstColorType);
|
| break;
|
| }
|
| case kScanline_Mode: {
|
| if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr,
|
| - colorCountPtr)) {
|
| + &colorCount)) {
|
| return "Could not start scanline decoder";
|
| }
|
|
|
| - void* dst = bitmap.getAddr(0, 0);
|
| - size_t rowBytes = bitmap.rowBytes();
|
| + void* dst = pixels.get();
|
| uint32_t height = decodeInfo.height();
|
| switch (codec->getScanlineOrder()) {
|
| case SkCodec::kTopDown_SkScanlineOrder:
|
| @@ -453,19 +450,17 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| case SkCodec::kOutOfOrder_SkScanlineOrder: {
|
| for (int y = 0; y < decodeInfo.height(); y++) {
|
| int dstY = codec->outputScanline(y);
|
| - void* dstPtr = bitmap.getAddr(0, dstY);
|
| + void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY);
|
| // We complete the loop, even if this call begins to fail
|
| // due to an incomplete image. This ensures any uninitialized
|
| // memory will be filled with the proper value.
|
| - codec->getScanlines(dstPtr, 1, bitmap.rowBytes());
|
| + codec->getScanlines(dstPtr, 1, rowBytes);
|
| }
|
| break;
|
| }
|
| }
|
|
|
| - premultiply_if_necessary(bitmap);
|
| - swap_rb_if_necessary(bitmap, fDstColorType);
|
| - canvas->drawBitmap(bitmap, 0, 0);
|
| + draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, colorPtr, colorCount, fDstColorType);
|
| break;
|
| }
|
| case kStripe_Mode: {
|
| @@ -474,10 +469,11 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| // does not align with image blocks.
|
| const int stripeHeight = 37;
|
| const int numStripes = (height + stripeHeight - 1) / stripeHeight;
|
| + void* dst = pixels.get();
|
|
|
| // Decode odd stripes
|
| - if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, NULL, colorPtr,
|
| - colorCountPtr)) {
|
| + if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, nullptr, colorPtr,
|
| + &colorCount)) {
|
| return "Could not start scanline decoder";
|
| }
|
|
|
| @@ -496,13 +492,14 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| const int startY = (i + 1) * stripeHeight;
|
| const int linesToRead = SkTMin(stripeHeight, height - startY);
|
| if (linesToRead > 0) {
|
| - codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
|
| + codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
|
| + rowBytes);
|
| }
|
| }
|
|
|
| // Decode even stripes
|
| const SkCodec::Result startResult = codec->startScanlineDecode(decodeInfo, nullptr,
|
| - colorPtr, colorCountPtr);
|
| + colorPtr, &colorCount);
|
| if (SkCodec::kSuccess != startResult) {
|
| return "Failed to restart scanline decoder with same parameters.";
|
| }
|
| @@ -510,7 +507,8 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| // Read a stripe
|
| const int startY = i * stripeHeight;
|
| const int linesToRead = SkTMin(stripeHeight, height - startY);
|
| - codec->getScanlines(bitmap.getAddr(0, startY), linesToRead, bitmap.rowBytes());
|
| + codec->getScanlines(SkTAddOffset<void>(dst, rowBytes * startY), linesToRead,
|
| + rowBytes);
|
|
|
| // Skip a stripe
|
| const int linesToSkip = SkTMin(stripeHeight, height - (i + 1) * stripeHeight);
|
| @@ -518,9 +516,8 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| codec->skipScanlines(linesToSkip);
|
| }
|
| }
|
| - premultiply_if_necessary(bitmap);
|
| - swap_rb_if_necessary(bitmap, fDstColorType);
|
| - canvas->drawBitmap(bitmap, 0, 0);
|
| +
|
| + draw_to_canvas(canvas, bitmapInfo, dst, rowBytes, colorPtr, colorCount, fDstColorType);
|
| break;
|
| }
|
| case kCroppedScanline_Mode: {
|
| @@ -537,16 +534,15 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| subset = SkIRect::MakeXYWH(x, 0, SkTMin(tileSize, width - x), height);
|
| opts.fSubset = ⊂
|
| if (SkCodec::kSuccess != codec->startScanlineDecode(decodeInfo, &opts,
|
| - colorPtr, colorCountPtr)) {
|
| + colorPtr, &colorCount)) {
|
| return "Could not start scanline decoder.";
|
| }
|
|
|
| - codec->getScanlines(bitmap.getAddr(x, 0), height, bitmap.rowBytes());
|
| + codec->getScanlines(SkTAddOffset<void>(pixels.get(), x * bpp), height, rowBytes);
|
| }
|
|
|
| - premultiply_if_necessary(bitmap);
|
| - swap_rb_if_necessary(bitmap, fDstColorType);
|
| - canvas->drawBitmap(bitmap, 0, 0);
|
| + draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, colorPtr, colorCount,
|
| + fDstColorType);
|
| break;
|
| }
|
| case kSubset_Mode: {
|
| @@ -569,7 +565,7 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| opts.fSubset = ⊂
|
| SkBitmap subsetBm;
|
| // We will reuse pixel memory from bitmap.
|
| - void* pixels = bitmap.getPixels();
|
| + void* dst = pixels.get();
|
| // 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().
|
| @@ -588,13 +584,9 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| const int scaledH = SkTMax(1, SkScalarRoundToInt(preScaleH * fScale));
|
| decodeInfo = decodeInfo.makeWH(scaledW, scaledH);
|
| SkImageInfo subsetBitmapInfo = bitmapInfo.makeWH(scaledW, scaledH);
|
| - size_t rowBytes = subsetBitmapInfo.minRowBytes();
|
| - if (!subsetBm.installPixels(subsetBitmapInfo, pixels, rowBytes, colorTable.get(),
|
| - nullptr, nullptr)) {
|
| - return SkStringPrintf("could not install pixels for %s.", fPath.c_str());
|
| - }
|
| - const SkCodec::Result result = codec->getPixels(decodeInfo, pixels, rowBytes,
|
| - &opts, colorPtr, colorCountPtr);
|
| + size_t subsetRowBytes = subsetBitmapInfo.minRowBytes();
|
| + const SkCodec::Result result = codec->getPixels(decodeInfo, dst, subsetRowBytes,
|
| + &opts, colorPtr, &colorCount);
|
| switch (result) {
|
| case SkCodec::kSuccess:
|
| case SkCodec::kIncompleteInput:
|
| @@ -605,9 +597,10 @@ Error CodecSrc::draw(SkCanvas* canvas) const {
|
| x, y, decodeInfo.width(), decodeInfo.height(),
|
| fPath.c_str(), W, H, result);
|
| }
|
| - premultiply_if_necessary(subsetBm);
|
| - swap_rb_if_necessary(subsetBm, fDstColorType);
|
| - canvas->drawBitmap(subsetBm, SkIntToScalar(left), SkIntToScalar(top));
|
| + draw_to_canvas(canvas, subsetBitmapInfo, dst, subsetRowBytes, colorPtr,
|
| + colorCount, fDstColorType, SkIntToScalar(left),
|
| + SkIntToScalar(top));
|
| +
|
| // translate by the scaled height.
|
| top += decodeInfo.height();
|
| }
|
| @@ -681,17 +674,11 @@ Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
|
| }
|
| decodeInfo = decodeInfo.makeWH(size.width(), size.height());
|
|
|
| - // Construct a color table for the decode if necessary
|
| - SkAutoTUnref<SkColorTable> colorTable(nullptr);
|
| - SkPMColor* colorPtr = nullptr;
|
| - int* colorCountPtr = nullptr;
|
| - int maxColors = 256;
|
| - if (kIndex_8_SkColorType == decodeInfo.colorType()) {
|
| - SkPMColor colors[256];
|
| - colorTable.reset(new SkColorTable(colors, maxColors));
|
| - colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
|
| - colorCountPtr = &maxColors;
|
| - }
|
| + int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
|
| + size_t rowBytes = size.width() * bpp;
|
| + SkAutoMalloc pixels(size.height() * rowBytes);
|
| + SkPMColor colorPtr[256];
|
| + int colorCount = 256;
|
|
|
| SkBitmap bitmap;
|
| SkImageInfo bitmapInfo = decodeInfo;
|
| @@ -699,27 +686,21 @@ Error AndroidCodecSrc::draw(SkCanvas* canvas) const {
|
| kBGRA_8888_SkColorType == decodeInfo.colorType()) {
|
| bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
|
| }
|
| - if (!bitmap.tryAllocPixels(bitmapInfo, nullptr, colorTable.get())) {
|
| - return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
|
| - decodeInfo.width(), decodeInfo.height());
|
| - }
|
|
|
| // Create options for the codec.
|
| SkAndroidCodec::AndroidOptions options;
|
| options.fColorPtr = colorPtr;
|
| - options.fColorCount = colorCountPtr;
|
| + options.fColorCount = &colorCount;
|
| options.fSampleSize = fSampleSize;
|
|
|
| - switch (codec->getAndroidPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), &options)) {
|
| + switch (codec->getAndroidPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
|
| case SkCodec::kSuccess:
|
| case SkCodec::kIncompleteInput:
|
| break;
|
| default:
|
| return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
|
| }
|
| - premultiply_if_necessary(bitmap);
|
| - swap_rb_if_necessary(bitmap, fDstColorType);
|
| - canvas->drawBitmap(bitmap, 0, 0);
|
| + draw_to_canvas(canvas, bitmapInfo, pixels.get(), rowBytes, colorPtr, colorCount, fDstColorType);
|
| return "";
|
| }
|
|
|
| @@ -820,31 +801,18 @@ Error ImageGenSrc::draw(SkCanvas* canvas) const {
|
| return Error::Nonfatal("Avoid requesting non-opaque kGray8 decodes.");
|
| }
|
|
|
| - SkAutoTUnref<SkColorTable> colorTable(nullptr);
|
| - SkPMColor* colorPtr = nullptr;
|
| - int* colorCountPtr = nullptr;
|
| - int maxColors = 256;
|
| - if (kIndex_8_SkColorType == decodeInfo.colorType()) {
|
| - SkPMColor colors[256];
|
| - colorTable.reset(new SkColorTable(colors, maxColors));
|
| - colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
|
| - colorCountPtr = &maxColors;
|
| - }
|
| + int bpp = SkColorTypeBytesPerPixel(decodeInfo.colorType());
|
| + size_t rowBytes = decodeInfo.width() * bpp;
|
| + SkAutoMalloc pixels(decodeInfo.height() * rowBytes);
|
| + SkPMColor colorPtr[256];
|
| + int colorCount = 256;
|
|
|
| - SkBitmap bitmap;
|
| - if (!bitmap.tryAllocPixels(decodeInfo, nullptr, colorTable.get())) {
|
| - return SkStringPrintf("Image(%s) is too large (%d x %d)", fPath.c_str(),
|
| - decodeInfo.width(), decodeInfo.height());
|
| - }
|
| -
|
| - if (!gen->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes(), colorPtr,
|
| - colorCountPtr))
|
| - {
|
| + if (!gen->getPixels(decodeInfo, pixels.get(), rowBytes, colorPtr, &colorCount)) {
|
| return SkStringPrintf("Image generator could not getPixels() for %s\n", fPath.c_str());
|
| }
|
|
|
| - premultiply_if_necessary(bitmap);
|
| - canvas->drawBitmap(bitmap, 0, 0);
|
| + draw_to_canvas(canvas, decodeInfo, pixels.get(), rowBytes, colorPtr, colorCount,
|
| + CodecSrc::kGetFromCanvas_DstColorType);
|
| return "";
|
| }
|
|
|
|
|