18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2007 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScaledBitmapSampler.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmap.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h"
132bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com#include "SkTypes.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 8888
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const uint8_t* SK_RESTRICT src,
191134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                              int width, int deltaSrc, int, const SkPMColor[]) {
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]);
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
29407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_gray_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
308d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Dither, unpremul, and skipZeroes have no effect
318d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Gray_D8888;
328d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
338d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const uint8_t* SK_RESTRICT src,
361134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                              int width, int deltaSrc, int, const SkPMColor[]) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
46407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_RGBx_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
478d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Dither, unpremul, and skipZeroes have no effect
488d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_RGBx_D8888;
498d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
508d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const uint8_t* SK_RESTRICT src,
531134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                              int width, int deltaSrc, int, const SkPMColor[]) {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alphaMask = 0xFF;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned alpha = src[3];
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        alphaMask &= alpha;
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return alphaMask != 0xFF;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
658d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow,
668d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                       const uint8_t* SK_RESTRICT src,
678d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                       int width, int deltaSrc, int,
688d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                       const SkPMColor[]) {
698d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
708d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    unsigned alphaMask = 0xFF;
718d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
728d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        unsigned alpha = src[3];
738d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
748d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
758d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        alphaMask &= alpha;
768d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
778d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return alphaMask != 0xFF;
788d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
798d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
808d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_RGBA_D8888_SkipZ(void* SK_RESTRICT dstRow,
818d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                    const uint8_t* SK_RESTRICT src,
828d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                    int width, int deltaSrc, int,
838d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                    const SkPMColor[]) {
848d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
858d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    unsigned alphaMask = 0xFF;
868d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
878d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        unsigned alpha = src[3];
888d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        if (0 != alpha) {
898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
908d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
918d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
928d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        alphaMask &= alpha;
938d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
948d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return alphaMask != 0xFF;
958d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
968d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
97407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
98407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_RGBA_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
998d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Dither has no effect.
100407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (!opts.fPremultiplyAlpha) {
1018d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        // We could check each component for a zero, at the expense of extra checks.
1028d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        // For now, just return unpremul.
1038d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_RGBA_D8888_Unpremul;
1048d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
1058d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Supply the versions that premultiply the colors
106407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fSkipZeros) {
1078d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_RGBA_D8888_SkipZ;
1088d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
1098d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_RGBA_D8888;
1108d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
1118d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 565
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const uint8_t* SK_RESTRICT src,
1161134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                             int width, int deltaSrc, int, const SkPMColor[]) {
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                               const uint8_t* SK_RESTRICT src,
1271134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                           int width, int deltaSrc, int y, const SkPMColor[]) {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DITHER_565_SCAN(y);
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
137407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
138407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_gray_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
1398d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Unpremul and skip zeroes make no difference
140407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
1418d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_Gray_D565_D;
1428d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
1438d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Gray_D565;
1448d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
1458d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const uint8_t* SK_RESTRICT src,
1481134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                             int width, int deltaSrc, int, const SkPMColor[]) {
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1578d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
1588d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                               const uint8_t* SK_RESTRICT src,
1598d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                               int width, int deltaSrc, int y,
1608d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                               const SkPMColor[]) {
1618d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
1628d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    DITHER_565_SCAN(y);
1638d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
1648d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
1658d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
1668d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
1678d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return false;
1688d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
1698d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
170407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
171407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_RGBx_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
1728d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Unpremul and skip zeroes make no difference
173407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
1748d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_RGBx_D565_D;
1758d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
1768d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_RGBx_D565;
1778d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
1788d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
1798d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
18057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.comstatic bool Sample_D565_D565(void* SK_RESTRICT dstRow,
18157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com                             const uint8_t* SK_RESTRICT src,
18257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com                             int width, int deltaSrc, int, const SkPMColor[]) {
18357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
18457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
18557f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    for (int x = 0; x < width; x++) {
18657f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        dst[x] = castedSrc[0];
18757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        castedSrc += deltaSrc >> 1;
18857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    }
18957f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com    return false;
19057f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com}
19157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com
192407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
193407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_565_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
1948d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Unpremul, dither, and skip zeroes have no effect
1958d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_D565_D565;
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 4444
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const uint8_t* SK_RESTRICT src,
2021134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                              int width, int deltaSrc, int, const SkPMColor[]) {
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned gray = src[0] >> 4;
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPackARGB4444(0xF, gray, gray, gray);
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const uint8_t* SK_RESTRICT src,
2141134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                            int width, int deltaSrc, int y, const SkPMColor[]) {
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DITHER_4444_SCAN(y);
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      DITHER_VALUE(x));
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
225407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
226407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_gray_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
2278d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Skip zeroes and unpremul make no difference
228407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
2298d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_Gray_D4444_D;
2308d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
2318d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Gray_D4444;
2328d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
2338d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const uint8_t* SK_RESTRICT src,
2361134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                              int width, int deltaSrc, int, const SkPMColor[]) {
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const uint8_t* SK_RESTRICT src,
2471134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                            int width, int deltaSrc, int y, const SkPMColor[]) {
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor16* dst = (SkPMColor16*)dstRow;
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DITHER_4444_SCAN(y);
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                      DITHER_VALUE(x));
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
259407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
260407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_RGBx_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
2618d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Skip zeroes and unpremul make no difference
262407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
2638d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_RGBx_D4444_D;
2648d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
2658d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_RGBx_D4444;
2668d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
2678d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                              const uint8_t* SK_RESTRICT src,
2701134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                              int width, int deltaSrc, int, const SkPMColor[]) {
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alphaMask = 0xFF;
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned alpha = src[3];
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkPixel32ToPixel4444(c);
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        alphaMask &= alpha;
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return alphaMask != 0xFF;
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2848d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_RGBA_D4444_SkipZ(void* SK_RESTRICT dstRow,
2858d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                    const uint8_t* SK_RESTRICT src,
2868d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                    int width, int deltaSrc, int,
2878d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                    const SkPMColor[]) {
2888d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
2898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    unsigned alphaMask = 0xFF;
2908d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
2918d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
2928d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        unsigned alpha = src[3];
2938d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        if (alpha != 0) {
2948d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
2958d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            dst[x] = SkPixel32ToPixel4444(c);
2968d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
2978d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
2988d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        alphaMask &= alpha;
2998d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
3008d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return alphaMask != 0xFF;
3018d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
3028d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3038d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                const uint8_t* SK_RESTRICT src,
3068d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                int width, int deltaSrc, int y,
3078d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                const SkPMColor[]) {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned alphaMask = 0xFF;
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    DITHER_4444_SCAN(y);
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (int x = 0; x < width; x++) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned alpha = src[3];
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        src += deltaSrc;
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        alphaMask &= alpha;
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return alphaMask != 0xFF;
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3228d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_RGBA_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
3238d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                      const uint8_t* SK_RESTRICT src,
3248d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                      int width, int deltaSrc, int y,
3258d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                      const SkPMColor[]) {
3268d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
3278d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    unsigned alphaMask = 0xFF;
3288d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    DITHER_4444_SCAN(y);
3298d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3308d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
3318d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        unsigned alpha = src[3];
3328d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        if (alpha != 0) {
3338d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
3348d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
3358d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
3368d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
3378d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        alphaMask &= alpha;
3388d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
3398d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return alphaMask != 0xFF;
3408d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
3418d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
342407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
343407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_RGBA_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
344407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (!opts.fPremultiplyAlpha) {
3458d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        // Unpremultiplied is not supported for 4444
3468d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return NULL;
3478d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
348407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fSkipZeros) {
349407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski        if (opts.fDither) {
3508d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            return Sample_RGBA_D4444_D_SkipZ;
3518d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
3528d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_RGBA_D4444_SkipZ;
3538d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
354407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
3558d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_RGBA_D4444_D;
3568d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
3578d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_RGBA_D4444;
3588d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
3598d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Index
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3621cdcb5138f9b70aff547ea1c3af96f0c90b12f8freed@android.com#define A32_MASK_IN_PLACE   (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
3631134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
3641134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.comstatic bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
3651134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                               const uint8_t* SK_RESTRICT src,
3661134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                       int width, int deltaSrc, int, const SkPMColor ctable[]) {
3671134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
3681134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
3691134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    SkPMColor cc = A32_MASK_IN_PLACE;
3701134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    for (int x = 0; x < width; x++) {
3711134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        SkPMColor c = ctable[*src];
3721134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        cc &= c;
3731134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        dst[x] = c;
3741134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        src += deltaSrc;
3751134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    }
3761134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    return cc != A32_MASK_IN_PLACE;
3771134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com}
3781134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
3798d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_Index_D8888_SkipZ(void* SK_RESTRICT dstRow,
3808d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                     const uint8_t* SK_RESTRICT src,
3818d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                     int width, int deltaSrc, int,
3828d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                     const SkPMColor ctable[]) {
3838d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
3848d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
3858d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor cc = A32_MASK_IN_PLACE;
3868d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
3878d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        SkPMColor c = ctable[*src];
3888d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        cc &= c;
3898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        if (c != 0) {
3908d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            dst[x] = c;
3918d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
3928d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
3938d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
3948d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return cc != A32_MASK_IN_PLACE;
3958d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
3968d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
397407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
398407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_index_to_8888_proc(const SkScaledBitmapSampler::Options& opts) {
399407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (!opts.fPremultiplyAlpha) {
4008d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        // Unpremultiplied is not supported for an index source.
4018d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return NULL;
4028d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
4038d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Dither makes no difference
404407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fSkipZeros) {
4058d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_Index_D8888_SkipZ;
4068d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
4078d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Index_D8888;
4088d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
4098d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
4101134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.comstatic bool Sample_Index_D565(void* SK_RESTRICT dstRow,
4111134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                               const uint8_t* SK_RESTRICT src,
4121134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                       int width, int deltaSrc, int, const SkPMColor ctable[]) {
4131134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4141134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
4151134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    for (int x = 0; x < width; x++) {
4161134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        dst[x] = SkPixel32ToPixel16(ctable[*src]);
4171134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        src += deltaSrc;
4181134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    }
4191134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    return false;
4201134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com}
4211134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4221134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.comstatic bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
4231134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                                const uint8_t* SK_RESTRICT src, int width,
4241134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                                int deltaSrc, int y, const SkPMColor ctable[]) {
4251134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4261134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
4271134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    DITHER_565_SCAN(y);
4281134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4291134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    for (int x = 0; x < width; x++) {
4301134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        SkPMColor c = ctable[*src];
4311134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
4321134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                                  SkGetPackedB32(c), DITHER_VALUE(x));
4331134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        src += deltaSrc;
4341134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    }
4351134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    return false;
4361134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com}
4371134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
438407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
439407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_index_to_565_proc(const SkScaledBitmapSampler::Options& opts) {
4408d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Unpremultiplied and skip zeroes make no difference
441407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
4428d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_Index_D565_D;
4438d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
4448d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Index_D565;
4458d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
4468d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
4471134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.comstatic bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
4481134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                               const uint8_t* SK_RESTRICT src, int width,
4491134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                               int deltaSrc, int y, const SkPMColor ctable[]) {
4501134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4511134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
4521134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    SkPMColor cc = A32_MASK_IN_PLACE;
4531134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    for (int x = 0; x < width; x++) {
4541134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        SkPMColor c = ctable[*src];
4551134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        cc &= c;
4561134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        dst[x] = SkPixel32ToPixel4444(c);
4571134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        src += deltaSrc;
4581134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    }
4591134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    return cc != A32_MASK_IN_PLACE;
4601134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com}
4611134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4621134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.comstatic bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
4631134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                                 const uint8_t* SK_RESTRICT src, int width,
4641134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                                int deltaSrc, int y, const SkPMColor ctable[]) {
4651134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4661134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
4671134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    SkPMColor cc = A32_MASK_IN_PLACE;
4681134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    DITHER_4444_SCAN(y);
4691134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4701134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    for (int x = 0; x < width; x++) {
4711134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        SkPMColor c = ctable[*src];
4721134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        cc &= c;
4731134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
4741134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com        src += deltaSrc;
4751134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    }
4761134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    return cc != A32_MASK_IN_PLACE;
4771134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com}
4781134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
4798d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_Index_D4444_SkipZ(void* SK_RESTRICT dstRow,
4808d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                     const uint8_t* SK_RESTRICT src, int width,
4818d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                     int deltaSrc, int y, const SkPMColor ctable[]) {
4828d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
4838d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
4848d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor cc = A32_MASK_IN_PLACE;
4858d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
4868d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        SkPMColor c = ctable[*src];
4878d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        cc &= c;
4888d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        if (c != 0) {
4898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            dst[x] = SkPixel32ToPixel4444(c);
4908d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
4918d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
4928d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
4938d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return cc != A32_MASK_IN_PLACE;
4948d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
4958d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
4968d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comstatic bool Sample_Index_D4444_D_SkipZ(void* SK_RESTRICT dstRow,
4978d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                       const uint8_t* SK_RESTRICT src, int width,
4988d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                       int deltaSrc, int y, const SkPMColor ctable[]) {
4998d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
5008d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
5018d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkPMColor cc = A32_MASK_IN_PLACE;
5028d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    DITHER_4444_SCAN(y);
5038d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
5048d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int x = 0; x < width; x++) {
5058d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        SkPMColor c = ctable[*src];
5068d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        cc &= c;
5078d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        if (c != 0) {
5088d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
5098d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
5108d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        src += deltaSrc;
5118d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
5128d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return cc != A32_MASK_IN_PLACE;
5138d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
5148d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
515407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
516407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_index_to_4444_proc(const SkScaledBitmapSampler::Options& opts) {
5178d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Unpremul not allowed
518407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (!opts.fPremultiplyAlpha) {
5198d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return NULL;
5208d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
521407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fSkipZeros) {
522407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski        if (opts.fDither) {
5238d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            return Sample_Index_D4444_D_SkipZ;
5248d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
5258d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_Index_D4444_SkipZ;
5268d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
527407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (opts.fDither) {
5288d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return Sample_Index_D4444_D;
5298d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
5308d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Index_D4444;
5318d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
5328d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool Sample_Index_DI(void* SK_RESTRICT dstRow,
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                            const uint8_t* SK_RESTRICT src,
5351134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                            int width, int deltaSrc, int, const SkPMColor[]) {
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (1 == deltaSrc) {
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        memcpy(dstRow, src, width);
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (int x = 0; x < width; x++) {
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst[x] = src[0];
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            src += deltaSrc;
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
549407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_index_to_index_proc(const SkScaledBitmapSampler::Options& opts) {
5508d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Unpremul not allowed
551407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (!opts.fPremultiplyAlpha) {
5528d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return NULL;
5538d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
5548d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Ignore dither and skip zeroes
5558d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Index_DI;
5568d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
5578d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
558f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com// A8
559f698c8262df397a7015662e91b1a727e1134c418scroggo@google.comstatic bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
560f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com                            const uint8_t* SK_RESTRICT src,
561f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com                            int width, int deltaSrc, int,
562f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com                            const SkPMColor[]) {
5635ee18dd20192d020884a95c7991c63ce33af3137scroggo@google.com    // Sampling Gray to A8 uses the same function as Index to Index8,
5645ee18dd20192d020884a95c7991c63ce33af3137scroggo@google.com    // except we assume that there is alpha for speed, since an A8
5655ee18dd20192d020884a95c7991c63ce33af3137scroggo@google.com    // bitmap with no alpha is not interesting.
5665ee18dd20192d020884a95c7991c63ce33af3137scroggo@google.com    (void) Sample_Index_DI(dstRow, src, width, deltaSrc, /* y unused */ 0,
5675ee18dd20192d020884a95c7991c63ce33af3137scroggo@google.com                           /* ctable unused */ NULL);
568f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com    return true;
569f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com}
570f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com
571407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskistatic SkScaledBitmapSampler::RowProc
572407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskiget_gray_to_A8_proc(const SkScaledBitmapSampler::Options& opts) {
573407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    if (!opts.fPremultiplyAlpha) {
5748d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return NULL;
5752bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
5768d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Ignore skip and dither.
5778d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    return Sample_Gray_DA8;
5782bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com}
5792bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com
580407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskitypedef SkScaledBitmapSampler::RowProc (*RowProcChooser)(const SkScaledBitmapSampler::Options&);
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScaledBitmapSampler.h"
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                             int sampleSize) {
587a728e35edcffd99216e3965a4b908ad0df7f69c2vandebo@chromium.org    fCTable = NULL;
588a728e35edcffd99216e3965a4b908ad0df7f69c2vandebo@chromium.org    fDstRow = NULL;
589a728e35edcffd99216e3965a4b908ad0df7f69c2vandebo@chromium.org    fRowProc = NULL;
590a728e35edcffd99216e3965a4b908ad0df7f69c2vandebo@chromium.org
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (width <= 0 || height <= 0) {
5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_throw();
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
594d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
595dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    SkDEBUGCODE(fSampleMode = kUninitialized_SampleMode);
596dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org
5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (sampleSize <= 1) {
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScaledWidth = width;
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fScaledHeight = height;
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fX0 = fY0 = 0;
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDX = fDY = 1;
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
604d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dx = SkMin32(sampleSize, width);
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int dy = SkMin32(sampleSize, height);
607d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fScaledWidth = width / dx;
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fScaledHeight = height / dy;
610d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fScaledWidth > 0);
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fScaledHeight > 0);
613d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fX0 = dx >> 1;
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fY0 = dy >> 1;
616d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fX0 >= 0 && fX0 < width);
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fY0 >= 0 && fY0 < height);
619d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDX = dx;
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDY = dy;
622d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6278d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.combool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
628407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski                                  const Options& opts,
6298d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                  const SkPMColor ctable[]) {
6308d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    static const RowProcChooser gProcChoosers[] = {
6318d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_gray_to_8888_proc,
6328d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_RGBx_to_8888_proc,
6338d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_RGBA_to_8888_proc,
6348d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_index_to_8888_proc,
6358d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // 565 to 8888
6368d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
6378d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_gray_to_565_proc,
6388d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_RGBx_to_565_proc,
6398d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_RGBx_to_565_proc, // The source alpha will be ignored.
6408d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_index_to_565_proc,
6418d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_565_to_565_proc,
6428d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
6438d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_gray_to_4444_proc,
6448d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_RGBx_to_4444_proc,
6458d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_RGBA_to_4444_proc,
6468d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_index_to_4444_proc,
6478d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // 565 to 4444
6488d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
6498d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // gray to index
6508d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // rgbx to index
6518d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // rgba to index
6528d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_index_to_index_proc,
6538d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // 565 to index
6548d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
6558d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        get_gray_to_A8_proc,
6568d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // rgbx to a8
6578d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // rgba to a8
6588d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // index to a8
6598d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        NULL, // 565 to a8
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
6618d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
6622bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    // The jump between dst configs in the table
6638d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    static const int gProcDstConfigSpan = 5;
6648d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcChoosers) == 5 * gProcDstConfigSpan,
6652bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com                      gProcs_has_the_wrong_number_of_entries);
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6671134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com    fCTable = ctable;
6681134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int index = 0;
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (sc) {
6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScaledBitmapSampler::kGray:
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSrcPixelSize = 1;
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            index += 0;
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScaledBitmapSampler::kRGB:
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSrcPixelSize = 3;
6778d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            index += 1;
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScaledBitmapSampler::kRGBX:
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSrcPixelSize = 4;
6818d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            index += 1;
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScaledBitmapSampler::kRGBA:
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSrcPixelSize = 4;
6858d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            index += 2;
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        case SkScaledBitmapSampler::kIndex:
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fSrcPixelSize = 1;
6898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            index += 3;
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
69157f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com        case SkScaledBitmapSampler::kRGB_565:
69257f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            fSrcPixelSize = 2;
6938d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            index += 4;
69457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com            break;
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6990689d7b12e7c427a077b003d3d8ae759d86f798freed    switch (dst->colorType()) {
7000689d7b12e7c427a077b003d3d8ae759d86f798freed        case kN32_SkColorType:
7012bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            index += 0 * gProcDstConfigSpan;
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7030689d7b12e7c427a077b003d3d8ae759d86f798freed        case kRGB_565_SkColorType:
7042bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            index += 1 * gProcDstConfigSpan;
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7060689d7b12e7c427a077b003d3d8ae759d86f798freed        case kARGB_4444_SkColorType:
7072bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            index += 2 * gProcDstConfigSpan;
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7090689d7b12e7c427a077b003d3d8ae759d86f798freed        case kIndex_8_SkColorType:
7102bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com            index += 3 * gProcDstConfigSpan;
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
7120689d7b12e7c427a077b003d3d8ae759d86f798freed        case kAlpha_8_SkColorType:
713f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com            index += 4 * gProcDstConfigSpan;
714f698c8262df397a7015662e91b1a727e1134c418scroggo@google.com            break;
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        default:
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return false;
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
718d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
7198d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    RowProcChooser chooser = gProcChoosers[index];
7208d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    if (NULL == chooser) {
7218d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        fRowProc = NULL;
7228d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    } else {
723407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski        fRowProc = chooser(opts);
7242bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com    }
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDstRow = (char*)dst->getPixels();
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDstRowBytes = dst->rowBytes();
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fCurrY = 0;
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fRowProc != NULL;
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
731407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevskibool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc,
732407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski                                  const SkImageDecoder& decoder,
733407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski                                  const SkPMColor ctable[]) {
734407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski    return this->begin(dst, sc, Options(decoder), ctable);
735407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski}
736407d7c90224fccf39685c9cb091fd777b5aac3d9krajcevski
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
738dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    SkASSERT(kInterlaced_SampleMode != fSampleMode);
739dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    SkDEBUGCODE(fSampleMode = kConsecutive_SampleMode);
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
7431134426f6b1c4130e8dbe4c38a4aa976fbb18b4breed@android.com                             fDX * fSrcPixelSize, fCurrY, fCTable);
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDstRow += fDstRowBytes;
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fCurrY += 1;
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return hadAlpha;
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7488d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
749dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.orgbool SkScaledBitmapSampler::sampleInterlaced(const uint8_t* SK_RESTRICT src, int srcY) {
750dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    SkASSERT(kConsecutive_SampleMode != fSampleMode);
751dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    SkDEBUGCODE(fSampleMode = kInterlaced_SampleMode);
752dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // Any line that should be a part of the destination can be created by the formula:
753dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // fY0 + (some multiplier) * fDY
754dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // so if srcY - fY0 is not an integer multiple of fDY that srcY will be skipped.
755dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    const int srcYMinusY0 = srcY - fY0;
756dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    if (srcYMinusY0 % fDY != 0) {
757dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org        // This line is not part of the output, so return false for alpha, since we have
758dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org        // not added an alpha to the output.
759dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org        return false;
760dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    }
761dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // Unlike in next(), where the data is used sequentially, this function skips around,
762dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // so fDstRow and fCurrY are never updated. fDstRow must always be the starting point
763dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // of the destination bitmap's pixels, which is used to calculate the destination row
764dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    // each time this function is called.
765dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    const int dstY = srcYMinusY0 / fDY;
766dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    SkASSERT(dstY < fScaledHeight);
767dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    char* dstRow = fDstRow + dstY * fDstRowBytes;
768dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org    return fRowProc(dstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
769dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org                    fDX * fSrcPixelSize, dstY, fCTable);
770dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org}
771dac4a1d518a4788c3e2475d68cbe8683b4a448ffcommit-bot@chromium.org
7728d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com#ifdef SK_DEBUG
7738d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// The following code is for a test to ensure that changing the method to get the right row proc
7748d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// did not change the row proc unintentionally. Tested by ImageDecodingTest.cpp
7758d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
7768d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// friend of SkScaledBitmapSampler solely for the purpose of accessing fRowProc.
7778d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comclass RowProcTester {
7788d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.compublic:
7798d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    static SkScaledBitmapSampler::RowProc getRowProc(const SkScaledBitmapSampler& sampler) {
7808d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        return sampler.fRowProc;
7818d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
7828d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com};
7838d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
7848d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
7858d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Table showing the expected RowProc for each combination of inputs.
7868d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Table formated as follows:
7878d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Each group of 5 consecutive rows represents sampling from a single
7888d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// SkScaledBitmapSampler::SrcConfig.
7898d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Within each set, each row represents a different destination SkBitmap::Config
7908d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Each column represents a different combination of dither and unpremul.
7918d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// D = dither   ~D = no dither
7928d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// U = unpremul ~U = no unpremul
7938d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com//  ~D~U                D~U                     ~DU                         DU
7948d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comSkScaledBitmapSampler::RowProc gTestProcs[] = {
7958d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Gray
7968d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Gray_DA8,    Sample_Gray_DA8,        NULL,                       NULL,                       // to A8
7978d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to Index8
7988d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Gray_D565,   Sample_Gray_D565_D,     Sample_Gray_D565,           Sample_Gray_D565_D,         // to 565
7998d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Gray_D4444,  Sample_Gray_D4444_D,    Sample_Gray_D4444,          Sample_Gray_D4444_D,        // to 4444
8008d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Gray_D8888,  Sample_Gray_D8888,      Sample_Gray_D8888,          Sample_Gray_D8888,          // to 8888
8018d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // Index
8028d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to A8
8038d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Index_DI,    Sample_Index_DI,        NULL,                       NULL,                       // to Index8
8048d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Index_D565,  Sample_Index_D565_D,    Sample_Index_D565,          Sample_Index_D565_D,        // to 565
8058d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Index_D4444, Sample_Index_D4444_D,   NULL,                       NULL,                       // to 4444
8068d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_Index_D8888, Sample_Index_D8888,     NULL,                       NULL,                       // to 8888
8078d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // RGB
8088d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to A8
8098d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to Index8
8108d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D565,   Sample_RGBx_D565_D,     Sample_RGBx_D565,           Sample_RGBx_D565_D,         // to 565
8118d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D4444,  Sample_RGBx_D4444_D,    Sample_RGBx_D4444,          Sample_RGBx_D4444_D,        // to 4444
8128d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D8888,  Sample_RGBx_D8888,      Sample_RGBx_D8888,          Sample_RGBx_D8888,          // to 8888
8138d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // RGBx is the same as RGB
8148d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to A8
8158d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to Index8
8168d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D565,   Sample_RGBx_D565_D,     Sample_RGBx_D565,           Sample_RGBx_D565_D,         // to 565
8178d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D4444,  Sample_RGBx_D4444_D,    Sample_RGBx_D4444,          Sample_RGBx_D4444_D,        // to 4444
8188d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D8888,  Sample_RGBx_D8888,      Sample_RGBx_D8888,          Sample_RGBx_D8888,          // to 8888
8198d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // RGBA
8208d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to A8
8218d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to Index8
8228d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBx_D565,   Sample_RGBx_D565_D,     Sample_RGBx_D565,           Sample_RGBx_D565_D,         // to 565
8238d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBA_D4444,  Sample_RGBA_D4444_D,    NULL,                       NULL,                       // to 4444
8248d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_RGBA_D8888,  Sample_RGBA_D8888,      Sample_RGBA_D8888_Unpremul, Sample_RGBA_D8888_Unpremul, // to 8888
8258d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    // RGB_565
8268d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to A8
8278d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to Index8
8288d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    Sample_D565_D565,   Sample_D565_D565,       Sample_D565_D565,           Sample_D565_D565,           // to 565
8298d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to 4444
8308d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    NULL,               NULL,                   NULL,                       NULL,                       // to 8888
8318d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com};
8328d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
8338d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com// Dummy class that allows instantiation of an ImageDecoder, so begin can query its fields.
8348d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comclass DummyDecoder : public SkImageDecoder {
8358d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.compublic:
8368d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    DummyDecoder() {}
8378d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comprotected:
838af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III    virtual Result onDecode(SkStream*, SkBitmap*, SkImageDecoder::Mode) SK_OVERRIDE {
839af1d4f84b8730781cc6dca61748cae66c237ca57Leon Scroggins III        return kFailure;
8408d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
8418d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com};
8428d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com
8431d06999bc2ad627649396dc51d3c3776aea2eacbscroggo@google.comvoid test_row_proc_choice();
8448d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.comvoid test_row_proc_choice() {
8456c22573edb234ad14df947278cfed010669a39a7reed    const SkColorType colorTypes[] = {
8466c22573edb234ad14df947278cfed010669a39a7reed        kAlpha_8_SkColorType, kIndex_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType,
8476c22573edb234ad14df947278cfed010669a39a7reed        kN32_SkColorType
8486c22573edb234ad14df947278cfed010669a39a7reed    };
8496c22573edb234ad14df947278cfed010669a39a7reed
8508d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkBitmap dummyBitmap;
8518d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    DummyDecoder dummyDecoder;
8528d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    size_t procCounter = 0;
8538d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    for (int sc = SkScaledBitmapSampler::kGray; sc <= SkScaledBitmapSampler::kRGB_565; ++sc) {
8546c22573edb234ad14df947278cfed010669a39a7reed        for (size_t c = 0; c < SK_ARRAY_COUNT(colorTypes); ++c) {
8558d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            for (int unpremul = 0; unpremul <= 1; ++unpremul) {
8568d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                for (int dither = 0; dither <= 1; ++dither) {
8578d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    // Arbitrary width/height/sampleSize to allow SkScaledBitmapSampler to
8588d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    // be considered valid.
8598d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    SkScaledBitmapSampler sampler(10, 10, 1);
8606c22573edb234ad14df947278cfed010669a39a7reed                    dummyBitmap.setInfo(SkImageInfo::Make(10, 10,
8616c22573edb234ad14df947278cfed010669a39a7reed                                                          colorTypes[c], kPremul_SkAlphaType));
8628d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    dummyDecoder.setDitherImage(SkToBool(dither));
8638d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    dummyDecoder.setRequireUnpremultipliedColors(SkToBool(unpremul));
8648d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    sampler.begin(&dummyBitmap, (SkScaledBitmapSampler::SrcConfig) sc,
8658d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                                  dummyDecoder);
8668d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    SkScaledBitmapSampler::RowProc expected = gTestProcs[procCounter];
8678d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    SkScaledBitmapSampler::RowProc actual = RowProcTester::getRowProc(sampler);
8688d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    SkASSERT(expected == actual);
8698d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                    procCounter++;
8708d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com                }
8718d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com            }
8728d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com        }
8738d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    }
8748d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com    SkASSERT(SK_ARRAY_COUNT(gTestProcs) == procCounter);
8758d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com}
8768d2392487cd97e68c0a71da9fd5d2b42ecac5ec8scroggo@google.com#endif // SK_DEBUG
877