1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc.
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/SkPaint.h"
9cb93a386Sopenharmony_ci#include "src/core/SkColorFilterBase.h"
10cb93a386Sopenharmony_ci#include "src/core/SkColorSpacePriv.h"
11cb93a386Sopenharmony_ci#include "src/core/SkPaintPriv.h"
12cb93a386Sopenharmony_ci#include "src/core/SkXfermodePriv.h"
13cb93a386Sopenharmony_ci#include "src/shaders/SkColorFilterShader.h"
14cb93a386Sopenharmony_ci#include "src/shaders/SkShaderBase.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_cistatic bool changes_alpha(const SkPaint& paint) {
17cb93a386Sopenharmony_ci    SkColorFilter* cf = paint.getColorFilter();
18cb93a386Sopenharmony_ci    return cf && !as_CFB(cf)->isAlphaUnchanged();
19cb93a386Sopenharmony_ci}
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_cibool SkPaintPriv::Overwrites(const SkPaint* paint, ShaderOverrideOpacity overrideOpacity) {
22cb93a386Sopenharmony_ci    if (!paint) {
23cb93a386Sopenharmony_ci        // No paint means we default to SRC_OVER, so we overwrite iff our shader-override
24cb93a386Sopenharmony_ci        // is opaque, or we don't have one.
25cb93a386Sopenharmony_ci        return overrideOpacity != kNotOpaque_ShaderOverrideOpacity;
26cb93a386Sopenharmony_ci    }
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci    SkXfermode::SrcColorOpacity opacityType = SkXfermode::kUnknown_SrcColorOpacity;
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci    if (!changes_alpha(*paint)) {
31cb93a386Sopenharmony_ci        const unsigned paintAlpha = paint->getAlpha();
32cb93a386Sopenharmony_ci        if (0xff == paintAlpha && overrideOpacity != kNotOpaque_ShaderOverrideOpacity &&
33cb93a386Sopenharmony_ci            (!paint->getShader() || paint->getShader()->isOpaque()))
34cb93a386Sopenharmony_ci        {
35cb93a386Sopenharmony_ci            opacityType = SkXfermode::kOpaque_SrcColorOpacity;
36cb93a386Sopenharmony_ci        } else if (0 == paintAlpha) {
37cb93a386Sopenharmony_ci            if (overrideOpacity == kNone_ShaderOverrideOpacity && !paint->getShader()) {
38cb93a386Sopenharmony_ci                opacityType = SkXfermode::kTransparentBlack_SrcColorOpacity;
39cb93a386Sopenharmony_ci            } else {
40cb93a386Sopenharmony_ci                opacityType = SkXfermode::kTransparentAlpha_SrcColorOpacity;
41cb93a386Sopenharmony_ci            }
42cb93a386Sopenharmony_ci        }
43cb93a386Sopenharmony_ci    }
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ci    const auto bm = paint->asBlendMode();
46cb93a386Sopenharmony_ci    if (!bm) {
47cb93a386Sopenharmony_ci        return false;   // don't know for sure, so we play it safe and return false.
48cb93a386Sopenharmony_ci    }
49cb93a386Sopenharmony_ci    return SkXfermode::IsOpaque(bm.value(), opacityType);
50cb93a386Sopenharmony_ci}
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_cibool SkPaintPriv::ShouldDither(const SkPaint& p, SkColorType dstCT) {
53cb93a386Sopenharmony_ci    // The paint dither flag can veto.
54cb93a386Sopenharmony_ci    if (!p.isDither()) {
55cb93a386Sopenharmony_ci        return false;
56cb93a386Sopenharmony_ci    }
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_ci    // We always dither 565 or 4444 when requested.
59cb93a386Sopenharmony_ci    if (dstCT == kRGB_565_SkColorType || dstCT == kARGB_4444_SkColorType) {
60cb93a386Sopenharmony_ci        return true;
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    // Otherwise, dither is only needed for non-const paints.
64cb93a386Sopenharmony_ci    return p.getImageFilter() || p.getMaskFilter() ||
65cb93a386Sopenharmony_ci           (p.getShader() && !as_SB(p.getShader())->isConstant());
66cb93a386Sopenharmony_ci}
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci// return true if the paint is just a single color (i.e. not a shader). If its
69cb93a386Sopenharmony_ci// a shader, then we can't compute a const luminance for it :(
70cb93a386Sopenharmony_cistatic bool just_a_color(const SkPaint& paint, SkColor* color) {
71cb93a386Sopenharmony_ci    SkColor c = paint.getColor();
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    const auto* shader = as_SB(paint.getShader());
74cb93a386Sopenharmony_ci    if (shader && !shader->asLuminanceColor(&c)) {
75cb93a386Sopenharmony_ci        return false;
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci    if (paint.getColorFilter()) {
78cb93a386Sopenharmony_ci        c = paint.getColorFilter()->filterColor(c);
79cb93a386Sopenharmony_ci    }
80cb93a386Sopenharmony_ci    if (color) {
81cb93a386Sopenharmony_ci        *color = c;
82cb93a386Sopenharmony_ci    }
83cb93a386Sopenharmony_ci    return true;
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ciSkColor SkPaintPriv::ComputeLuminanceColor(const SkPaint& paint) {
87cb93a386Sopenharmony_ci    SkColor c;
88cb93a386Sopenharmony_ci    if (!just_a_color(paint, &c)) {
89cb93a386Sopenharmony_ci        c = SkColorSetRGB(0x7F, 0x80, 0x7F);
90cb93a386Sopenharmony_ci    }
91cb93a386Sopenharmony_ci    return c;
92cb93a386Sopenharmony_ci}
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_civoid SkPaintPriv::RemoveColorFilter(SkPaint* p, SkColorSpace* dstCS) {
95cb93a386Sopenharmony_ci    if (SkColorFilter* filter = p->getColorFilter()) {
96cb93a386Sopenharmony_ci        if (SkShader* shader = p->getShader()) {
97cb93a386Sopenharmony_ci            // SkColorFilterShader will modulate the shader color by paint alpha
98cb93a386Sopenharmony_ci            // before applying the filter, so we'll reset it to opaque.
99cb93a386Sopenharmony_ci            p->setShader(sk_make_sp<SkColorFilterShader>(sk_ref_sp(shader),
100cb93a386Sopenharmony_ci                                                         p->getAlphaf(),
101cb93a386Sopenharmony_ci                                                         sk_ref_sp(filter)));
102cb93a386Sopenharmony_ci            p->setAlphaf(1.0f);
103cb93a386Sopenharmony_ci        } else {
104cb93a386Sopenharmony_ci            p->setColor(filter->filterColor4f(p->getColor4f(), sk_srgb_singleton(), dstCS), dstCS);
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci        p->setColorFilter(nullptr);
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci}
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ciSkScalar SkPaintPriv::ComputeResScaleForStroking(const SkMatrix& matrix) {
111cb93a386Sopenharmony_ci    // Not sure how to handle perspective differently, so we just don't try (yet)
112cb93a386Sopenharmony_ci    SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]);
113cb93a386Sopenharmony_ci    SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX],  matrix[SkMatrix::kMScaleY]);
114cb93a386Sopenharmony_ci    if (SkScalarsAreFinite(sx, sy)) {
115cb93a386Sopenharmony_ci        SkScalar scale = std::max(sx, sy);
116cb93a386Sopenharmony_ci        if (scale > 0) {
117cb93a386Sopenharmony_ci            return scale;
118cb93a386Sopenharmony_ci        }
119cb93a386Sopenharmony_ci    }
120cb93a386Sopenharmony_ci    return 1;
121cb93a386Sopenharmony_ci}
122