xref: /aosp_15_r20/external/skia/gm/coloremoji_blendmodes.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2014 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 "gm/gm.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkBlendMode.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkFont.h"
14 #include "include/core/SkFontStyle.h"
15 #include "include/core/SkFontTypes.h"
16 #include "include/core/SkImageInfo.h"
17 #include "include/core/SkMatrix.h"
18 #include "include/core/SkPaint.h"
19 #include "include/core/SkRect.h"
20 #include "include/core/SkRefCnt.h"
21 #include "include/core/SkScalar.h"
22 #include "include/core/SkShader.h"
23 #include "include/core/SkSize.h"
24 #include "include/core/SkString.h"
25 #include "include/core/SkTileMode.h"
26 #include "include/core/SkTypeface.h"
27 #include "include/core/SkTypes.h"
28 #include "include/effects/SkGradientShader.h"
29 #include "include/utils/SkTextUtils.h"
30 #include "src/base/SkUTF.h"
31 #include "tools/ToolUtils.h"
32 #include "tools/fonts/FontToolUtils.h"
33 
34 #include <string.h>
35 
36 namespace {
37 
38 static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
39 
40 class ColorEmojiBlendModesGM : public skiagm::GM {
41 public:
42     const static int W = 64;
43     const static int H = 64;
ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat format)44     ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat format) : fFormat(format) {}
45 
46 protected:
onOnceBeforeDraw()47     void onOnceBeforeDraw() override {
48         const SkColor colors[] = {
49             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
50             SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW
51         };
52         SkMatrix local;
53         local.setRotate(180);
54         SkPaint paint;
55         paint.setAntiAlias(true);
56         paint.setShader(SkGradientShader::MakeSweep(0, 0, colors, nullptr, std::size(colors),
57                                                     0, &local));
58 
59         sk_sp<SkTypeface> orig(ToolUtils::CreatePortableTypeface("serif", SkFontStyle::Bold()));
60         SkASSERT(orig);
61         fColorSample = ToolUtils::EmojiSample(fFormat);
62 
63         fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType,
64                                             kOpaque_SkAlphaType), gData, 4);
65     }
66 
getName() const67     SkString getName() const override {
68         return SkString("coloremoji_blendmodes_") += ToolUtils::NameForFontFormat(fFormat);
69     }
70 
getISize()71     SkISize getISize() override { return {400, 640}; }
72 
onDraw(SkCanvas * canvas,SkString * errorMsg)73     DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
74 
75         if (!fColorSample.typeface) {
76             *errorMsg = SkStringPrintf("Unable to instantiate emoji test font of format %s.",
77                                        ToolUtils::NameForFontFormat(fFormat).c_str());
78             return DrawResult::kSkip;
79         }
80 
81         canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
82 
83         const SkBlendMode gModes[] = {
84             SkBlendMode::kClear,
85             SkBlendMode::kSrc,
86             SkBlendMode::kDst,
87             SkBlendMode::kSrcOver,
88             SkBlendMode::kDstOver,
89             SkBlendMode::kSrcIn,
90             SkBlendMode::kDstIn,
91             SkBlendMode::kSrcOut,
92             SkBlendMode::kDstOut,
93             SkBlendMode::kSrcATop,
94             SkBlendMode::kDstATop,
95 
96             SkBlendMode::kXor,
97             SkBlendMode::kPlus,
98             SkBlendMode::kModulate,
99             SkBlendMode::kScreen,
100             SkBlendMode::kOverlay,
101             SkBlendMode::kDarken,
102             SkBlendMode::kLighten,
103             SkBlendMode::kColorDodge,
104             SkBlendMode::kColorBurn,
105             SkBlendMode::kHardLight,
106             SkBlendMode::kSoftLight,
107             SkBlendMode::kDifference,
108             SkBlendMode::kExclusion,
109             SkBlendMode::kMultiply,
110             SkBlendMode::kHue,
111             SkBlendMode::kSaturation,
112             SkBlendMode::kColor,
113             SkBlendMode::kLuminosity,
114         };
115 
116         const SkScalar w = SkIntToScalar(W);
117         const SkScalar h = SkIntToScalar(H);
118         SkMatrix m;
119         m.setScale(SkIntToScalar(6), SkIntToScalar(6));
120         auto s = fBG.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions(), m);
121 
122         SkFont labelFont(ToolUtils::DefaultPortableTypeface());
123 
124         SkPaint textP;
125         textP.setAntiAlias(true);
126         SkFont textFont(fColorSample.typeface, 70);
127 
128         const int kWrap = 5;
129 
130         SkScalar x0 = 0;
131         SkScalar y0 = 0;
132         SkScalar x = x0, y = y0;
133         for (size_t i = 0; i < std::size(gModes); i++) {
134             SkRect r;
135             r.setLTRB(x, y, x+w, y+h);
136 
137             SkPaint p;
138             p.setStyle(SkPaint::kFill_Style);
139             p.setShader(s);
140             canvas->drawRect(r, p);
141 
142             r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
143             p.setStyle(SkPaint::kStroke_Style);
144             p.setShader(nullptr);
145             canvas->drawRect(r, p);
146 
147             {
148                 SkAutoCanvasRestore arc(canvas, true);
149                 canvas->clipRect(r);
150                 textP.setBlendMode(gModes[i]);
151                 const char* text    = fColorSample.sampleText;
152                 SkUnichar unichar = SkUTF::NextUTF8(&text, text + strlen(text));
153                 SkASSERT(unichar >= 0);
154                 canvas->drawSimpleText(&unichar, 4, SkTextEncoding::kUTF32,
155                                        x+ w/10.f, y + 7.f*h/8.f, textFont, textP);
156             }
157 #if 1
158             const char* label = SkBlendMode_Name(gModes[i]);
159             SkTextUtils::DrawString(canvas, label, x + w/2, y - labelFont.getSize()/2,
160                                     labelFont, SkPaint(), SkTextUtils::kCenter_Align);
161 #endif
162             x += w + SkIntToScalar(10);
163             if ((i % kWrap) == kWrap - 1) {
164                 x = x0;
165                 y += h + SkIntToScalar(30);
166             }
167         }
168 
169         return DrawResult::kOk;
170     }
171 
172 private:
173     SkBitmap fBG;
174     ToolUtils::EmojiFontFormat fFormat;
175     ToolUtils::EmojiTestSample fColorSample;
176 
177     using INHERITED = GM;
178 };
179 }  // namespace
180 
181 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::ColrV0);)
182 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Sbix);)
183 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Cbdt);)
184 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Test);)
185 DEF_GM(return new ColorEmojiBlendModesGM(ToolUtils::EmojiFontFormat::Svg);)
186