xref: /aosp_15_r20/external/skia/gm/androidblendmodes.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2018 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/SkImageInfo.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkRect.h"
17 #include "include/core/SkSize.h"
18 #include "include/core/SkString.h"
19 #include "include/core/SkTypeface.h"
20 #include "include/utils/SkTextUtils.h"
21 #include "tools/ToolUtils.h"
22 #include "tools/fonts/FontToolUtils.h"
23 
24 #include <initializer_list>
25 
26 namespace {
27 
28 // This GM recreates the blend mode images from the Android documentation
29 class AndroidBlendModesGM : public skiagm::GM {
30 public:
AndroidBlendModesGM()31     AndroidBlendModesGM() {
32         this->setBGColor(SK_ColorBLACK);
33     }
34 
35 protected:
getName() const36     SkString getName() const override { return SkString("androidblendmodes"); }
37 
getISize()38     SkISize getISize() override {
39         return SkISize::Make(kNumCols * kBitmapSize, kNumRows * kBitmapSize);
40     }
41 
onOnceBeforeDraw()42     void onOnceBeforeDraw() override {
43         SkImageInfo ii = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize);
44         {
45             fCompositeSrc.allocPixels(ii);
46             SkCanvas tmp(fCompositeSrc);
47             tmp.clear(SK_ColorTRANSPARENT);
48             SkPaint p;
49             p.setAntiAlias(true);
50             p.setColor(ToolUtils::color_to_565(kBlue));
51             tmp.drawRect(SkRect::MakeLTRB(16, 96, 160, 240), p);
52         }
53 
54         {
55             fCompositeDst.allocPixels(ii);
56             SkCanvas tmp(fCompositeDst);
57             tmp.clear(SK_ColorTRANSPARENT);
58             SkPaint p;
59             p.setAntiAlias(true);
60             p.setColor(ToolUtils::color_to_565(kRed));
61             tmp.drawCircle(160, 95, 80, p);
62         }
63     }
64 
drawTile(SkCanvas * canvas,int xOffset,int yOffset,SkBlendMode mode)65     void drawTile(SkCanvas* canvas, int xOffset, int yOffset, SkBlendMode mode) {
66         canvas->translate(xOffset, yOffset);
67 
68         canvas->clipRect(SkRect::MakeXYWH(0, 0, 256, 256));
69 
70         canvas->saveLayer(nullptr, nullptr);
71 
72         SkPaint p;
73         canvas->drawImage(fCompositeDst.asImage(), 0, 0, SkSamplingOptions(), &p);
74         p.setBlendMode(mode);
75         canvas->drawImage(fCompositeSrc.asImage(), 0, 0, SkSamplingOptions(), &p);
76     }
77 
onDraw(SkCanvas * canvas)78     void onDraw(SkCanvas* canvas) override {
79         SkFont font = ToolUtils::DefaultPortableFont();
80 
81         ToolUtils::draw_checkerboard(canvas, kWhite, kGrey, 32);
82 
83         int xOffset = 0, yOffset = 0;
84 
85         // Android doesn't expose all the blend modes
86         // Note that the Android documentation calls:
87         //    Skia's kPlus,     add
88         //    Skia's kModulate, multiply
89         for (SkBlendMode mode : { SkBlendMode::kPlus /* add */, SkBlendMode::kClear,
90                                   SkBlendMode::kDarken, SkBlendMode::kDst,
91                                   SkBlendMode::kDstATop, SkBlendMode::kDstIn,
92                                   SkBlendMode::kDstOut, SkBlendMode::kDstOver,
93                                   SkBlendMode::kLighten, SkBlendMode::kModulate /* multiply */,
94                                   SkBlendMode::kOverlay, SkBlendMode::kScreen,
95                                   SkBlendMode::kSrc, SkBlendMode::kSrcATop,
96                                   SkBlendMode::kSrcIn, SkBlendMode::kSrcOut,
97                                   SkBlendMode::kSrcOver, SkBlendMode::kXor } ) {
98 
99             int saveCount = canvas->save();
100             this->drawTile(canvas, xOffset, yOffset, mode);
101             canvas->restoreToCount(saveCount);
102 
103             SkTextUtils::DrawString(canvas, SkBlendMode_Name(mode),
104                                xOffset + kBitmapSize/2.0f,
105                                yOffset + kBitmapSize,
106                                font, SkPaint(), SkTextUtils::kCenter_Align);
107 
108             xOffset += 256;
109             if (xOffset >= 1024) {
110                 xOffset = 0;
111                 yOffset += 256;
112             }
113         }
114     }
115 
116 private:
117     static const int kBitmapSize = 256;
118     static const int kNumRows = 5;
119     static const int kNumCols = 4;
120 
121     static const SkColor  kBlue  = SkColorSetARGB(255, 22, 150, 243);
122     static const SkColor  kRed   = SkColorSetARGB(255, 233, 30, 99);
123     static const SkColor  kWhite = SkColorSetARGB(255, 243, 243, 243);
124     static const SkColor  kGrey  = SkColorSetARGB(255, 222, 222, 222);
125 
126     SkBitmap fCompositeSrc;
127     SkBitmap fCompositeDst;
128 
129     using INHERITED = GM;
130 };
131 
132 }  // namespace
133 
134 DEF_GM(return new AndroidBlendModesGM;)
135