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