| Index: src/codec/SkMaskSwizzler.cpp | 
| diff --git a/src/codec/SkMaskSwizzler.cpp b/src/codec/SkMaskSwizzler.cpp | 
| index 58be0c67af441660664b5e25466d6a205b04d92c..f7b3a47add47d03dc1cc2446f537c595a86a832c 100644 | 
| --- a/src/codec/SkMaskSwizzler.cpp | 
| +++ b/src/codec/SkMaskSwizzler.cpp | 
| @@ -8,57 +8,64 @@ | 
| #include "SkCodecPriv.h" | 
| #include "SkColorPriv.h" | 
| #include "SkMaskSwizzler.h" | 
| +#include "SkScaledCodec.h" | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint16_t* srcPtr = (uint16_t*) srcRow; | 
| +    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| for (int i = 0; i < width; i++) { | 
| -        uint16_t p = srcPtr[i]; | 
| +        uint16_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return SkSwizzler::kOpaque_ResultAlpha; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint16_t* srcPtr = (uint16_t*) srcRow; | 
| +    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| INIT_RESULT_ALPHA; | 
| for (int i = 0; i < width; i++) { | 
| -        uint16_t p = srcPtr[i]; | 
| +        uint16_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| uint8_t alpha = masks->getAlpha(p); | 
| UPDATE_RESULT_ALPHA(alpha); | 
| dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return COMPUTE_RESULT_ALPHA; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint16_t* srcPtr = (uint16_t*) srcRow; | 
| +    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| INIT_RESULT_ALPHA; | 
| for (int i = 0; i < width; i++) { | 
| -        uint16_t p = srcPtr[i]; | 
| +        uint16_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| uint8_t alpha = masks->getAlpha(p); | 
| UPDATE_RESULT_ALPHA(alpha); | 
| dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return COMPUTE_RESULT_ALPHA; | 
| } | 
| @@ -66,152 +73,174 @@ static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul( | 
| // TODO (msarett): We have promoted a two byte per pixel image to 8888, only to | 
| // convert it back to 565. Instead, we should swizzle to 565 directly. | 
| static SkSwizzler::ResultAlpha swizzle_mask16_to_565( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint16_t* srcPtr = (uint16_t*) srcRow; | 
| +    uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; | 
| uint16_t* dstPtr = (uint16_t*) dstRow; | 
| for (int i = 0; i < width; i++) { | 
| -        uint16_t p = srcPtr[i]; | 
| +        uint16_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| dstPtr[i] = SkPack888ToRGB16(red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return SkSwizzler::kOpaque_ResultAlpha; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| +    srcRow += 3 * startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| -    for (int i = 0; i < 3*width; i += 3) { | 
| -        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; | 
| +    for (int i = 0; i < width; i++) { | 
| +        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| -        dstPtr[i/3] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 
| +        dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 
| +        srcRow += 3 * sampleX; | 
| } | 
| return SkSwizzler::kOpaque_ResultAlpha; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| +    srcRow += 3 * startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| INIT_RESULT_ALPHA; | 
| -    for (int i = 0; i < 3*width; i += 3) { | 
| -        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; | 
| +    for (int i = 0; i < width; i++) { | 
| +        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| uint8_t alpha = masks->getAlpha(p); | 
| UPDATE_RESULT_ALPHA(alpha); | 
| -        dstPtr[i/3] = SkPackARGB32NoCheck(alpha, red, green, blue); | 
| +        dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); | 
| +        srcRow += 3 * sampleX; | 
| } | 
| return COMPUTE_RESULT_ALPHA; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| +    srcRow += 3 * startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| INIT_RESULT_ALPHA; | 
| -    for (int i = 0; i < 3*width; i += 3) { | 
| -        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; | 
| +    for (int i = 0; i < width; i++) { | 
| +        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| uint8_t alpha = masks->getAlpha(p); | 
| UPDATE_RESULT_ALPHA(alpha); | 
| -        dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue); | 
| +        dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); | 
| +        srcRow += 3 * sampleX; | 
| } | 
| return COMPUTE_RESULT_ALPHA; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask24_to_565( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| +    srcRow += 3 * startX; | 
| uint16_t* dstPtr = (uint16_t*) dstRow; | 
| -    for (int i = 0; i < 3*width; i += 3) { | 
| -        uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; | 
| +    for (int i = 0; i < width; i++) { | 
| +        uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| -        dstPtr[i/3] = SkPack888ToRGB16(red, green, blue); | 
| +        dstPtr[i] = SkPack888ToRGB16(red, green, blue); | 
| +        srcRow += 3 * sampleX; | 
| } | 
| return SkSwizzler::kOpaque_ResultAlpha; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint32_t* srcPtr = (uint32_t*) srcRow; | 
| +    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| for (int i = 0; i < width; i++) { | 
| -        uint32_t p = srcPtr[i]; | 
| +        uint32_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return SkSwizzler::kOpaque_ResultAlpha; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint32_t* srcPtr = (uint32_t*) srcRow; | 
| +    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| INIT_RESULT_ALPHA; | 
| for (int i = 0; i < width; i++) { | 
| -        uint32_t p = srcPtr[i]; | 
| +        uint32_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| uint8_t alpha = masks->getAlpha(p); | 
| UPDATE_RESULT_ALPHA(alpha); | 
| dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return COMPUTE_RESULT_ALPHA; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
|  | 
| // Use the masks to decode to the destination | 
| -    uint32_t* srcPtr = (uint32_t*) srcRow; | 
| +    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; | 
| SkPMColor* dstPtr = (SkPMColor*) dstRow; | 
| INIT_RESULT_ALPHA; | 
| for (int i = 0; i < width; i++) { | 
| -        uint32_t p = srcPtr[i]; | 
| +        uint32_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| uint8_t alpha = masks->getAlpha(p); | 
| UPDATE_RESULT_ALPHA(alpha); | 
| dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return COMPUTE_RESULT_ALPHA; | 
| } | 
|  | 
| static SkSwizzler::ResultAlpha swizzle_mask32_to_565( | 
| -        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { | 
| +        void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, | 
| +        uint32_t startX, uint32_t sampleX) { | 
| // Use the masks to decode to the destination | 
| -    uint32_t* srcPtr = (uint32_t*) srcRow; | 
| +    uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; | 
| uint16_t* dstPtr = (uint16_t*) dstRow; | 
| for (int i = 0; i < width; i++) { | 
| -        uint32_t p = srcPtr[i]; | 
| +        uint32_t p = srcPtr[0]; | 
| uint8_t red = masks->getRed(p); | 
| uint8_t green = masks->getGreen(p); | 
| uint8_t blue = masks->getBlue(p); | 
| dstPtr[i] = SkPack888ToRGB16(red, green, blue); | 
| +        srcPtr += sampleX; | 
| } | 
| return SkSwizzler::kOpaque_ResultAlpha; | 
| } | 
| @@ -222,15 +251,16 @@ static SkSwizzler::ResultAlpha swizzle_mask32_to_565( | 
| * | 
| */ | 
| SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| -        const SkImageInfo& info, SkMasks* masks, uint32_t bitsPerPixel) { | 
| +        const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, SkMasks* masks, | 
| +        uint32_t bitsPerPixel) { | 
|  | 
| // Choose the appropriate row procedure | 
| RowProc proc = nullptr; | 
| switch (bitsPerPixel) { | 
| case 16: | 
| -            switch (info.colorType()) { | 
| +            switch (dstInfo.colorType()) { | 
| case kN32_SkColorType: | 
| -                    switch (info.alphaType()) { | 
| +                    switch (dstInfo.alphaType()) { | 
| case kUnpremul_SkAlphaType: | 
| proc = &swizzle_mask16_to_n32_unpremul; | 
| break; | 
| @@ -245,7 +275,7 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| } | 
| break; | 
| case kRGB_565_SkColorType: | 
| -                    switch (info.alphaType()) { | 
| +                    switch (dstInfo.alphaType()) { | 
| case kOpaque_SkAlphaType: | 
| proc = &swizzle_mask16_to_565; | 
| break; | 
| @@ -258,9 +288,9 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| } | 
| break; | 
| case 24: | 
| -            switch (info.colorType()) { | 
| +            switch (dstInfo.colorType()) { | 
| case kN32_SkColorType: | 
| -                    switch (info.alphaType()) { | 
| +                    switch (dstInfo.alphaType()) { | 
| case kUnpremul_SkAlphaType: | 
| proc = &swizzle_mask24_to_n32_unpremul; | 
| break; | 
| @@ -275,7 +305,7 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| } | 
| break; | 
| case kRGB_565_SkColorType: | 
| -                    switch (info.alphaType()) { | 
| +                    switch (dstInfo.alphaType()) { | 
| case kOpaque_SkAlphaType: | 
| proc = &swizzle_mask24_to_565; | 
| break; | 
| @@ -288,9 +318,9 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| } | 
| break; | 
| case 32: | 
| -            switch (info.colorType()) { | 
| +            switch (dstInfo.colorType()) { | 
| case kN32_SkColorType: | 
| -                    switch (info.alphaType()) { | 
| +                    switch (dstInfo.alphaType()) { | 
| case kUnpremul_SkAlphaType: | 
| proc = &swizzle_mask32_to_n32_unpremul; | 
| break; | 
| @@ -305,7 +335,7 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| } | 
| break; | 
| case kRGB_565_SkColorType: | 
| -                    switch (info.alphaType()) { | 
| +                    switch (dstInfo.alphaType()) { | 
| case kOpaque_SkAlphaType: | 
| proc = &swizzle_mask32_to_565; | 
| break; | 
| @@ -321,7 +351,12 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| SkASSERT(false); | 
| return nullptr; | 
| } | 
| -    return new SkMaskSwizzler(info, masks, proc); | 
| + | 
| +    // Get the sample size | 
| +    int sampleX; | 
| +    SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, &sampleX, NULL); | 
| + | 
| +    return new SkMaskSwizzler(dstInfo, masks, proc, sampleX); | 
| } | 
|  | 
| /* | 
| @@ -330,10 +365,12 @@ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( | 
| * | 
| */ | 
| SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, SkMasks* masks, | 
| -                               RowProc proc) | 
| +                               RowProc proc, uint32_t sampleX) | 
| : fDstInfo(dstInfo) | 
| , fMasks(masks) | 
| , fRowProc(proc) | 
| +    , fSampleX(sampleX) | 
| +    , fStartX(SkScaledCodec::GetStartCoord(sampleX)) | 
| {} | 
|  | 
| /* | 
| @@ -343,5 +380,5 @@ SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, SkMasks* masks, | 
| */ | 
| SkSwizzler::ResultAlpha SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { | 
| SkASSERT(nullptr != dst && nullptr != src); | 
| -    return fRowProc(dst, src, fDstInfo.width(), fMasks); | 
| +    return fRowProc(dst, src, fDstInfo.width(), fMasks, fStartX, fSampleX); | 
| } | 
|  |