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