1/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkLerpXfermode.h"
9#include "SkColorPriv.h"
10#include "SkFlattenableBuffers.h"
11#include "SkString.h"
12
13SkXfermode* SkLerpXfermode::Create(SkScalar scale) {
14    int scale256 = SkScalarRoundToInt(scale * 256);
15    if (scale256 >= 256) {
16        return SkXfermode::Create(SkXfermode::kSrc_Mode);
17    } else if (scale256 <= 0) {
18        return SkXfermode::Create(SkXfermode::kDst_Mode);
19    }
20    return SkNEW_ARGS(SkLerpXfermode, (scale256));
21}
22
23SkLerpXfermode::SkLerpXfermode(unsigned scale256) : fScale256(scale256) {}
24
25SkLerpXfermode::SkLerpXfermode(SkFlattenableReadBuffer& buffer)
26    : INHERITED(buffer) {
27    fScale256 = buffer.readUInt();
28}
29
30void SkLerpXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
31    this->INHERITED::flatten(buffer);
32    buffer.writeUInt(fScale256);
33}
34
35void SkLerpXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
36                             const SkAlpha aa[]) const {
37    const int scale = fScale256;
38
39    if (aa) {
40        for (int i = 0; i < count; ++i) {
41            unsigned a = aa[i];
42            if (a) {
43                SkPMColor dstC = dst[i];
44                SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
45                if (a < 255) {
46                    resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7));
47                }
48                dst[i] = resC;
49            }
50        }
51    } else {
52        for (int i = 0; i < count; ++i) {
53            dst[i] = SkFastFourByteInterp256(src[i], dst[i], scale);
54        }
55    }
56}
57
58void SkLerpXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
59                             const SkAlpha aa[]) const {
60    const int scale = fScale256;
61
62    if (aa) {
63        for (int i = 0; i < count; ++i) {
64            unsigned a = aa[i];
65            if (a) {
66                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
67                SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
68                if (a < 255) {
69                    resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7));
70                }
71                dst[i] = SkPixel32ToPixel16(resC);
72            }
73        }
74    } else {
75        for (int i = 0; i < count; ++i) {
76            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
77            SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
78            dst[i] = SkPixel32ToPixel16(resC);
79        }
80    }
81}
82
83void SkLerpXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
84                             const SkAlpha aa[]) const {
85    const int scale = fScale256;
86
87    if (aa) {
88        for (int i = 0; i < count; ++i) {
89            unsigned a = aa[i];
90            if (a) {
91                unsigned dstA = dst[i];
92                unsigned resA = SkAlphaBlend(SkGetPackedA32(src[i]), dstA, scale);
93                if (a < 255) {
94                    resA = SkAlphaBlend(resA, dstA, a + (a >> 7));
95                }
96                dst[i] = resA;
97            }
98        }
99    } else {
100        for (int i = 0; i < count; ++i) {
101            dst[i] = SkAlphaBlend(SkGetPackedA32(src[i]), dst[i], scale);
102        }
103    }
104}
105
106#ifdef SK_DEVELOPER
107void SkLerpXfermode::toString(SkString* str) const {
108    str->printf("SkLerpXfermode: scale: %g", fScale256 / 256.0);
109}
110#endif
111