1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkString.h"
9cb93a386Sopenharmony_ci#include "include/private/SkColorData.h"
10cb93a386Sopenharmony_ci#include "include/private/SkOnce.h"
11cb93a386Sopenharmony_ci#include "src/core/SkBlendModePriv.h"
12cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h"
13cb93a386Sopenharmony_ci#include "src/core/SkOpts.h"
14cb93a386Sopenharmony_ci#include "src/core/SkRasterPipeline.h"
15cb93a386Sopenharmony_ci#include "src/core/SkReadBuffer.h"
16cb93a386Sopenharmony_ci#include "src/core/SkWriteBuffer.h"
17cb93a386Sopenharmony_ci#include "src/core/SkXfermodePriv.h"
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU
20cb93a386Sopenharmony_ci#include "src/gpu/GrFragmentProcessor.h"
21cb93a386Sopenharmony_ci#include "src/gpu/effects/GrCustomXfermode.h"
22cb93a386Sopenharmony_ci#include "src/gpu/effects/GrPorterDuffXferProcessor.h"
23cb93a386Sopenharmony_ci#endif
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ciclass SkProcCoeffXfermode : public SkXfermode {
28cb93a386Sopenharmony_cipublic:
29cb93a386Sopenharmony_ci    SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci    void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
32cb93a386Sopenharmony_ci                const SkAlpha aa[]) const override {
33cb93a386Sopenharmony_ci        SkASSERT(dst && src && count >= 0);
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci        SkRasterPipeline_<256> p;
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_ci        SkRasterPipeline_MemoryCtx dst_ctx = { (void*)dst, 0 },
38cb93a386Sopenharmony_ci                                   src_ctx = { (void*)src, 0 },
39cb93a386Sopenharmony_ci                                    aa_ctx = { (void*)aa,  0 };
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci        p.append_load    (kN32_SkColorType, &src_ctx);
42cb93a386Sopenharmony_ci        p.append_load_dst(kN32_SkColorType, &dst_ctx);
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_ci        if (SkBlendMode_ShouldPreScaleCoverage(fMode, /*rgb_coverage=*/false)) {
45cb93a386Sopenharmony_ci            if (aa) {
46cb93a386Sopenharmony_ci                p.append(SkRasterPipeline::scale_u8, &aa_ctx);
47cb93a386Sopenharmony_ci            }
48cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fMode, &p);
49cb93a386Sopenharmony_ci        } else {
50cb93a386Sopenharmony_ci            SkBlendMode_AppendStages(fMode, &p);
51cb93a386Sopenharmony_ci            if (aa) {
52cb93a386Sopenharmony_ci                p.append(SkRasterPipeline::lerp_u8, &aa_ctx);
53cb93a386Sopenharmony_ci            }
54cb93a386Sopenharmony_ci        }
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci        p.append_store(kN32_SkColorType, &dst_ctx);
57cb93a386Sopenharmony_ci        p.run(0, 0, count,1);
58cb93a386Sopenharmony_ci    }
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ciprivate:
61cb93a386Sopenharmony_ci    const SkBlendMode fMode;
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    using INHERITED = SkXfermode;
64cb93a386Sopenharmony_ci};
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ciconst char* SkBlendMode_Name(SkBlendMode mode) {
67cb93a386Sopenharmony_ci    SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode);
68cb93a386Sopenharmony_ci    const char* gModeStrings[] = {
69cb93a386Sopenharmony_ci        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
70cb93a386Sopenharmony_ci        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
71cb93a386Sopenharmony_ci        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
72cb93a386Sopenharmony_ci        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
73cb93a386Sopenharmony_ci        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
74cb93a386Sopenharmony_ci    };
75cb93a386Sopenharmony_ci    return gModeStrings[(int)mode];
76cb93a386Sopenharmony_ci    static_assert(SK_ARRAY_COUNT(gModeStrings) == (size_t)SkBlendMode::kLastMode + 1, "mode_count");
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_cisk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
80cb93a386Sopenharmony_ci    if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
81cb93a386Sopenharmony_ci        // report error
82cb93a386Sopenharmony_ci        return nullptr;
83cb93a386Sopenharmony_ci    }
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
86cb93a386Sopenharmony_ci    // so we can just return nullptr from the factory.
87cb93a386Sopenharmony_ci    if (SkBlendMode::kSrcOver == mode) {
88cb93a386Sopenharmony_ci        return nullptr;
89cb93a386Sopenharmony_ci    }
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci    const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    static SkOnce        once[COUNT_BLENDMODES];
94cb93a386Sopenharmony_ci    static SkXfermode* cached[COUNT_BLENDMODES];
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci    once[(int)mode]([mode] {
97cb93a386Sopenharmony_ci        if (auto xfermode = SkOpts::create_xfermode(mode)) {
98cb93a386Sopenharmony_ci            cached[(int)mode] = xfermode;
99cb93a386Sopenharmony_ci        } else {
100cb93a386Sopenharmony_ci            cached[(int)mode] = new SkProcCoeffXfermode(mode);
101cb93a386Sopenharmony_ci        }
102cb93a386Sopenharmony_ci    });
103cb93a386Sopenharmony_ci    return sk_ref_sp(cached[(int)mode]);
104cb93a386Sopenharmony_ci}
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_cibool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
109cb93a386Sopenharmony_ci    SkBlendModeCoeff src, dst;
110cb93a386Sopenharmony_ci    if (!SkBlendMode_AsCoeff(mode, &src, &dst)) {
111cb93a386Sopenharmony_ci        return false;
112cb93a386Sopenharmony_ci    }
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    switch (src) {
115cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kDA:
116cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kDC:
117cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kIDA:
118cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kIDC:
119cb93a386Sopenharmony_ci            return false;
120cb93a386Sopenharmony_ci        default:
121cb93a386Sopenharmony_ci            break;
122cb93a386Sopenharmony_ci    }
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    switch (dst) {
125cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kZero:
126cb93a386Sopenharmony_ci            return true;
127cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kISA:
128cb93a386Sopenharmony_ci            return kOpaque_SrcColorOpacity == opacityType;
129cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kSA:
130cb93a386Sopenharmony_ci            return kTransparentBlack_SrcColorOpacity == opacityType ||
131cb93a386Sopenharmony_ci            kTransparentAlpha_SrcColorOpacity == opacityType;
132cb93a386Sopenharmony_ci        case SkBlendModeCoeff::kSC:
133cb93a386Sopenharmony_ci            return kTransparentBlack_SrcColorOpacity == opacityType;
134cb93a386Sopenharmony_ci        default:
135cb93a386Sopenharmony_ci            return false;
136cb93a386Sopenharmony_ci    }
137cb93a386Sopenharmony_ci    return false;
138cb93a386Sopenharmony_ci}
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci#if SK_SUPPORT_GPU
141cb93a386Sopenharmony_ciconst GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
142cb93a386Sopenharmony_ci    if (SkBlendMode_AsCoeff(mode, nullptr, nullptr)) {
143cb93a386Sopenharmony_ci        const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
144cb93a386Sopenharmony_ci        SkASSERT(result);
145cb93a386Sopenharmony_ci        return result;
146cb93a386Sopenharmony_ci    }
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci    SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
149cb93a386Sopenharmony_ci    return GrCustomXfermode::Get(mode);
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci#endif
152cb93a386Sopenharmony_ci
153