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
269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkLerpXfermode::SkLerpXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {
28b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    fScale256 = buffer.readUInt();
29b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
31b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
328b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkLerpXfermode::flatten(SkWriteBuffer& buffer) const {
33b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    buffer.writeUInt(fScale256);
34b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
35b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkLerpXfermode::CreateProc(SkReadBuffer& buffer) {
379fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkNEW_ARGS(SkLerpXfermode, (buffer.readUInt()));
389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
40b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::xfer32(SkPMColor dst[], const SkPMColor src[], int count,
41b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                             const SkAlpha aa[]) const {
42b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    const int scale = fScale256;
43b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
44b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    if (aa) {
45b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        for (int i = 0; i < count; ++i) {
46b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            unsigned a = aa[i];
47b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            if (a) {
48b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                SkPMColor dstC = dst[i];
49b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
50b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                if (a < 255) {
51b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                    resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7));
52b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                }
53b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                dst[i] = resC;
54b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            }
55b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        }
56b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    } else {
57b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        for (int i = 0; i < count; ++i) {
58b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            dst[i] = SkFastFourByteInterp256(src[i], dst[i], scale);
59b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        }
60b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    }
61b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
62b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
63b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::xfer16(uint16_t dst[], const SkPMColor src[], int count,
64b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                             const SkAlpha aa[]) const {
65b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    const int scale = fScale256;
66b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
67b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    if (aa) {
68b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        for (int i = 0; i < count; ++i) {
69b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            unsigned a = aa[i];
70b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            if (a) {
71b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
72b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
73b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                if (a < 255) {
74b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                    resC = SkFastFourByteInterp256(resC, dstC, a + (a >> 7));
75b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                }
76b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                dst[i] = SkPixel32ToPixel16(resC);
77b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            }
78b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        }
79b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    } else {
80b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        for (int i = 0; i < count; ++i) {
81b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
82b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            SkPMColor resC = SkFastFourByteInterp256(src[i], dstC, scale);
83b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            dst[i] = SkPixel32ToPixel16(resC);
84b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        }
85b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    }
86b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
87b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
88b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::xferA8(SkAlpha dst[], const SkPMColor src[], int count,
89b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                             const SkAlpha aa[]) const {
90b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    const int scale = fScale256;
91b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
92b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    if (aa) {
93b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        for (int i = 0; i < count; ++i) {
94b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            unsigned a = aa[i];
95b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            if (a) {
96b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                unsigned dstA = dst[i];
97b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                unsigned resA = SkAlphaBlend(SkGetPackedA32(src[i]), dstA, scale);
98b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                if (a < 255) {
99b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                    resA = SkAlphaBlend(resA, dstA, a + (a >> 7));
100b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                }
101b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com                dst[i] = resA;
102b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            }
103b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        }
104b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    } else {
105b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        for (int i = 0; i < count; ++i) {
106b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com            dst[i] = SkAlphaBlend(SkGetPackedA32(src[i]), dst[i], scale);
107b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com        }
108b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    }
109b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
110b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com
1110f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
112b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.comvoid SkLerpXfermode::toString(SkString* str) const {
113b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com    str->printf("SkLerpXfermode: scale: %g", fScale256 / 256.0);
114b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com}
115b83cb9bf89d26b40e4db83db1b9782437d2adba7reed@google.com#endif
116