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 "SkReadBuffer.h"
11#include "SkWriteBuffer.h"
12#include "SkString.h"
13
14SkXfermode* SkLerpXfermode::Create(SkScalar scale) {
15    int scale256 = SkScalarRoundToInt(scale * 256);
16    if (scale256 >= 256) {
17        return SkXfermode::Create(SkXfermode::kSrc_Mode);
18    } else if (scale256 <= 0) {
19        return SkXfermode::Create(SkXfermode::kDst_Mode);
20    }
21    return SkNEW_ARGS(SkLerpXfermode, (scale256));
22}
23
24SkLerpXfermode::SkLerpXfermode(unsigned scale256) : fScale256(scale256) {}
25
26void SkLerpXfermode::flatten(SkWriteBuffer& buffer) const {
27    buffer.writeUInt(fScale256);
28}
29
30SkFlattenable* SkLerpXfermode::CreateProc(SkReadBuffer& buffer) {
31    return SkNEW_ARGS(SkLerpXfermode, (buffer.readUInt()));
32}
33
34void SkLerpXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
35                             const SkAlpha aa[]) const {
36    const int scale = fScale256;
37
38    if (aa) {
39        for (int i = 0; i < count; ++i) {
40            unsigned a = aa[i];
41            if (a) {
42                SkPMColor dstC = dst[i];
43                SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
44                if (a < 255) {
45                    resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7));
46                }
47                dst[i] = resC;
48            }
49        }
50    } else {
51        for (int i = 0; i < count; ++i) {
52            dst[i] = SkFastFourByteInterp256(src[i], dst[i], scale);
53        }
54    }
55}
56
57void SkLerpXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
58                             const SkAlpha aa[]) const {
59    const int scale = fScale256;
60
61    if (aa) {
62        for (int i = 0; i < count; ++i) {
63            unsigned a = aa[i];
64            if (a) {
65                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
66                SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
67                if (a < 255) {
68                    resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7));
69                }
70                dst[i] = SkPixel32ToPixel16(resC);
71            }
72        }
73    } else {
74        for (int i = 0; i < count; ++i) {
75            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
76            SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
77            dst[i] = SkPixel32ToPixel16(resC);
78        }
79    }
80}
81
82void SkLerpXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
83                             const SkAlpha aa[]) const {
84    const int scale = fScale256;
85
86    if (aa) {
87        for (int i = 0; i < count; ++i) {
88            unsigned a = aa[i];
89            if (a) {
90                unsigned dstA = dst[i];
91                unsigned resA = SkAlphaBlend(SkGetPackedA32(src[i]), dstA, scale);
92                if (a < 255) {
93                    resA = SkAlphaBlend(resA, dstA, a + (a >> 7));
94                }
95                dst[i] = resA;
96            }
97        }
98    } else {
99        for (int i = 0; i < count; ++i) {
100            dst[i] = SkAlphaBlend(SkGetPackedA32(src[i]), dst[i], scale);
101        }
102    }
103}
104
105#ifndef SK_IGNORE_TO_STRING
106void SkLerpXfermode::toString(SkString* str) const {
107    str->printf("SkLerpXfermode: scale: %g", fScale256 / 256.0);
108}
109#endif
110