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