1b184f7f52b2a94e95aee326a3ca37110d2e43336reed/*
2b184f7f52b2a94e95aee326a3ca37110d2e43336reed * Copyright 2014 Google Inc.
3b184f7f52b2a94e95aee326a3ca37110d2e43336reed *
4b184f7f52b2a94e95aee326a3ca37110d2e43336reed * Use of this source code is governed by a BSD-style license that can be
5b184f7f52b2a94e95aee326a3ca37110d2e43336reed * found in the LICENSE file.
6b184f7f52b2a94e95aee326a3ca37110d2e43336reed */
7b184f7f52b2a94e95aee326a3ca37110d2e43336reed
8b184f7f52b2a94e95aee326a3ca37110d2e43336reed#include "SkBitmap.h"
9b184f7f52b2a94e95aee326a3ca37110d2e43336reed#include "SkCanvas.h"
10fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com#include "SkConfig8888.h"
117111d463cee893a479280c7af41757e709e33ef5reed@google.com#include "SkColorPriv.h"
12b184f7f52b2a94e95aee326a3ca37110d2e43336reed#include "SkDither.h"
134b163ed2c22facbe8891616874ae07ba7827d9c9reed@google.com#include "SkMathPriv.h"
1461c49f357a03f68c12c2650ac9915657298352a4commit-bot@chromium.org#include "SkUnPreMultiply.h"
15fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com
167111d463cee893a479280c7af41757e709e33ef5reed@google.comenum AlphaVerb {
177111d463cee893a479280c7af41757e709e33ef5reed@google.com    kNothing_AlphaVerb,
187111d463cee893a479280c7af41757e709e33ef5reed@google.com    kPremul_AlphaVerb,
197111d463cee893a479280c7af41757e709e33ef5reed@google.com    kUnpremul_AlphaVerb,
207111d463cee893a479280c7af41757e709e33ef5reed@google.com};
21fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com
227111d463cee893a479280c7af41757e709e33ef5reed@google.comtemplate <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) {
237111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (doSwapRB) {
247111d463cee893a479280c7af41757e709e33ef5reed@google.com        c = SkSwizzle_RB(c);
25fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com    }
26be41d38f1c076c9e4dc595a6e1a4eb5ccdbd307bskia.committer@gmail.com
277111d463cee893a479280c7af41757e709e33ef5reed@google.com    // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so
287111d463cee893a479280c7af41757e709e33ef5reed@google.com    // we can perform premul or unpremul the same way without knowing the swizzles for RGB.
297111d463cee893a479280c7af41757e709e33ef5reed@google.com    switch (doAlpha) {
307111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kNothing_AlphaVerb:
317111d463cee893a479280c7af41757e709e33ef5reed@google.com            // no change
32fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com            break;
337111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kPremul_AlphaVerb:
347111d463cee893a479280c7af41757e709e33ef5reed@google.com            c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c),
357111d463cee893a479280c7af41757e709e33ef5reed@google.com                                  SkGetPackedG32(c), SkGetPackedB32(c));
36fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com            break;
377111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kUnpremul_AlphaVerb:
387111d463cee893a479280c7af41757e709e33ef5reed@google.com            c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c);
39fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com            break;
40fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com    }
417111d463cee893a479280c7af41757e709e33ef5reed@google.com    return c;
42fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com}
43fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com
447111d463cee893a479280c7af41757e709e33ef5reed@google.comtemplate <bool doSwapRB, AlphaVerb doAlpha>
457111d463cee893a479280c7af41757e709e33ef5reed@google.comvoid convert32_row(uint32_t* dst, const uint32_t* src, int count) {
467111d463cee893a479280c7af41757e709e33ef5reed@google.com    // This has to be correct if src == dst (but not partial overlap)
477111d463cee893a479280c7af41757e709e33ef5reed@google.com    for (int i = 0; i < count; ++i) {
487111d463cee893a479280c7af41757e709e33ef5reed@google.com        dst[i] = convert32<doSwapRB, doAlpha>(src[i]);
49fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com    }
50fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com}
51fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com
527111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic bool is_32bit_colortype(SkColorType ct) {
537111d463cee893a479280c7af41757e709e33ef5reed@google.com    return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct;
547111d463cee893a479280c7af41757e709e33ef5reed@google.com}
55fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com
567111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) {
5744977485bdac75c055c3fa638f118874ccd2d22freed    SkASSERT(kUnknown_SkAlphaType != src);
5844977485bdac75c055c3fa638f118874ccd2d22freed    SkASSERT(kUnknown_SkAlphaType != dst);
59fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com
607111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) {
617111d463cee893a479280c7af41757e709e33ef5reed@google.com        return kNothing_AlphaVerb;
62e14792d99fc7a1a314ef5e2ca5b269239468355acommit-bot@chromium.org    }
637111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kPremul_SkAlphaType == dst) {
647111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkASSERT(kUnpremul_SkAlphaType == src);
657111d463cee893a479280c7af41757e709e33ef5reed@google.com        return kPremul_AlphaVerb;
667111d463cee893a479280c7af41757e709e33ef5reed@google.com    } else {
677111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkASSERT(kPremul_SkAlphaType == src);
687111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkASSERT(kUnpremul_SkAlphaType == dst);
697111d463cee893a479280c7af41757e709e33ef5reed@google.com        return kUnpremul_AlphaVerb;
701121170477302e25ef2a020cf2092aa6b399b3efreed@google.com    }
71231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org}
721121170477302e25ef2a020cf2092aa6b399b3efreed@google.com
737111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) {
747111d463cee893a479280c7af41757e709e33ef5reed@google.com    memcpy(dst, src, count * 4);
75231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org}
761121170477302e25ef2a020cf2092aa6b399b3efreed@google.com
777111d463cee893a479280c7af41757e709e33ef5reed@google.combool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const {
787111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (width <= 0 || height <= 0) {
797111d463cee893a479280c7af41757e709e33ef5reed@google.com        return false;
80231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org    }
817111d463cee893a479280c7af41757e709e33ef5reed@google.com
827111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) {
837111d463cee893a479280c7af41757e709e33ef5reed@google.com        return false;
847111d463cee893a479280c7af41757e709e33ef5reed@google.com    }
857111d463cee893a479280c7af41757e709e33ef5reed@google.com
867111d463cee893a479280c7af41757e709e33ef5reed@google.com    void (*proc)(uint32_t* dst, const uint32_t* src, int count);
877111d463cee893a479280c7af41757e709e33ef5reed@google.com    AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType);
887111d463cee893a479280c7af41757e709e33ef5reed@google.com    bool doSwapRB = fColorType != dst->fColorType;
897111d463cee893a479280c7af41757e709e33ef5reed@google.com
907111d463cee893a479280c7af41757e709e33ef5reed@google.com    switch (doAlpha) {
917111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kNothing_AlphaVerb:
927111d463cee893a479280c7af41757e709e33ef5reed@google.com            if (doSwapRB) {
937111d463cee893a479280c7af41757e709e33ef5reed@google.com                proc = convert32_row<true, kNothing_AlphaVerb>;
947111d463cee893a479280c7af41757e709e33ef5reed@google.com            } else {
957111d463cee893a479280c7af41757e709e33ef5reed@google.com                if (fPixels == dst->fPixels) {
967111d463cee893a479280c7af41757e709e33ef5reed@google.com                    return true;
977111d463cee893a479280c7af41757e709e33ef5reed@google.com                }
987111d463cee893a479280c7af41757e709e33ef5reed@google.com                proc = memcpy32_row;
997111d463cee893a479280c7af41757e709e33ef5reed@google.com            }
100231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org            break;
1017111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kPremul_AlphaVerb:
1027111d463cee893a479280c7af41757e709e33ef5reed@google.com            if (doSwapRB) {
1037111d463cee893a479280c7af41757e709e33ef5reed@google.com                proc = convert32_row<true, kPremul_AlphaVerb>;
1047111d463cee893a479280c7af41757e709e33ef5reed@google.com            } else {
1057111d463cee893a479280c7af41757e709e33ef5reed@google.com                proc = convert32_row<false, kPremul_AlphaVerb>;
1067111d463cee893a479280c7af41757e709e33ef5reed@google.com            }
107231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org            break;
1087111d463cee893a479280c7af41757e709e33ef5reed@google.com        case kUnpremul_AlphaVerb:
1097111d463cee893a479280c7af41757e709e33ef5reed@google.com            if (doSwapRB) {
1107111d463cee893a479280c7af41757e709e33ef5reed@google.com                proc = convert32_row<true, kUnpremul_AlphaVerb>;
1117111d463cee893a479280c7af41757e709e33ef5reed@google.com            } else {
1127111d463cee893a479280c7af41757e709e33ef5reed@google.com                proc = convert32_row<false, kUnpremul_AlphaVerb>;
1137111d463cee893a479280c7af41757e709e33ef5reed@google.com            }
114fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com            break;
115fb0d741d69a30d93b623e14ec34b737ee1673884bsalomon@google.com    }
116a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1177111d463cee893a479280c7af41757e709e33ef5reed@google.com    uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels);
1187111d463cee893a479280c7af41757e709e33ef5reed@google.com    const uint32_t* srcP = static_cast<const uint32_t*>(fPixels);
1197111d463cee893a479280c7af41757e709e33ef5reed@google.com    size_t srcInc = fRowBytes >> 2;
1207111d463cee893a479280c7af41757e709e33ef5reed@google.com    size_t dstInc = dst->fRowBytes >> 2;
1217111d463cee893a479280c7af41757e709e33ef5reed@google.com    for (int y = 0; y < height; ++y) {
1227111d463cee893a479280c7af41757e709e33ef5reed@google.com        proc(dstP, srcP, width);
1237111d463cee893a479280c7af41757e709e33ef5reed@google.com        dstP += dstInc;
1247111d463cee893a479280c7af41757e709e33ef5reed@google.com        srcP += srcInc;
125a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1267111d463cee893a479280c7af41757e709e33ef5reed@google.com    return true;
127a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
128b184f7f52b2a94e95aee326a3ca37110d2e43336reed
129b184f7f52b2a94e95aee326a3ca37110d2e43336reedstatic void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow,
130b184f7f52b2a94e95aee326a3ca37110d2e43336reed                        int rowCount) {
131b184f7f52b2a94e95aee326a3ca37110d2e43336reed    SkASSERT(bytesPerRow <= srcRB);
132b184f7f52b2a94e95aee326a3ca37110d2e43336reed    SkASSERT(bytesPerRow <= dstRB);
133b184f7f52b2a94e95aee326a3ca37110d2e43336reed    for (int i = 0; i < rowCount; ++i) {
134b184f7f52b2a94e95aee326a3ca37110d2e43336reed        memcpy(dst, src, bytesPerRow);
135b184f7f52b2a94e95aee326a3ca37110d2e43336reed        dst = (char*)dst + dstRB;
136b184f7f52b2a94e95aee326a3ca37110d2e43336reed        src = (const char*)src + srcRB;
137b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
138b184f7f52b2a94e95aee326a3ca37110d2e43336reed}
139b184f7f52b2a94e95aee326a3ca37110d2e43336reed
1400c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reedstatic void copy_g8_to_32(void* dst, size_t dstRB, const void* src, size_t srcRB, int w, int h) {
1410c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    uint32_t* dst32 = (uint32_t*)dst;
1420c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    const uint8_t* src8 = (const uint8_t*)src;
1430c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed
1440c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    for (int y = 0; y < h; ++y) {
1450c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        for (int x = 0; x < w; ++x) {
1460c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            dst32[x] = SkPackARGB32(0xFF, src8[x], src8[x], src8[x]);
1470c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        }
1480c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        dst32 = (uint32_t*)((char*)dst32 + dstRB);
1490c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        src8 += srcRB;
1500c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    }
1510c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed}
1520c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed
1530c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reedstatic void copy_32_to_g8(void* dst, size_t dstRB, const void* src, size_t srcRB,
1540c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed                          const SkImageInfo& srcInfo) {
1550c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    uint8_t* dst8 = (uint8_t*)dst;
1560c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    const uint32_t* src32 = (const uint32_t*)src;
1570c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed
1580c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    const int w = srcInfo.width();
1590c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    const int h = srcInfo.height();
1600c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    const bool isBGRA = (kBGRA_8888_SkColorType == srcInfo.colorType());
1610c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed
1620c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    for (int y = 0; y < h; ++y) {
1630c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        if (isBGRA) {
1640c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            // BGRA
1650c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            for (int x = 0; x < w; ++x) {
1660c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed                uint32_t s = src32[x];
1670c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed                dst8[x] = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF);
1680c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            }
1690c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        } else {
1700c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            // RGBA
1710c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            for (int x = 0; x < w; ++x) {
1720c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed                uint32_t s = src32[x];
1730c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed                dst8[x] = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF);
1740c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            }
1750c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        }
1760c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        src32 = (const uint32_t*)((const char*)src32 + srcRB);
1770c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        dst8 += dstRB;
1780c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    }
1790c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed}
1800c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed
181b184f7f52b2a94e95aee326a3ca37110d2e43336reedbool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
182b184f7f52b2a94e95aee326a3ca37110d2e43336reed                             const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
183b184f7f52b2a94e95aee326a3ca37110d2e43336reed                             SkColorTable* ctable) {
184b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (srcInfo.dimensions() != dstInfo.dimensions()) {
185b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
186b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
187b184f7f52b2a94e95aee326a3ca37110d2e43336reed
188b184f7f52b2a94e95aee326a3ca37110d2e43336reed    const int width = srcInfo.width();
189b184f7f52b2a94e95aee326a3ca37110d2e43336reed    const int height = srcInfo.height();
190b184f7f52b2a94e95aee326a3ca37110d2e43336reed
191b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // Handle fancy alpha swizzling if both are ARGB32
192b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) {
193b184f7f52b2a94e95aee326a3ca37110d2e43336reed        SkDstPixelInfo dstPI;
194b184f7f52b2a94e95aee326a3ca37110d2e43336reed        dstPI.fColorType = dstInfo.colorType();
195b184f7f52b2a94e95aee326a3ca37110d2e43336reed        dstPI.fAlphaType = dstInfo.alphaType();
196b184f7f52b2a94e95aee326a3ca37110d2e43336reed        dstPI.fPixels = dstPixels;
197b184f7f52b2a94e95aee326a3ca37110d2e43336reed        dstPI.fRowBytes = dstRB;
198775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein
199b184f7f52b2a94e95aee326a3ca37110d2e43336reed        SkSrcPixelInfo srcPI;
200b184f7f52b2a94e95aee326a3ca37110d2e43336reed        srcPI.fColorType = srcInfo.colorType();
201b184f7f52b2a94e95aee326a3ca37110d2e43336reed        srcPI.fAlphaType = srcInfo.alphaType();
202b184f7f52b2a94e95aee326a3ca37110d2e43336reed        srcPI.fPixels = srcPixels;
203b184f7f52b2a94e95aee326a3ca37110d2e43336reed        srcPI.fRowBytes = srcRB;
204775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein
205b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return srcPI.convertPixelsTo(&dstPI, width, height);
206b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
207b184f7f52b2a94e95aee326a3ca37110d2e43336reed
208b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // If they agree on colorType and the alphaTypes are compatible, then we just memcpy.
209b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // Note: we've already taken care of 32bit colortypes above.
210b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (srcInfo.colorType() == dstInfo.colorType()) {
211b184f7f52b2a94e95aee326a3ca37110d2e43336reed        switch (srcInfo.colorType()) {
212b184f7f52b2a94e95aee326a3ca37110d2e43336reed            case kRGB_565_SkColorType:
213b184f7f52b2a94e95aee326a3ca37110d2e43336reed            case kAlpha_8_SkColorType:
2140c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed            case kGray_8_SkColorType:
215b184f7f52b2a94e95aee326a3ca37110d2e43336reed                break;
216b184f7f52b2a94e95aee326a3ca37110d2e43336reed            case kIndex_8_SkColorType:
217b184f7f52b2a94e95aee326a3ca37110d2e43336reed            case kARGB_4444_SkColorType:
218b184f7f52b2a94e95aee326a3ca37110d2e43336reed                if (srcInfo.alphaType() != dstInfo.alphaType()) {
219b184f7f52b2a94e95aee326a3ca37110d2e43336reed                    return false;
220b184f7f52b2a94e95aee326a3ca37110d2e43336reed                }
221b184f7f52b2a94e95aee326a3ca37110d2e43336reed                break;
222b184f7f52b2a94e95aee326a3ca37110d2e43336reed            default:
223b184f7f52b2a94e95aee326a3ca37110d2e43336reed                return false;
224b184f7f52b2a94e95aee326a3ca37110d2e43336reed        }
225b184f7f52b2a94e95aee326a3ca37110d2e43336reed        rect_memcpy(dstPixels, dstRB, srcPixels, srcRB, width * srcInfo.bytesPerPixel(), height);
226b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return true;
227b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
228b184f7f52b2a94e95aee326a3ca37110d2e43336reed
229b184f7f52b2a94e95aee326a3ca37110d2e43336reed    /*
230b184f7f52b2a94e95aee326a3ca37110d2e43336reed     *  Begin section where we try to change colorTypes along the way. Not all combinations
231b184f7f52b2a94e95aee326a3ca37110d2e43336reed     *  are supported.
232b184f7f52b2a94e95aee326a3ca37110d2e43336reed     */
233b184f7f52b2a94e95aee326a3ca37110d2e43336reed
2340c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    if (kGray_8_SkColorType == srcInfo.colorType() && 4 == dstInfo.bytesPerPixel()) {
2350c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        copy_g8_to_32(dstPixels, dstRB, srcPixels, srcRB, width, height);
2360c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        return true;
2370c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    }
2380c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    if (kGray_8_SkColorType == dstInfo.colorType() && 4 == srcInfo.bytesPerPixel()) {
2390c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        copy_32_to_g8(dstPixels, dstRB, srcPixels, srcRB, srcInfo);
2400c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed        return true;
2410c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed    }
2420c9b1a8d05ea6ec5dfae0ead854304673d94d2c2reed
243b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // Can no longer draw directly into 4444, but we can manually whack it for a few combinations
244b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (kARGB_4444_SkColorType == dstInfo.colorType() &&
245b184f7f52b2a94e95aee326a3ca37110d2e43336reed        (kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) {
246b184f7f52b2a94e95aee326a3ca37110d2e43336reed        if (srcInfo.alphaType() == kUnpremul_SkAlphaType) {
247b184f7f52b2a94e95aee326a3ca37110d2e43336reed            // Our method for converting to 4444 assumes premultiplied.
248b184f7f52b2a94e95aee326a3ca37110d2e43336reed            return false;
249b184f7f52b2a94e95aee326a3ca37110d2e43336reed        }
250775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein
251b184f7f52b2a94e95aee326a3ca37110d2e43336reed        const SkPMColor* table = NULL;
252b184f7f52b2a94e95aee326a3ca37110d2e43336reed        if (kIndex_8_SkColorType == srcInfo.colorType()) {
253b184f7f52b2a94e95aee326a3ca37110d2e43336reed            if (NULL == ctable) {
254b184f7f52b2a94e95aee326a3ca37110d2e43336reed                return false;
255b184f7f52b2a94e95aee326a3ca37110d2e43336reed            }
256775b8199a214af57c3ea7969e9d456f5f3eb137fmtklein            table = ctable->readColors();
257b184f7f52b2a94e95aee326a3ca37110d2e43336reed        }
258b184f7f52b2a94e95aee326a3ca37110d2e43336reed
259b184f7f52b2a94e95aee326a3ca37110d2e43336reed        for (int y = 0; y < height; ++y) {
260b184f7f52b2a94e95aee326a3ca37110d2e43336reed            DITHER_4444_SCAN(y);
261b184f7f52b2a94e95aee326a3ca37110d2e43336reed            SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*)dstPixels;
262b184f7f52b2a94e95aee326a3ca37110d2e43336reed            if (table) {
263b184f7f52b2a94e95aee326a3ca37110d2e43336reed                const uint8_t* SK_RESTRICT srcRow = (const uint8_t*)srcPixels;
264b184f7f52b2a94e95aee326a3ca37110d2e43336reed                for (int x = 0; x < width; ++x) {
265b184f7f52b2a94e95aee326a3ca37110d2e43336reed                    dstRow[x] = SkDitherARGB32To4444(table[srcRow[x]], DITHER_VALUE(x));
266b184f7f52b2a94e95aee326a3ca37110d2e43336reed                }
267b184f7f52b2a94e95aee326a3ca37110d2e43336reed            } else {
268b184f7f52b2a94e95aee326a3ca37110d2e43336reed                const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)srcPixels;
269b184f7f52b2a94e95aee326a3ca37110d2e43336reed                for (int x = 0; x < width; ++x) {
270b184f7f52b2a94e95aee326a3ca37110d2e43336reed                    dstRow[x] = SkDitherARGB32To4444(srcRow[x], DITHER_VALUE(x));
271b184f7f52b2a94e95aee326a3ca37110d2e43336reed                }
272b184f7f52b2a94e95aee326a3ca37110d2e43336reed            }
273b184f7f52b2a94e95aee326a3ca37110d2e43336reed            dstPixels = (char*)dstPixels + dstRB;
274b184f7f52b2a94e95aee326a3ca37110d2e43336reed            srcPixels = (const char*)srcPixels + srcRB;
275b184f7f52b2a94e95aee326a3ca37110d2e43336reed        }
276b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return true;
277b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
278b184f7f52b2a94e95aee326a3ca37110d2e43336reed
279b184f7f52b2a94e95aee326a3ca37110d2e43336reed    if (dstInfo.alphaType() == kUnpremul_SkAlphaType) {
280b184f7f52b2a94e95aee326a3ca37110d2e43336reed        // We do not support drawing to unpremultiplied bitmaps.
281b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return false;
282b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
283b184f7f52b2a94e95aee326a3ca37110d2e43336reed
284b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // Final fall-back, draw with a canvas
285b184f7f52b2a94e95aee326a3ca37110d2e43336reed    //
286b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // Always clear the dest in case one of the blitters accesses it
287b184f7f52b2a94e95aee326a3ca37110d2e43336reed    // TODO: switch the allocation of tmpDst to call sk_calloc_throw
288b184f7f52b2a94e95aee326a3ca37110d2e43336reed    {
289b184f7f52b2a94e95aee326a3ca37110d2e43336reed        SkBitmap bm;
290b184f7f52b2a94e95aee326a3ca37110d2e43336reed        if (!bm.installPixels(srcInfo, const_cast<void*>(srcPixels), srcRB, ctable, NULL, NULL)) {
291b184f7f52b2a94e95aee326a3ca37110d2e43336reed            return false;
292b184f7f52b2a94e95aee326a3ca37110d2e43336reed        }
293b184f7f52b2a94e95aee326a3ca37110d2e43336reed        SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterDirect(dstInfo, dstPixels, dstRB));
294b184f7f52b2a94e95aee326a3ca37110d2e43336reed        if (NULL == canvas.get()) {
295b184f7f52b2a94e95aee326a3ca37110d2e43336reed            return false;
296b184f7f52b2a94e95aee326a3ca37110d2e43336reed        }
297b184f7f52b2a94e95aee326a3ca37110d2e43336reed
298b184f7f52b2a94e95aee326a3ca37110d2e43336reed        SkPaint  paint;
299b184f7f52b2a94e95aee326a3ca37110d2e43336reed        paint.setDither(true);
300b184f7f52b2a94e95aee326a3ca37110d2e43336reed
301b184f7f52b2a94e95aee326a3ca37110d2e43336reed        canvas->clear(0);
302b184f7f52b2a94e95aee326a3ca37110d2e43336reed        canvas->drawBitmap(bm, 0, 0, &paint);
303b184f7f52b2a94e95aee326a3ca37110d2e43336reed        return true;
304b184f7f52b2a94e95aee326a3ca37110d2e43336reed    }
305b184f7f52b2a94e95aee326a3ca37110d2e43336reed}
306b184f7f52b2a94e95aee326a3ca37110d2e43336reed
307