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 typedef GM INHERITED;
175 };
176 DEF_GM( return new DrawAtlasColorsGM; )
177