Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Unified Diff: src/codec/SkScaledCodec.cpp

Issue 1406223002: Create an SkAndroidCodec API separate from SkCodec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/codec/SkScaledCodec.cpp
diff --git a/src/codec/SkScaledCodec.cpp b/src/codec/SkScaledCodec.cpp
index 6b50a09f268c3889e99831098980486aef235af7..84488235fb610b0336649cb1cd77d615851b9917 100644
--- a/src/codec/SkScaledCodec.cpp
+++ b/src/codec/SkScaledCodec.cpp
@@ -5,344 +5,289 @@
* found in the LICENSE file.
*/
+#include "SkCodec.h"
#include "SkCodecPriv.h"
#include "SkScaledCodec.h"
-#include "SkStream.h"
-#include "SkWebpCodec.h"
-
-SkCodec* SkScaledCodec::NewFromStream(SkStream* stream) {
- SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream));
- if (nullptr == codec) {
- return nullptr;
- }
-
- switch (codec->getEncodedFormat()) {
- case kWEBP_SkEncodedFormat:
- // Webp codec supports scaling and subsetting natively
- return codec.detach();
- case kPNG_SkEncodedFormat:
- case kJPEG_SkEncodedFormat:
- // wrap in new SkScaledCodec
- return new SkScaledCodec(codec.detach());
- default:
- // FIXME: SkScaledCodec is temporarily disabled for other formats
- // while focusing on the formats that are supported by
- // BitmapRegionDecoder.
- return nullptr;
- }
-}
-
-SkCodec* SkScaledCodec::NewFromData(SkData* data) {
- if (!data) {
- return nullptr;
- }
- return NewFromStream(new SkMemoryStream(data));
-}
-
-SkScaledCodec::SkScaledCodec(SkCodec* codec)
- : INHERITED(codec->getInfo(), nullptr)
+SkSampledCodec::SkSampledCodec(SkCodec* codec)
+ : INHERITED(codec->getInfo())
, fCodec(codec)
{}
-SkScaledCodec::~SkScaledCodec() {}
-
-bool SkScaledCodec::onRewind() {
- return fCodec->onRewind();
+static bool is_in_range(int coord, int offset, int length) {
scroggo 2015/10/16 21:13:55 I still need to look over this file in more detail
+ return coord >= offset && coord < offset + length;
}
-static SkISize best_scaled_dimensions(const SkISize& origDims, const SkISize& nativeDims,
- const SkISize& scaledCodecDims, float desiredScale) {
- if (nativeDims == scaledCodecDims) {
- // does not matter which to return if equal. Return here to skip below calculations
- return nativeDims;
+SkISize SkSampledCodec::onGetSampledDimensions(int sampleSize) const {
+ // Fast path for when we are not scaling.
+ if (1 == sampleSize) {
+ return fCodec->getInfo().dimensions();
}
- float idealWidth = origDims.width() * desiredScale;
- float idealHeight = origDims.height() * desiredScale;
-
- // calculate difference between native dimensions and ideal dimensions
- float nativeWDiff = SkTAbs(idealWidth - nativeDims.width());
- float nativeHDiff = SkTAbs(idealHeight - nativeDims.height());
- float nativeDiff = nativeWDiff + nativeHDiff;
- // Native scaling is preferred to sampling. If we can scale natively to
- // within one of the ideal value, we should choose to scale natively.
- if (nativeWDiff < 1.0f && nativeHDiff < 1.0f) {
- return nativeDims;
+ const int width = fCodec->getInfo().width();
+ const int height = fCodec->getInfo().height();
+
+ // Check if the codec can provide the scaling natively.
+ float scale = get_scale_from_sample_size(sampleSize);
+ SkSize idealSize = SkSize::Make(scale * (float) width, scale * (float) height);
+ SkISize nativeSize = fCodec->getScaledDimensions(scale);
+ float widthDiff = SkTAbs(((float) nativeSize.width()) - idealSize.width());
+ float heightDiff = SkTAbs(((float) nativeSize.height()) - idealSize.height());
+ if (widthDiff < 1.0f && heightDiff < 1.0f) {
+ return nativeSize;
}
- // calculate difference between scaledCodec dimensions and ideal dimensions
- float scaledCodecWDiff = SkTAbs(idealWidth - scaledCodecDims.width());
- float scaledCodecHDiff = SkTAbs(idealHeight - scaledCodecDims.height());
- float scaledCodecDiff = scaledCodecWDiff + scaledCodecHDiff;
-
- // return dimensions closest to ideal dimensions.
- // If the differences are equal, return nativeDims, as native scaling is more efficient.
- return nativeDiff > scaledCodecDiff ? scaledCodecDims : nativeDims;
+ // Provide the scaling by sampling.
+ return SkISize::Make(get_scaled_dimension(width, sampleSize),
+ get_scaled_dimension(height, sampleSize));
}
-/*
- * Return a valid set of output dimensions for this decoder, given an input scale
- */
-SkISize SkScaledCodec::onGetScaledDimensions(float desiredScale) const {
- SkISize nativeDimensions = fCodec->getScaledDimensions(desiredScale);
- // support scaling down by integer numbers. Ex: 1/2, 1/3, 1/4 ...
- SkISize scaledCodecDimensions;
- if (desiredScale > 0.5f) {
- // sampleSize = 1
- scaledCodecDimensions = fCodec->getInfo().dimensions();
+SkISize SkSampledCodec::onGetSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const {
scroggo 2015/10/19 20:03:20 Interesting - this function is no longer virtual (
msarett 2015/10/19 21:39:21 Yeah I agree that it makes sense but is a little w
+ // This call is less expensive than onGetSampledDimensions() because, regardless
+ // of the scaling method, we are free to choose how many of the pixels that we
+ // want to clip.
+ // Alternatively, we could call onGetSampledDimensions(), calculate the scale
+ // as a float and do our best to apply an identical scale here. But I'm not
+ // sure that there is any added benefit to that approach.
+
+ // We should, however, be sure that if the subset specifies the entire image,
+ // we will perform a full image decode.
+ if (fCodec->getInfo().dimensions() == subset.size()) {
+ return onGetSampledDimensions(sampleSize);
}
- // sampleSize determines the step size between samples
- // Ex: sampleSize = 2, sample every second pixel in x and y directions
- int sampleSize = int ((1.0f / desiredScale) + 0.5f);
- int scaledWidth = get_scaled_dimension(this->getInfo().width(), sampleSize);
- int scaledHeight = get_scaled_dimension(this->getInfo().height(), sampleSize);
+ return SkISize::Make(get_scaled_dimension(subset.width(), sampleSize),
+ get_scaled_dimension(subset.height(), sampleSize));
+}
- // Return the calculated output dimensions for the given scale
- scaledCodecDimensions = SkISize::Make(scaledWidth, scaledHeight);
+SkCodec::Result SkSampledCodec::onGetAndroidPixels(const SkImageInfo& info, void* pixels,
+ size_t rowBytes, AndroidOptions& options) {
+ // Create an Options struct for the codec.
+ SkCodec::Options codecOptions;
+ codecOptions.fZeroInitialized = options.fZeroInitialized;
- return best_scaled_dimensions(this->getInfo().dimensions(), nativeDimensions,
- scaledCodecDimensions, desiredScale);
-}
+ SkIRect* subset = options.fSubset;
+ if (!subset || subset->size() == fCodec->getInfo().dimensions()) {
+ // Try to use the native codec to perform the decode.
+ SkCodec::Result result = fCodec->getPixels(info, pixels, rowBytes, &codecOptions,
+ options.fColorPtr, options.fColorCount);
-// check if scaling to dstInfo size from srcInfo size using sampleSize is possible
-static bool scaling_supported(const SkISize& dstDim, const SkISize& srcDim,
- int* sampleX, int* sampleY) {
- SkScaledCodec::ComputeSampleSize(dstDim, srcDim, sampleX, sampleY);
- const int dstWidth = dstDim.width();
- const int dstHeight = dstDim.height();
- const int srcWidth = srcDim.width();
- const int srcHeight = srcDim.height();
- // only support down sampling, not up sampling
- if (dstWidth > srcWidth || dstHeight > srcHeight) {
- return false;
- }
- // check that srcWidth is scaled down by an integer value
- if (get_scaled_dimension(srcWidth, *sampleX) != dstWidth) {
- return false;
- }
- // check that src height is scaled down by an integer value
- if (get_scaled_dimension(srcHeight, *sampleY) != dstHeight) {
- return false;
- }
- // sampleX and sampleY should be equal unless the original sampleSize requested was larger
- // than srcWidth or srcHeight. If so, the result of this is dstWidth or dstHeight = 1.
- // This functionality allows for tall thin images to still be scaled down by scaling factors.
- if (*sampleX != *sampleY){
- if (1 != dstWidth && 1 != dstHeight) {
- return false;
+ if (SkCodec::kInvalidScale != result) {
+ return result;
}
- }
- return true;
-}
-bool SkScaledCodec::onDimensionsSupported(const SkISize& dim) {
- // Check with fCodec first. No need to call the non-virtual version, which
- // just checks if it matches the original, since a match means this method
- // will not be called.
- if (fCodec->onDimensionsSupported(dim)) {
- return true;
+ // If the native codec does not support the requested scale, scale by sampling.
+ return sampledDecode(info, pixels, rowBytes, options);
}
- // FIXME: These variables are unused, but are needed by scaling_supported.
- // This class could also cache these values, and avoid calling this in
- // onGetPixels (since getPixels already calls it).
- int sampleX;
- int sampleY;
- return scaling_supported(dim, this->getInfo().dimensions(), &sampleX, &sampleY);
-}
-
-// calculates sampleSize in x and y direction
-void SkScaledCodec::ComputeSampleSize(const SkISize& dstDim, const SkISize& srcDim,
- int* sampleXPtr, int* sampleYPtr) {
- int srcWidth = srcDim.width();
- int dstWidth = dstDim.width();
- int srcHeight = srcDim.height();
- int dstHeight = dstDim.height();
-
- int sampleX = srcWidth / dstWidth;
- int sampleY = srcHeight / dstHeight;
-
- // only support down sampling, not up sampling
- SkASSERT(dstWidth <= srcWidth);
- SkASSERT(dstHeight <= srcHeight);
-
- // sampleX and sampleY should be equal unless the original sampleSize requested was
- // larger than srcWidth or srcHeight.
- // If so, the result of this is dstWidth or dstHeight = 1. This functionality
- // allows for tall thin images to still be scaled down by scaling factors.
-
- if (sampleX != sampleY){
- if (1 != dstWidth && 1 != dstHeight) {
+ // We are performing a subset decode.
+ // First attempt to use the native codec. The native codec needs to know the scaled size
+ // of the image and the subset.
+ int sampleSize = options.fSampleSize;
+ // FIXME: We already make this same function call in getAndroidPixels().
+ SkISize scaledSize = this->onGetSampledDimensions(sampleSize);
+ int scaledSubsetX = subset->x() / sampleSize;
+ int scaledSubsetY = subset->y() / sampleSize;
+ int scaledSubsetWidth = info.width();
+ int scaledSubsetHeight = info.height();
+
+ // The scanline decoder only needs to be aware of scaledSubsetX and scaledSubestWidth.
+ // We will handling subsetting in the y-dimension by skipping scanlines.
+ SkIRect scanlineSubset = SkIRect::MakeXYWH(scaledSubsetX, 0, scaledSubsetWidth,
+ scaledSize.height());
+ codecOptions.fSubset = &scanlineSubset;
+ SkCodec::Result result = fCodec->startScanlineDecode(info.makeWH(scaledSize.width(),
+ scaledSize.height()), &codecOptions, options.fColorPtr, options.fColorCount);
+ switch (result) {
+ case SkCodec::kSuccess:
+ break;
+ case SkCodec::kInvalidScale:
+ // If the native codec does not support the requested scale, scale by sampling.
+ return sampledDecode(info, pixels, rowBytes, options);
+ default:
+ return result;
+ }
- // rounding during onGetScaledDimensions can cause different sampleSizes
- // Ex: srcWidth = 79, srcHeight = 20, sampleSize = 10
- // dstWidth = 7, dstHeight = 2, sampleX = 79/7 = 11, sampleY = 20/2 = 10
- // correct for this rounding by comparing width to sampleY and height to sampleX
+ switch (fCodec->getScanlineOrder()) {
+ case SkCodec::kTopDown_SkScanlineOrder:
+ case SkCodec::kNone_SkScanlineOrder: {
+ if (!fCodec->skipScanlines(scaledSubsetY)) {
+ fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZeroInitialized,
+ scaledSubsetHeight, 0);
+ return SkCodec::kIncompleteInput;
+ }
- if (get_scaled_dimension(srcWidth, sampleY) == dstWidth) {
- sampleX = sampleY;
- } else if (get_scaled_dimension(srcHeight, sampleX) == dstHeight) {
- sampleY = sampleX;
+ int decodedLines = fCodec->getScanlines(pixels, scaledSubsetHeight, rowBytes);
+ if (decodedLines != scaledSubsetHeight) {
+ return SkCodec::kIncompleteInput;
}
+ return SkCodec::kSuccess;
}
- }
-
- if (sampleXPtr) {
- *sampleXPtr = sampleX;
- }
- if (sampleYPtr) {
- *sampleYPtr = sampleY;
+ case SkCodec::kBottomUp_SkScanlineOrder:
+ case SkCodec::kOutOfOrder_SkScanlineOrder: {
+ for (int y = 0; y < scaledSize.height(); y++) {
+ int dstY = fCodec->nextScanline();
+ if (is_in_range(dstY, scaledSubsetY, scaledSubsetHeight)) {
+ void* pixelsPtr = SkTAddOffset<void>(pixels, rowBytes * (dstY - scaledSubsetY));
+ if (1 != fCodec->getScanlines(pixelsPtr, 1, rowBytes)) {
+ // FIXME: Fill incomplete images skbug.com/4428
+ return SkCodec::kIncompleteInput;
+ }
+ } else {
+ if (!fCodec->skipScanlines(1)) {
+ // FIXME: Fill incomplete images skbug.com/4428
+ return SkCodec::kIncompleteInput;
+ }
+ }
+ }
+ return SkCodec::kSuccess;
+ }
+ default:
+ SkASSERT(false);
+ return SkCodec::kUnimplemented;
}
}
-// TODO: Implement subsetting in onGetPixels which works when and when not sampling
-SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
- size_t rowBytes, const Options& options,
- SkPMColor ctable[], int* ctableCount,
- int* rowsDecoded) {
+SkCodec::Result SkSampledCodec::sampledDecode(const SkImageInfo& info, void* pixels,
+ size_t rowBytes, AndroidOptions& options) {
+ // Create options struct for the codec.
+ SkCodec::Options sampledOptions;
+ sampledOptions.fZeroInitialized = options.fZeroInitialized;
+ // Check if there is a subset.
+ SkIRect subset;
+ int subsetY = 0;
+ int subsetWidth = fCodec->getInfo().width();
+ int subsetHeight = fCodec->getInfo().height();
if (options.fSubset) {
- // Subsets are not supported.
- return kUnimplemented;
+ // We will need to know about subsetting in the y-dimension in order to use the
+ // scanline decoder.
+ SkIRect* subsetPtr = options.fSubset;
+ subsetY = subsetPtr->y();
+ subsetWidth = subsetPtr->width();
+ subsetHeight = subsetPtr->height();
+
+ // The scanline decoder only needs to be aware of subsetting in the x-dimension.
+ subset.setXYWH(subsetPtr->x(), 0, subsetWidth, fCodec->getInfo().height());
+ sampledOptions.fSubset = &subset;
}
- if (fCodec->dimensionsSupported(requestedInfo.dimensions())) {
- // Make sure that the parent class does not fill on an incomplete decode, since
- // fCodec will take care of filling the uninitialized lines.
- *rowsDecoded = requestedInfo.height();
- return fCodec->getPixels(requestedInfo, dst, rowBytes, &options, ctable, ctableCount);
- }
-
- // scaling requested
- int sampleX;
- int sampleY;
- if (!scaling_supported(requestedInfo.dimensions(), fCodec->getInfo().dimensions(),
- &sampleX, &sampleY)) {
- // onDimensionsSupported would have returned false, meaning we should never reach here.
- SkASSERT(false);
- return kInvalidScale;
- }
-
- // set first sample pixel in y direction
- const int Y0 = get_start_coord(sampleY);
-
- const int dstHeight = requestedInfo.height();
- const int srcWidth = fCodec->getInfo().width();
- const int srcHeight = fCodec->getInfo().height();
-
- const SkImageInfo info = requestedInfo.makeWH(srcWidth, srcHeight);
-
- Result result = fCodec->startScanlineDecode(info, &options, ctable, ctableCount);
-
- if (kSuccess != result) {
+ // Start the scanline decode.
+ SkCodec::Result result = fCodec->startScanlineDecode(
+ info.makeWH(fCodec->getInfo().width(), fCodec->getInfo().height()), &sampledOptions,
+ options.fColorPtr, options.fColorCount);
+ if (SkCodec::kSuccess != result) {
+ // If scaling is not supported, we should have caught the error
+ // in getAndroidPixels().
+ SkASSERT(SkCodec::kInvalidScale != result);
return result;
}
SkSampler* sampler = fCodec->getSampler(true);
if (!sampler) {
- return kUnimplemented;
+ return SkCodec::kUnimplemented;
}
- if (sampler->setSampleX(sampleX) != requestedInfo.width()) {
- return kInvalidScale;
+ // Since we guarantee that output dimensions are always at least one (even if the sampleSize
+ // is greater than a given dimension), the input sampleSize is not always the sampleSize that
+ // we use in practice.
+ int sampleX = subsetWidth / info.width();
+ int sampleY = subsetHeight / info.height();
+ if (sampler->setSampleX(sampleX) != info.width()) {
+ SkASSERT(false);
+ return SkCodec::kInvalidScale;
}
+ int y0 = get_start_coord(sampleY);
+ int dstHeight = info.height();
switch(fCodec->getScanlineOrder()) {
case SkCodec::kTopDown_SkScanlineOrder: {
- if (!fCodec->skipScanlines(Y0)) {
- *rowsDecoded = 0;
- return kIncompleteInput;
+ if (!fCodec->skipScanlines(y0 + subsetY)) {
+ fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZeroInitialized,
+ dstHeight, 0);
+ return SkCodec::kIncompleteInput;
}
+ void* pixelPtr = pixels;
for (int y = 0; y < dstHeight; y++) {
- if (1 != fCodec->getScanlines(dst, 1, rowBytes)) {
- // The failed call to getScanlines() will take care of
- // filling the failed row, so we indicate that we have
- // decoded (y + 1) rows.
- *rowsDecoded = y + 1;
- return kIncompleteInput;
+ if (1 != fCodec->getScanlines(pixelPtr, 1, rowBytes)) {
+ fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZeroInitialized,
+ dstHeight, y + 1);
+ return SkCodec::kIncompleteInput;
}
- if (y < dstHeight - 1) {
- if (!fCodec->skipScanlines(sampleY - 1)) {
- *rowsDecoded = y + 1;
- return kIncompleteInput;
- }
+ int linesToSkip = SkTMin(sampleY - 1, dstHeight - y - 1);
+ if (!fCodec->skipScanlines(linesToSkip)) {
+ fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZeroInitialized,
+ dstHeight, y + 1);
+ return SkCodec::kIncompleteInput;
}
- dst = SkTAddOffset<void>(dst, rowBytes);
+ pixelPtr = SkTAddOffset<void>(pixelPtr, rowBytes);
}
- return kSuccess;
+ return SkCodec::kSuccess;
}
case SkCodec::kBottomUp_SkScanlineOrder:
case SkCodec::kOutOfOrder_SkScanlineOrder: {
- Result result = kSuccess;
+ SkCodec::Result result = SkCodec::kSuccess;
int y;
- for (y = 0; y < srcHeight; y++) {
+ for (y = 0; y < fCodec->getInfo().height(); y++) {
int srcY = fCodec->nextScanline();
- if (is_coord_necessary(srcY, sampleY, dstHeight)) {
- void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_coord(srcY, sampleY));
- if (1 != fCodec->getScanlines(dstPtr, 1, rowBytes)) {
- result = kIncompleteInput;
+ if (is_coord_necessary(srcY, sampleY, dstHeight, subsetY)) {
+ void* pixelPtr = SkTAddOffset<void>(pixels,
+ rowBytes * get_dst_coord(srcY, sampleY));
+ if (1 != fCodec->getScanlines(pixelPtr, 1, rowBytes)) {
+ result = SkCodec::kIncompleteInput;
break;
}
} else {
if (!fCodec->skipScanlines(1)) {
- result = kIncompleteInput;
+ result = SkCodec::kIncompleteInput;
break;
}
}
}
- // We handle filling uninitialized memory here instead of in the parent class.
- // The parent class does not know that we are sampling.
- if (kIncompleteInput == result) {
- const uint32_t fillValue = fCodec->getFillValue(requestedInfo.colorType(),
- requestedInfo.alphaType());
- for (; y < srcHeight; y++) {
+ // We handle filling uninitialized memory here instead of using fCodec.
+ // fCodec does not know that we are sampling.
+ if (SkCodec::kIncompleteInput == result) {
+ const uint32_t fillValue = fCodec->getFillValue(info.colorType(),
+ info.alphaType());
+ for (; y < fCodec->getInfo().height(); y++) {
int srcY = fCodec->outputScanline(y);
- if (is_coord_necessary(srcY, sampleY, dstHeight)) {
- void* dstRow = SkTAddOffset<void>(dst,
+ if (is_coord_necessary(srcY, sampleY, dstHeight, subsetY)) {
+ void* pixelPtr = SkTAddOffset<void>(pixels,
rowBytes * get_dst_coord(srcY, sampleY));
- SkSampler::Fill(requestedInfo.makeWH(requestedInfo.width(), 1), dstRow,
- rowBytes, fillValue, options.fZeroInitialized);
+ SkSampler::Fill(info.makeWH(info.width(), 1), pixelPtr, rowBytes, fillValue,
+ options.fZeroInitialized);
}
}
- *rowsDecoded = dstHeight;
}
return result;
}
case SkCodec::kNone_SkScanlineOrder: {
- SkAutoMalloc storage(srcHeight * rowBytes);
+ SkAutoMalloc storage((subsetHeight - y0) * rowBytes);
uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());
- int scanlines = fCodec->getScanlines(storagePtr, srcHeight, rowBytes);
- storagePtr += Y0 * rowBytes;
- scanlines -= Y0;
+ if (!fCodec->skipScanlines(subsetY + y0)) {
+ fCodec->fillIncompleteImage(info, pixels, rowBytes, options.fZeroInitialized,
+ dstHeight, 0);
+ return SkCodec::kIncompleteInput;
+ }
+ int scanlines = fCodec->getScanlines(storagePtr, subsetHeight - y0, rowBytes);
int y = 0;
- while (y < dstHeight && scanlines > 0) {
- memcpy(dst, storagePtr, rowBytes);
+ void* pixelPtr = pixels;
+ while (y < dstHeight) {
+ memcpy(pixelPtr, storagePtr, info.minRowBytes());
storagePtr += sampleY * rowBytes;
- dst = SkTAddOffset<void>(dst, rowBytes);
- scanlines -= sampleY;
+ pixelPtr = SkTAddOffset<void>(pixelPtr, rowBytes);
y++;
}
- if (y < dstHeight) {
+ if (scanlines < dstHeight) {
// fCodec has already handled filling uninitialized memory.
- *rowsDecoded = dstHeight;
- return kIncompleteInput;
+ return SkCodec::kIncompleteInput;
}
- return kSuccess;
+ return SkCodec::kSuccess;
}
default:
SkASSERT(false);
- return kUnimplemented;
+ return SkCodec::kUnimplemented;
}
}
-
-uint32_t SkScaledCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType) const {
- return fCodec->onGetFillValue(colorType, alphaType);
-}
-
-SkCodec::SkScanlineOrder SkScaledCodec::onGetScanlineOrder() const {
- return fCodec->onGetScanlineOrder();
-}

Powered by Google App Engine
This is Rietveld 408576698