1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h" // IWYU pragma: keep
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
27*c8dee2aaSAndroid Build Coastguard Worker #endif
28*c8dee2aaSAndroid Build Coastguard Worker
29*c8dee2aaSAndroid Build Coastguard Worker #include <cstdarg>
30*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker using namespace skiagm;
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker static void draw_failure_message(SkCanvas* canvas, const char format[], ...) SK_PRINTF_LIKE(2, 3);
35*c8dee2aaSAndroid Build Coastguard Worker
draw_failure_message(SkCanvas * canvas,const char format[],...)36*c8dee2aaSAndroid Build Coastguard Worker static void draw_failure_message(SkCanvas* canvas, const char format[], ...) {
37*c8dee2aaSAndroid Build Coastguard Worker SkString failureMsg;
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker va_list argp;
40*c8dee2aaSAndroid Build Coastguard Worker va_start(argp, format);
41*c8dee2aaSAndroid Build Coastguard Worker failureMsg.appendVAList(format, argp);
42*c8dee2aaSAndroid Build Coastguard Worker va_end(argp);
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar kOffset = 5.0f;
45*c8dee2aaSAndroid Build Coastguard Worker canvas->drawColor(SkColorSetRGB(200,0,0));
46*c8dee2aaSAndroid Build Coastguard Worker SkFont font = ToolUtils::DefaultPortableFont();
47*c8dee2aaSAndroid Build Coastguard Worker SkRect bounds;
48*c8dee2aaSAndroid Build Coastguard Worker font.measureText(failureMsg.c_str(), failureMsg.size(), SkTextEncoding::kUTF8, &bounds);
49*c8dee2aaSAndroid Build Coastguard Worker SkPaint textPaint(SkColors::kWhite);
50*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(failureMsg, kOffset, bounds.height() + kOffset, font, textPaint);
51*c8dee2aaSAndroid Build Coastguard Worker }
52*c8dee2aaSAndroid Build Coastguard Worker
draw_gpu_only_message(SkCanvas * canvas)53*c8dee2aaSAndroid Build Coastguard Worker static void draw_gpu_only_message(SkCanvas* canvas) {
54*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bmp;
55*c8dee2aaSAndroid Build Coastguard Worker bmp.allocN32Pixels(128, 64);
56*c8dee2aaSAndroid Build Coastguard Worker SkCanvas bmpCanvas(bmp);
57*c8dee2aaSAndroid Build Coastguard Worker bmpCanvas.drawColor(SK_ColorWHITE);
58*c8dee2aaSAndroid Build Coastguard Worker SkFont font(ToolUtils::DefaultPortableTypeface(), 20);
59*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint(SkColors::kRed);
60*c8dee2aaSAndroid Build Coastguard Worker bmpCanvas.drawString("GPU Only", 20, 40, font, paint);
61*c8dee2aaSAndroid Build Coastguard Worker SkMatrix localM;
62*c8dee2aaSAndroid Build Coastguard Worker localM.setRotate(35.f);
63*c8dee2aaSAndroid Build Coastguard Worker localM.postTranslate(10.f, 0.f);
64*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(bmp.makeShader(SkTileMode::kMirror, SkTileMode::kMirror,
65*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(SkFilterMode::kLinear,
66*c8dee2aaSAndroid Build Coastguard Worker SkMipmapMode::kNearest),
67*c8dee2aaSAndroid Build Coastguard Worker localM));
68*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
69*c8dee2aaSAndroid Build Coastguard Worker }
70*c8dee2aaSAndroid Build Coastguard Worker
handle_gm_failure(SkCanvas * canvas,DrawResult result,const SkString & errorMsg)71*c8dee2aaSAndroid Build Coastguard Worker static void handle_gm_failure(SkCanvas* canvas, DrawResult result, const SkString& errorMsg) {
72*c8dee2aaSAndroid Build Coastguard Worker if (DrawResult::kFail == result) {
73*c8dee2aaSAndroid Build Coastguard Worker draw_failure_message(canvas, "DRAW FAILED: %s", errorMsg.c_str());
74*c8dee2aaSAndroid Build Coastguard Worker } else if (SkString(GM::kErrorMsg_DrawSkippedGpuOnly) == errorMsg) {
75*c8dee2aaSAndroid Build Coastguard Worker draw_gpu_only_message(canvas);
76*c8dee2aaSAndroid Build Coastguard Worker } else {
77*c8dee2aaSAndroid Build Coastguard Worker draw_failure_message(canvas, "DRAW SKIPPED: %s", errorMsg.c_str());
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
GM(SkColor bgColor)81*c8dee2aaSAndroid Build Coastguard Worker GM::GM(SkColor bgColor) {
82*c8dee2aaSAndroid Build Coastguard Worker fMode = kGM_Mode;
83*c8dee2aaSAndroid Build Coastguard Worker fBGColor = bgColor;
84*c8dee2aaSAndroid Build Coastguard Worker }
85*c8dee2aaSAndroid Build Coastguard Worker
~GM()86*c8dee2aaSAndroid Build Coastguard Worker GM::~GM() {}
87*c8dee2aaSAndroid Build Coastguard Worker
gpuSetup(SkCanvas * canvas,SkString * errorMsg,GraphiteTestContext * graphiteTestContext)88*c8dee2aaSAndroid Build Coastguard Worker DrawResult GM::gpuSetup(SkCanvas* canvas,
89*c8dee2aaSAndroid Build Coastguard Worker SkString* errorMsg,
90*c8dee2aaSAndroid Build Coastguard Worker GraphiteTestContext* graphiteTestContext) {
91*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT1("GM", TRACE_FUNC, "name", TRACE_STR_COPY(this->getName().c_str()));
92*c8dee2aaSAndroid Build Coastguard Worker if (!fGpuSetup) {
93*c8dee2aaSAndroid Build Coastguard Worker // When drawn in viewer, gpuSetup will be called multiple times with the same
94*c8dee2aaSAndroid Build Coastguard Worker // GrContext or graphite::Context.
95*c8dee2aaSAndroid Build Coastguard Worker fGpuSetup = true;
96*c8dee2aaSAndroid Build Coastguard Worker fGpuSetupResult = this->onGpuSetup(canvas, errorMsg, graphiteTestContext);
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker if (fGpuSetupResult == DrawResult::kOk) {
99*c8dee2aaSAndroid Build Coastguard Worker fGraphiteTestContext = graphiteTestContext;
100*c8dee2aaSAndroid Build Coastguard Worker } else {
101*c8dee2aaSAndroid Build Coastguard Worker handle_gm_failure(canvas, fGpuSetupResult, *errorMsg);
102*c8dee2aaSAndroid Build Coastguard Worker }
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker return fGpuSetupResult;
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
gpuTeardown()107*c8dee2aaSAndroid Build Coastguard Worker void GM::gpuTeardown() {
108*c8dee2aaSAndroid Build Coastguard Worker this->onGpuTeardown();
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker // After 'gpuTeardown' a GM can be reused with a different GrContext or graphite::Context. Reset
111*c8dee2aaSAndroid Build Coastguard Worker // the flag so 'onGpuSetup' will be called.
112*c8dee2aaSAndroid Build Coastguard Worker fGpuSetup = false;
113*c8dee2aaSAndroid Build Coastguard Worker fGraphiteTestContext = nullptr;
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker
draw(SkCanvas * canvas,SkString * errorMsg)116*c8dee2aaSAndroid Build Coastguard Worker DrawResult GM::draw(SkCanvas* canvas, SkString* errorMsg) {
117*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT1("GM", TRACE_FUNC, "name", TRACE_STR_COPY(this->getName().c_str()));
118*c8dee2aaSAndroid Build Coastguard Worker this->drawBackground(canvas);
119*c8dee2aaSAndroid Build Coastguard Worker return this->drawContent(canvas, errorMsg);
120*c8dee2aaSAndroid Build Coastguard Worker }
121*c8dee2aaSAndroid Build Coastguard Worker
drawContent(SkCanvas * canvas,SkString * errorMsg)122*c8dee2aaSAndroid Build Coastguard Worker DrawResult GM::drawContent(SkCanvas* canvas, SkString* errorMsg) {
123*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("GM", TRACE_FUNC);
124*c8dee2aaSAndroid Build Coastguard Worker this->onceBeforeDraw();
125*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
126*c8dee2aaSAndroid Build Coastguard Worker DrawResult drawResult = this->onDraw(canvas, errorMsg);
127*c8dee2aaSAndroid Build Coastguard Worker if (DrawResult::kOk != drawResult) {
128*c8dee2aaSAndroid Build Coastguard Worker handle_gm_failure(canvas, drawResult, *errorMsg);
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker return drawResult;
131*c8dee2aaSAndroid Build Coastguard Worker }
132*c8dee2aaSAndroid Build Coastguard Worker
drawBackground(SkCanvas * canvas)133*c8dee2aaSAndroid Build Coastguard Worker void GM::drawBackground(SkCanvas* canvas) {
134*c8dee2aaSAndroid Build Coastguard Worker TRACE_EVENT0("GM", TRACE_FUNC);
135*c8dee2aaSAndroid Build Coastguard Worker this->onceBeforeDraw();
136*c8dee2aaSAndroid Build Coastguard Worker canvas->drawColor(fBGColor, SkBlendMode::kSrc);
137*c8dee2aaSAndroid Build Coastguard Worker }
138*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)139*c8dee2aaSAndroid Build Coastguard Worker DrawResult GM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
140*c8dee2aaSAndroid Build Coastguard Worker this->onDraw(canvas);
141*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
142*c8dee2aaSAndroid Build Coastguard Worker }
onDraw(SkCanvas *)143*c8dee2aaSAndroid Build Coastguard Worker void GM::onDraw(SkCanvas*) { SK_ABORT("Not implemented."); }
144*c8dee2aaSAndroid Build Coastguard Worker
getISize()145*c8dee2aaSAndroid Build Coastguard Worker SkISize SimpleGM::getISize() { return fSize; }
getName() const146*c8dee2aaSAndroid Build Coastguard Worker SkString SimpleGM::getName() const { return fName; }
onDraw(SkCanvas * canvas,SkString * errorMsg)147*c8dee2aaSAndroid Build Coastguard Worker DrawResult SimpleGM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
148*c8dee2aaSAndroid Build Coastguard Worker return fDrawProc(canvas, errorMsg);
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
getISize()152*c8dee2aaSAndroid Build Coastguard Worker SkISize SimpleGpuGM::getISize() { return fSize; }
getName() const153*c8dee2aaSAndroid Build Coastguard Worker SkString SimpleGpuGM::getName() const { return fName; }
onDraw(GrRecordingContext * rContext,SkCanvas * canvas,SkString * errorMsg)154*c8dee2aaSAndroid Build Coastguard Worker DrawResult SimpleGpuGM::onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) {
155*c8dee2aaSAndroid Build Coastguard Worker return fDrawProc(rContext, canvas, errorMsg);
156*c8dee2aaSAndroid Build Coastguard Worker }
157*c8dee2aaSAndroid Build Coastguard Worker #endif
158*c8dee2aaSAndroid Build Coastguard Worker
setBGColor(SkColor color)159*c8dee2aaSAndroid Build Coastguard Worker void GM::setBGColor(SkColor color) {
160*c8dee2aaSAndroid Build Coastguard Worker fBGColor = color;
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker
animate(double nanos)163*c8dee2aaSAndroid Build Coastguard Worker bool GM::animate(double nanos) { return this->onAnimate(nanos); }
164*c8dee2aaSAndroid Build Coastguard Worker
runAsBench() const165*c8dee2aaSAndroid Build Coastguard Worker bool GM::runAsBench() const { return false; }
166*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()167*c8dee2aaSAndroid Build Coastguard Worker void GM::onOnceBeforeDraw() {}
168*c8dee2aaSAndroid Build Coastguard Worker
onAnimate(double)169*c8dee2aaSAndroid Build Coastguard Worker bool GM::onAnimate(double /*nanos*/) { return false; }
170*c8dee2aaSAndroid Build Coastguard Worker
onChar(SkUnichar uni)171*c8dee2aaSAndroid Build Coastguard Worker bool GM::onChar(SkUnichar uni) { return false; }
172*c8dee2aaSAndroid Build Coastguard Worker
onGetControls(SkMetaData *)173*c8dee2aaSAndroid Build Coastguard Worker bool GM::onGetControls(SkMetaData*) { return false; }
174*c8dee2aaSAndroid Build Coastguard Worker
onSetControls(const SkMetaData &)175*c8dee2aaSAndroid Build Coastguard Worker void GM::onSetControls(const SkMetaData&) {}
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////////////////////
178*c8dee2aaSAndroid Build Coastguard Worker
drawSizeBounds(SkCanvas * canvas,SkColor color)179*c8dee2aaSAndroid Build Coastguard Worker void GM::drawSizeBounds(SkCanvas* canvas, SkColor color) {
180*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::Make(this->getISize()), SkPaint(SkColor4f::FromColor(color)));
181*c8dee2aaSAndroid Build Coastguard Worker }
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker // need to explicitly declare this, or we get some weird infinite loop llist
184*c8dee2aaSAndroid Build Coastguard Worker template GMRegistry* GMRegistry::gHead;
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GANESH)
onDraw(GrRecordingContext * rContext,SkCanvas * canvas,SkString * errorMsg)187*c8dee2aaSAndroid Build Coastguard Worker DrawResult GpuGM::onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) {
188*c8dee2aaSAndroid Build Coastguard Worker this->onDraw(rContext, canvas);
189*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
190*c8dee2aaSAndroid Build Coastguard Worker }
onDraw(GrRecordingContext *,SkCanvas *)191*c8dee2aaSAndroid Build Coastguard Worker void GpuGM::onDraw(GrRecordingContext*, SkCanvas*) {
192*c8dee2aaSAndroid Build Coastguard Worker SK_ABORT("Not implemented.");
193*c8dee2aaSAndroid Build Coastguard Worker }
194*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas,SkString * errorMsg)195*c8dee2aaSAndroid Build Coastguard Worker DrawResult GpuGM::onDraw(SkCanvas* canvas, SkString* errorMsg) {
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker auto rContext = canvas->recordingContext();
198*c8dee2aaSAndroid Build Coastguard Worker if (!rContext) {
199*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
200*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker if (rContext->abandoned()) {
203*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "GrContext abandoned.";
204*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kSkip;
205*c8dee2aaSAndroid Build Coastguard Worker }
206*c8dee2aaSAndroid Build Coastguard Worker return this->onDraw(rContext, canvas, errorMsg);
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker #endif
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker template <typename Fn>
mark(SkCanvas * canvas,SkScalar x,SkScalar y,Fn && fn)211*c8dee2aaSAndroid Build Coastguard Worker static void mark(SkCanvas* canvas, SkScalar x, SkScalar y, Fn&& fn) {
212*c8dee2aaSAndroid Build Coastguard Worker SkPaint alpha;
213*c8dee2aaSAndroid Build Coastguard Worker alpha.setAlpha(0x50);
214*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(nullptr, &alpha);
215*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(x,y);
216*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(2,2);
217*c8dee2aaSAndroid Build Coastguard Worker fn();
218*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
MarkGMGood(SkCanvas * canvas,SkScalar x,SkScalar y)221*c8dee2aaSAndroid Build Coastguard Worker void MarkGMGood(SkCanvas* canvas, SkScalar x, SkScalar y) {
222*c8dee2aaSAndroid Build Coastguard Worker mark(canvas, x,y, [&]{
223*c8dee2aaSAndroid Build Coastguard Worker // A green circle.
224*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(0, 0, 12, SkPaint(SkColor4f::FromColor(SkColorSetRGB(27, 158, 119))));
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker // Cut out a check mark.
227*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint(SkColors::kTransparent);
228*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
229*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(2);
230*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
231*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(-6, 0,
232*c8dee2aaSAndroid Build Coastguard Worker -1, 5, paint);
233*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(-1, +5,
234*c8dee2aaSAndroid Build Coastguard Worker +7, -5, paint);
235*c8dee2aaSAndroid Build Coastguard Worker });
236*c8dee2aaSAndroid Build Coastguard Worker }
237*c8dee2aaSAndroid Build Coastguard Worker
MarkGMBad(SkCanvas * canvas,SkScalar x,SkScalar y)238*c8dee2aaSAndroid Build Coastguard Worker void MarkGMBad(SkCanvas* canvas, SkScalar x, SkScalar y) {
239*c8dee2aaSAndroid Build Coastguard Worker mark(canvas, x,y, [&] {
240*c8dee2aaSAndroid Build Coastguard Worker // A red circle.
241*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(0,0, 12, SkPaint(SkColor4f::FromColor(SkColorSetRGB(231, 41, 138))));
242*c8dee2aaSAndroid Build Coastguard Worker
243*c8dee2aaSAndroid Build Coastguard Worker // Cut out an 'X'.
244*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint(SkColors::kTransparent);
245*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kSrc);
246*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(2);
247*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
248*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(-5,-5,
249*c8dee2aaSAndroid Build Coastguard Worker +5,+5, paint);
250*c8dee2aaSAndroid Build Coastguard Worker canvas->drawLine(+5,-5,
251*c8dee2aaSAndroid Build Coastguard Worker -5,+5, paint);
252*c8dee2aaSAndroid Build Coastguard Worker });
253*c8dee2aaSAndroid Build Coastguard Worker }
254*c8dee2aaSAndroid Build Coastguard Worker
255*c8dee2aaSAndroid Build Coastguard Worker namespace skiagm {
Register(skiagm::GM * gm)256*c8dee2aaSAndroid Build Coastguard Worker void Register(skiagm::GM* gm) {
257*c8dee2aaSAndroid Build Coastguard Worker // The skiagm::GMRegistry class is a subclass of sk_tools::Registry. Instances of
258*c8dee2aaSAndroid Build Coastguard Worker // sk_tools::Registry form a linked list (there is one such list for each subclass), where each
259*c8dee2aaSAndroid Build Coastguard Worker // instance holds a value and a pointer to the next sk_tools::Registry instance. The head of
260*c8dee2aaSAndroid Build Coastguard Worker // this linked list is stored in a global variable. The sk_tools::Registry constructor
261*c8dee2aaSAndroid Build Coastguard Worker // automatically pushes a new instance to the head of said linked list. Therefore, in order to
262*c8dee2aaSAndroid Build Coastguard Worker // register a value in the GM registry, it suffices to just instantiate skiagm::GMRegistry with
263*c8dee2aaSAndroid Build Coastguard Worker // the value we wish to register.
264*c8dee2aaSAndroid Build Coastguard Worker new skiagm::GMRegistry([=]() { return std::unique_ptr<skiagm::GM>(gm); });
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker } // namespace skiagm
267