Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
aaxfermodes.cpp
Go to the documentation of this file.
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"
12#include "include/core/SkFont.h"
16#include "include/core/SkRect.h"
18#include "include/core/SkSize.h"
23#include "tools/ToolUtils.h"
25
26enum {
27 kXfermodeCount = (int)SkBlendMode::kLastMode + 1 + 1, // extra for arith
37};
38
39constexpr SkColor kBGColor = 0xc8d2b887;
40
41constexpr SkColor kShapeColors[2] = {
42 0x82ff0080, // input color unknown
43 0xff00ffff, // input color opaque
44};
45
54
55/**
56 * Verifies AA works properly on all Xfermodes, including arithmetic, with both opaque and unknown
57 * src colors.
58 */
59class AAXfermodesGM : public skiagm::GM {
60public:
62
63protected:
69
70 SkString getName() const override { return SkString("aaxfermodes"); }
71
78
79 void onOnceBeforeDraw() override {
81 fLabelFont.setSize(5 * kShapeSize/8);
82 fLabelFont.setSubpixel(true);
83
84 constexpr SkScalar radius = -1.4f * kShapeSize/2;
85 SkPoint pts[4] = {
86 {-radius, 0},
87 {0, -1.33f * radius},
88 {radius, 0},
89 {0, 1.33f * radius}
90 };
91 fOval = SkPathBuilder().moveTo(pts[0])
92 .quadTo(pts[1], pts[2])
93 .quadTo(pts[3], pts[0])
94 .detach();
95
96 fConcave = SkPathBuilder().moveTo(-radius, 0)
97 .quadTo(0, 0, 0, -radius)
98 .quadTo(0, 0, radius, 0)
99 .quadTo(0, 0, 0, radius)
100 .quadTo(0, 0, -radius, 0)
101 .close()
102 .detach();
103 }
104
105 void draw_pass(SkCanvas* canvas, DrawingPass drawingPass) {
106 SkRect clipRect =
107 { -kShapeSize*11/16, -kShapeSize*11/16, kShapeSize*11/16, kShapeSize*11/16 };
108
109 canvas->save();
110 if (kCheckerboard_Pass == drawingPass) {
111 canvas->translate(kMargin, kMargin);
112 }
113 canvas->translate(0, kTitleSpacing);
114
115 for (size_t xfermodeSet = 0; xfermodeSet < 2; xfermodeSet++) {
116 size_t firstMode = ((size_t)SkBlendMode::kLastCoeffMode + 1) * xfermodeSet;
117 canvas->save();
118
119 if (kShape_Pass == drawingPass) {
120 SkTextUtils::DrawString(canvas, "Src Unknown",
122 kSubtitleSpacing / 2 + fLabelFont.getSize() / 3, fLabelFont, SkPaint(),
124 SkTextUtils::DrawString(canvas, "Src Opaque",
126 kPaintSpacing, kSubtitleSpacing / 2 + fLabelFont.getSize() / 3,
127 fLabelFont, SkPaint(), SkTextUtils::kCenter_Align);
128 }
129
131
132 for (size_t m = 0; m <= (size_t)SkBlendMode::kLastCoeffMode; m++) {
133 if (firstMode + m > (size_t)SkBlendMode::kLastMode) {
134 break;
135 }
136 SkBlendMode mode = static_cast<SkBlendMode>(firstMode + m);
137 canvas->save();
138
139 if (kShape_Pass == drawingPass) {
140 this->drawModeName(canvas, mode);
141 }
142 canvas->translate(kLabelSpacing + kShapeSpacing/2, 0);
143
144 for (size_t colorIdx = 0; colorIdx < std::size(kShapeColors); colorIdx++) {
146 this->setupShapePaint(canvas, kShapeColors[colorIdx], mode, &paint);
147 SkASSERT(colorIdx == 0 || 255 == paint.getAlpha());
148 canvas->save();
149
150 for (size_t shapeIdx = 0; shapeIdx <= kLast_Shape; shapeIdx++) {
151 if (kShape_Pass != drawingPass) {
152 canvas->save();
153 canvas->clipRect(clipRect);
154 if (kCheckerboard_Pass == drawingPass) {
155 ToolUtils::draw_checkerboard(canvas, 0xffffffff, 0xffc6c3c6, 10);
156 } else {
157 SkASSERT(kBackground_Pass == drawingPass);
159 }
160 canvas->restore();
161 } else {
162 this->drawShape(canvas, static_cast<Shape>(shapeIdx), paint, mode);
163 }
164 canvas->translate(kShapeTypeSpacing, 0);
165 }
166
167 canvas->restore();
168 canvas->translate(kPaintSpacing, 0);
169 }
170
171 canvas->restore();
172 canvas->translate(0, kShapeSpacing);
173 }
174
175 canvas->restore();
177 }
178
179 canvas->restore();
180 }
181
182 void onDraw(SkCanvas* canvas) override {
184 canvas->saveLayer(nullptr, nullptr);
185
186 canvas->translate(kMargin, kMargin);
188
189 SkFont titleFont(fLabelFont);
190 titleFont.setSize(9 * titleFont.getSize() / 8);
191 titleFont.setEmbolden(true);
192 SkTextUtils::DrawString(canvas, "Porter Duff",
194 kTitleSpacing / 2 + titleFont.getSize() / 3, titleFont, SkPaint(),
196 SkTextUtils::DrawString(canvas, "Advanced",
198 kTitleSpacing / 2 + titleFont.getSize() / 3, titleFont, SkPaint(),
200
201 draw_pass(canvas, kShape_Pass);
202 canvas->restore();
203 }
204
205 void drawModeName(SkCanvas* canvas, SkBlendMode mode) {
206 const char* modeName = SkBlendMode_Name(mode);
207 SkTextUtils::DrawString(canvas, modeName, kLabelSpacing - kShapeSize / 4,
208 fLabelFont.getSize() / 4, fLabelFont, SkPaint(),
210 }
211
213 paint->setColor(color);
214
215 if (mode == SkBlendMode::kPlus) {
216 // Check for overflow, otherwise we might get confusing AA artifacts.
217 int maxSum = std::max(std::max(SkColorGetA(kBGColor) + SkColorGetA(color),
221
222 if (maxSum > 255) {
223 SkPaint dimPaint;
224 dimPaint.setAntiAlias(false);
226 if (255 != paint->getAlpha()) {
227 // Dim the src and dst colors.
228 dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0);
229 paint->setAlpha(255 * paint->getAlpha() / maxSum);
230 } else {
231 // Just clear the dst, we need to preserve the paint's opacity.
232 dimPaint.setARGB(0, 0, 0, 0);
233 }
234 canvas->drawRect({ -kShapeSpacing/2, -kShapeSpacing/2,
236 dimPaint);
237 }
238 }
239 }
240
241 void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkBlendMode mode) {
243 SkPaint shapePaint(paint);
244 shapePaint.setAntiAlias(kSquare_Shape != shape);
245 shapePaint.setBlendMode(mode);
246
247 switch (shape) {
248 case kSquare_Shape:
249 canvas->drawRect({ -kShapeSize/2, -kShapeSize/2, kShapeSize/2, kShapeSize/2 },
250 shapePaint);
251 break;
252
253 case kDiamond_Shape:
254 canvas->save();
255 canvas->rotate(45);
256 canvas->drawRect({ -kShapeSize/2, -kShapeSize/2, kShapeSize/2, kShapeSize/2 },
257 shapePaint);
258 canvas->restore();
259 break;
260
261 case kOval_Shape:
262 canvas->save();
263 canvas->rotate(static_cast<SkScalar>((511 * (int)mode + 257) % 360));
264 canvas->drawPath(fOval, shapePaint);
265 canvas->restore();
266 break;
267
268 case kConcave_Shape:
269 canvas->drawPath(fConcave, shapePaint);
270 break;
271
272 default:
273 SK_ABORT("Invalid shape.");
274 }
275 }
276
277private:
278 SkFont fLabelFont;
279 SkPath fOval;
280 SkPath fConcave;
281
282 using INHERITED = skiagm::GM;
283};
284DEF_GM( return new AAXfermodesGM; )
SkColor4f color
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkASSERT(cond)
Definition SkAssert.h:116
SK_API const char * SkBlendMode_Name(SkBlendMode blendMode)
SkBlendMode
Definition SkBlendMode.h:38
@ kPlus
r = min(s + d, 1)
@ kDstIn
r = d * sa
@ kLastCoeffMode
last porter duff blend mode
@ kLastMode
last valid value
#define SkColorGetR(color)
Definition SkColor.h:65
#define SkColorGetG(color)
Definition SkColor.h:69
uint32_t SkColor
Definition SkColor.h:37
#define SkColorGetA(color)
Definition SkColor.h:61
#define SkColorGetB(color)
Definition SkColor.h:73
constexpr SkColor kShapeColors[2]
Shape
@ kSquare_Shape
@ kOval_Shape
@ kConcave_Shape
@ kLast_Shape
@ kDiamond_Shape
constexpr SkColor kBGColor
@ kXfermodeCount
@ kPaintSpacing
@ kShapeTypeSpacing
@ kShapeSpacing
@ kShapeSize
@ kMargin
@ kTitleSpacing
@ kXfermodeTypeSpacing
@ kSubtitleSpacing
@ kLabelSpacing
Type::kYUV Type::kRGBA() int(0.7 *637)
void onDraw(SkCanvas *canvas) override
void draw_pass(SkCanvas *canvas, DrawingPass drawingPass)
SkISize getISize() override
void onOnceBeforeDraw() override
void drawShape(SkCanvas *canvas, Shape shape, const SkPaint &paint, SkBlendMode mode)
SkString getName() const override
void setupShapePaint(SkCanvas *canvas, SkColor color, SkBlendMode mode, SkPaint *paint)
void drawModeName(SkCanvas *canvas, SkBlendMode mode)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition SkCanvas.cpp:500
void drawRect(const SkRect &rect, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void restore()
Definition SkCanvas.cpp:465
void translate(SkScalar dx, SkScalar dy)
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition SkCanvas.h:1182
void rotate(SkScalar degrees)
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void setSubpixel(bool subpixel)
Definition SkFont.cpp:109
void setTypeface(sk_sp< SkTypeface > tf)
Definition SkFont.cpp:90
SkScalar getSize() const
Definition SkFont.h:217
void setSize(SkScalar textSize)
Definition SkFont.cpp:129
void setEmbolden(bool embolden)
Definition SkFont.cpp:115
void setAntiAlias(bool aa)
Definition SkPaint.h:170
void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkPaint.cpp:134
void setBlendMode(SkBlendMode mode)
Definition SkPaint.cpp:151
SkPathBuilder & close()
SkPathBuilder & moveTo(SkPoint pt)
SkPathBuilder & quadTo(SkPoint pt1, SkPoint pt2)
static void DrawString(SkCanvas *canvas, const char text[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint, Align align=kLeft_Align)
Definition SkTextUtils.h:34
const Paint & paint
float SkScalar
Definition extension.cpp:12
#define DEF_GM(CODE)
Definition gm.h:40
sk_sp< SkTypeface > DefaultPortableTypeface()
void draw_checkerboard(SkCanvas *canvas, SkColor c1, SkColor c2, int size)
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20