1#include "SkConfig8888.h"
2#include "SkColorPriv.h"
3#include "SkMathPriv.h"
4#include "SkUnPreMultiply.h"
5
6enum AlphaVerb {
7    kNothing_AlphaVerb,
8    kPremul_AlphaVerb,
9    kUnpremul_AlphaVerb,
10};
11
12template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) {
13    if (doSwapRB) {
14        c = SkSwizzle_RB(c);
15    }
16
17    // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so
18    // we can perform premul or unpremul the same way without knowing the swizzles for RGB.
19    switch (doAlpha) {
20        case kNothing_AlphaVerb:
21            // no change
22            break;
23        case kPremul_AlphaVerb:
24            c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c),
25                                  SkGetPackedG32(c), SkGetPackedB32(c));
26            break;
27        case kUnpremul_AlphaVerb:
28            c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c);
29            break;
30    }
31    return c;
32}
33
34template <bool doSwapRB, AlphaVerb doAlpha>
35void convert32_row(uint32_t* dst, const uint32_t* src, int count) {
36    // This has to be correct if src == dst (but not partial overlap)
37    for (int i = 0; i < count; ++i) {
38        dst[i] = convert32<doSwapRB, doAlpha>(src[i]);
39    }
40}
41
42static bool is_32bit_colortype(SkColorType ct) {
43    return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct;
44}
45
46static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) {
47    SkASSERT(kIgnore_SkAlphaType != src);
48    SkASSERT(kIgnore_SkAlphaType != dst);
49
50    if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) {
51        return kNothing_AlphaVerb;
52    }
53    if (kPremul_SkAlphaType == dst) {
54        SkASSERT(kUnpremul_SkAlphaType == src);
55        return kPremul_AlphaVerb;
56    } else {
57        SkASSERT(kPremul_SkAlphaType == src);
58        SkASSERT(kUnpremul_SkAlphaType == dst);
59        return kUnpremul_AlphaVerb;
60    }
61}
62
63static void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) {
64    memcpy(dst, src, count * 4);
65}
66
67bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const {
68    if (width <= 0 || height <= 0) {
69        return false;
70    }
71
72    if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) {
73        return false;
74    }
75
76    void (*proc)(uint32_t* dst, const uint32_t* src, int count);
77    AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType);
78    bool doSwapRB = fColorType != dst->fColorType;
79
80    switch (doAlpha) {
81        case kNothing_AlphaVerb:
82            if (doSwapRB) {
83                proc = convert32_row<true, kNothing_AlphaVerb>;
84            } else {
85                if (fPixels == dst->fPixels) {
86                    return true;
87                }
88                proc = memcpy32_row;
89            }
90            break;
91        case kPremul_AlphaVerb:
92            if (doSwapRB) {
93                proc = convert32_row<true, kPremul_AlphaVerb>;
94            } else {
95                proc = convert32_row<false, kPremul_AlphaVerb>;
96            }
97            break;
98        case kUnpremul_AlphaVerb:
99            if (doSwapRB) {
100                proc = convert32_row<true, kUnpremul_AlphaVerb>;
101            } else {
102                proc = convert32_row<false, kUnpremul_AlphaVerb>;
103            }
104            break;
105    }
106
107    uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels);
108    const uint32_t* srcP = static_cast<const uint32_t*>(fPixels);
109    size_t srcInc = fRowBytes >> 2;
110    size_t dstInc = dst->fRowBytes >> 2;
111    for (int y = 0; y < height; ++y) {
112        proc(dstP, srcP, width);
113        dstP += dstInc;
114        srcP += srcInc;
115    }
116    return true;
117}
118