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