1 /*
2  * Copyright 2015 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/SkBlendMode.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkFont.h"
13 #include "include/core/SkImage.h"
14 #include "include/core/SkImageInfo.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkRSXform.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkRefCnt.h"
19 #include "include/core/SkScalar.h"
20 #include "include/core/SkSize.h"
21 #include "include/core/SkString.h"
22 #include "include/core/SkSurface.h"
23 #include "include/core/SkTypeface.h"
24 #include "include/core/SkTypes.h"
25 #include "tools/ToolUtils.h"
26 
27 // Create a square atlas of:
28 //   opaque white  |     opaque red
29 //  ------------------------------------
30 //   opaque green  |  transparent black
31 //
make_atlas(SkCanvas * caller,int atlasSize)32 static sk_sp<SkImage> make_atlas(SkCanvas* caller, int atlasSize) {
33     const int kBlockSize = atlasSize/2;
34 
35     SkImageInfo info = SkImageInfo::MakeN32Premul(atlasSize, atlasSize);
36     auto        surface(ToolUtils::makeSurface(caller, info));
37     SkCanvas* canvas = surface->getCanvas();
38 
39     SkPaint paint;
40     paint.setBlendMode(SkBlendMode::kSrc);
41 
42     paint.setColor(SK_ColorWHITE);
43     SkRect r = SkRect::MakeXYWH(0, 0,
44                                 SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
45     canvas->drawRect(r, paint);
46 
47     paint.setColor(SK_ColorRED);
48     r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), 0,
49                          SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
50     canvas->drawRect(r, paint);
51 
52     paint.setColor(SK_ColorGREEN);
53     r = SkRect::MakeXYWH(0, SkIntToScalar(kBlockSize),
54                          SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
55     canvas->drawRect(r, paint);
56 
57     paint.setColor(SK_ColorTRANSPARENT);
58     r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize),
59                          SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
60     canvas->drawRect(r, paint);
61 
62     return surface->makeImageSnapshot();
63 }
64 
65 // This GM tests the drawAtlas API with colors, different xfer modes
66 // and transparency in the atlas image
67 class DrawAtlasColorsGM : public skiagm::GM {
68 public:
DrawAtlasColorsGM()69     DrawAtlasColorsGM() {
70         this->setBGColor(0xFFCCCCCC);
71     }
72 
73 protected:
onShortName()74     SkString onShortName() override {
75         return SkString("draw-atlas-colors");
76     }
77 
onISize()78     SkISize onISize() override {
79         return SkISize::Make(kNumXferModes * (kAtlasSize + kPad) + kPad,
80                              2 * kNumColors * (kAtlasSize + kPad) + kTextPad + kPad);
81     }
82 
onDraw(SkCanvas * canvas)83     void onDraw(SkCanvas* canvas) override {
84         const SkRect target = SkRect::MakeWH(SkIntToScalar(kAtlasSize), SkIntToScalar(kAtlasSize));
85 
86         auto atlas = make_atlas(canvas, kAtlasSize);
87 
88         const SkBlendMode gModes[] = {
89             SkBlendMode::kClear,
90             SkBlendMode::kSrc,
91             SkBlendMode::kDst,
92             SkBlendMode::kSrcOver,
93             SkBlendMode::kDstOver,
94             SkBlendMode::kSrcIn,
95             SkBlendMode::kDstIn,
96             SkBlendMode::kSrcOut,
97             SkBlendMode::kDstOut,
98             SkBlendMode::kSrcATop,
99             SkBlendMode::kDstATop,
100             SkBlendMode::kXor,
101             SkBlendMode::kPlus,
102             SkBlendMode::kModulate,
103             SkBlendMode::kScreen,
104             SkBlendMode::kOverlay,
105             SkBlendMode::kDarken,
106             SkBlendMode::kLighten,
107             SkBlendMode::kColorDodge,
108             SkBlendMode::kColorBurn,
109             SkBlendMode::kHardLight,
110             SkBlendMode::kSoftLight,
111             SkBlendMode::kDifference,
112             SkBlendMode::kExclusion,
113             SkBlendMode::kMultiply,
114             SkBlendMode::kHue,
115             SkBlendMode::kSaturation,
116             SkBlendMode::kColor,
117             SkBlendMode::kLuminosity,
118         };
119 
120         SkColor gColors[] = {
121             SK_ColorWHITE,
122             SK_ColorRED,
123             0x88888888,         // transparent grey
124             0x88000088          // transparent blue
125         };
126 
127         const int numModes = SK_ARRAY_COUNT(gModes);
128         SkASSERT(numModes == kNumXferModes);
129         const int numColors = SK_ARRAY_COUNT(gColors);
130         SkASSERT(numColors == kNumColors);
131         SkRSXform xforms[numColors];
132         SkRect rects[numColors];
133         SkColor quadColors[numColors];
134 
135         SkPaint paint;
136         paint.setAntiAlias(true);
137 
138         for (int i = 0; i < numColors; ++i) {
139             xforms[i].set(1.0f, 0.0f, SkIntToScalar(kPad), i*(target.width()+kPad));
140             rects[i] = target;
141             quadColors[i] = gColors[i];
142         }
143 
144         SkFont font(ToolUtils::create_portable_typeface(), kTextPad);
145 
146         for (int i = 0; i < numModes; ++i) {
147             const char* label = SkBlendMode_Name(gModes[i]);
148             canvas->drawString(label, i*(target.width()+kPad)+kPad, SkIntToScalar(kTextPad),
149                                font, paint);
150         }
151 
152         for (int i = 0; i < numModes; ++i) {
153             canvas->save();
154             canvas->translate(SkIntToScalar(i*(target.height()+kPad)),
155                               SkIntToScalar(kTextPad+kPad));
156             // w/o a paint
157             canvas->drawAtlas(atlas.get(), xforms, rects, quadColors, numColors,
158                               gModes[i], nullptr, nullptr);
159             canvas->translate(0.0f, numColors*(target.height()+kPad));
160             // w a paint
161             canvas->drawAtlas(atlas.get(), xforms, rects, quadColors, numColors,
162                               gModes[i], nullptr, &paint);
163             canvas->restore();
164         }
165     }
166 
167 private:
168     static constexpr int kNumXferModes = 29;
169     static constexpr int kNumColors = 4;
170     static constexpr int kAtlasSize = 30;
171     static constexpr int kPad = 2;
172     static constexpr int kTextPad = 8;
173 
174     using INHERITED = GM;
175 };
176 DEF_GM( return new DrawAtlasColorsGM; )
177