Flutter Engine
The Flutter Engine
ThinAASlide.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2019 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
10#include "include/core/SkFont.h"
12#include "include/core/SkPath.h"
16#include "tools/viewer/Slide.h"
17
18using namespace skia_private;
19
20namespace skiagm {
21
23public:
24 inline static constexpr SkScalar kTileWidth = 20.f;
25 inline static constexpr SkScalar kTileHeight = 20.f;
26
27 // Draw the shape, limited to kTileWidth x kTileHeight. It must apply the local subpixel (tx,
28 // ty) translation and rotation by angle. Prior to these transform adjustments, the SkCanvas
29 // will only have pixel aligned translations (these are separated to make super-sampling
30 // renderers easier).
31 virtual void draw(SkCanvas* canvas, SkPaint* paint,
32 SkScalar tx, SkScalar ty, SkScalar angle) = 0;
33
34 virtual SkString name() = 0;
35
37
38 void applyLocalTransform(SkCanvas* canvas, SkScalar tx, SkScalar ty, SkScalar angle) {
39 canvas->translate(tx, ty);
40 canvas->rotate(angle, kTileWidth / 2.f, kTileHeight / 2.f);
41 }
42};
43
45public:
48 }
49
50 SkString name() override { return SkString("rect"); }
51
53 // Not really available but can't return nullptr
54 return Make();
55 }
56
57 void draw(SkCanvas* canvas, SkPaint* paint, SkScalar tx, SkScalar ty, SkScalar angle) override {
58 SkScalar width = paint->getStrokeWidth();
59 paint->setStyle(SkPaint::kFill_Style);
60
61 this->applyLocalTransform(canvas, tx, ty, angle);
62 canvas->drawRect(SkRect::MakeLTRB(kTileWidth / 2.f - width / 2.f, 2.f,
63 kTileWidth / 2.f + width / 2.f, kTileHeight - 2.f),
64 *paint);
65 }
66
67private:
68 RectRenderer() {}
69};
70
72public:
73 static sk_sp<ShapeRenderer> MakeLine(bool hairline = false) {
74 return MakeCurve(0.f, hairline);
75 }
76
77 static sk_sp<ShapeRenderer> MakeLines(SkScalar depth, bool hairline = false) {
78 return MakeCurve(-depth, hairline);
79 }
80
81 static sk_sp<ShapeRenderer> MakeCurve(SkScalar depth, bool hairline = false) {
82 return sk_sp<ShapeRenderer>(new PathRenderer(depth, hairline));
83 }
84
85 SkString name() override {
87 if (fHairline) {
88 name.append("hairline");
89 if (fDepth > 0.f) {
90 name.appendf("-curve-%.2f", fDepth);
91 }
92 } else if (fDepth > 0.f) {
93 name.appendf("curve-%.2f", fDepth);
94 } else if (fDepth < 0.f) {
95 name.appendf("line-%.2f", -fDepth);
96 } else {
97 name.append("line");
98 }
99
100 return name;
101 }
102
104 return sk_sp<ShapeRenderer>(new PathRenderer(fDepth, true));
105 }
106
107 void draw(SkCanvas* canvas, SkPaint* paint, SkScalar tx, SkScalar ty, SkScalar angle) override {
108 SkPath path;
109 path.moveTo(kTileWidth / 2.f, 2.f);
110
111 if (fDepth > 0.f) {
112 path.quadTo(kTileWidth / 2.f + fDepth, kTileHeight / 2.f,
113 kTileWidth / 2.f, kTileHeight - 2.f);
114 } else {
115 if (fDepth < 0.f) {
116 path.lineTo(kTileWidth / 2.f + fDepth, kTileHeight / 2.f);
117 }
118 path.lineTo(kTileWidth / 2.f, kTileHeight - 2.f);
119 }
120
121 if (fHairline) {
122 // Fake thinner hairlines by making it transparent, conflating coverage and alpha
123 SkColor4f color = paint->getColor4f();
124 SkScalar width = paint->getStrokeWidth();
125 if (width > 1.f) {
126 // Can't emulate width larger than a pixel
127 return;
128 }
129 paint->setColor4f({color.fR, color.fG, color.fB, width}, nullptr);
130 paint->setStrokeWidth(0.f);
131 }
132
133 // Adding round caps forces Ganesh to use the path renderer for lines instead of converting
134 // them to rectangles (which are already explicitly tested). However, when not curved, the
135 // GrStyledShape will still find a way to turn it into a rrect draw so it doesn't hit the
136 // path renderer in that condition.
137 paint->setStrokeCap(SkPaint::kRound_Cap);
138 paint->setStrokeJoin(SkPaint::kMiter_Join);
139 paint->setStyle(SkPaint::kStroke_Style);
140
141 this->applyLocalTransform(canvas, tx, ty, angle);
142 canvas->drawPath(path, *paint);
143 }
144
145private:
146 SkScalar fDepth; // 0.f to make a line, otherwise outset of curve from end points
147 bool fHairline;
148
149 PathRenderer(SkScalar depth, bool hairline)
150 : fDepth(depth)
151 , fHairline(hairline) {}
152};
153
155public:
156 ~OffscreenShapeRenderer() override = default;
157
159 bool forceRaster = false) {
160 SkASSERT(supersample > 0);
162 supersample, forceRaster));
163 }
164
165 SkString name() override {
166 SkString name = fRenderer->name();
167 if (fSupersampleFactor != 1) {
168 name.prependf("%dx-", fSupersampleFactor * fSupersampleFactor);
169 }
170 return name;
171 }
172
174 return Make(fRenderer->toHairline(), fSupersampleFactor, fForceRasterBackend);
175 }
176
177 void draw(SkCanvas* canvas, SkPaint* paint, SkScalar tx, SkScalar ty, SkScalar angle) override {
178 // Subpixel translation+angle are applied in the offscreen buffer
179 this->prepareBuffer(canvas, paint, tx, ty, angle);
180 this->redraw(canvas);
181 }
182
183 // Exposed so that it's easy to fill the offscreen buffer, then draw zooms/filters of it before
184 // drawing the original scale back into the canvas.
186 auto info = SkImageInfo::Make(fSupersampleFactor * kTileWidth,
187 fSupersampleFactor * kTileHeight,
189 auto surface = fForceRasterBackend ? SkSurfaces::Raster(info) : canvas->makeSurface(info);
190
191 surface->getCanvas()->save();
192 // Make fully transparent so it is easy to determine pixels that are touched by partial cov.
193 surface->getCanvas()->clear(SK_ColorTRANSPARENT);
194 // Set up scaling to fit supersampling amount
195 surface->getCanvas()->scale(fSupersampleFactor, fSupersampleFactor);
196 fRenderer->draw(surface->getCanvas(), paint, tx, ty, angle);
197 surface->getCanvas()->restore();
198
199 // Save image so it can be drawn zoomed in or to visualize touched pixels; only valid until
200 // the next call to draw()
201 fLastRendered = surface->makeImageSnapshot();
202 }
203
204 void redraw(SkCanvas* canvas, SkScalar scale = 1.f, bool debugMode = false) {
205 SkASSERT(fLastRendered);
206 // Use medium quality filter to get mipmaps when drawing smaller, or use nearest filtering
207 // when upscaling
208 SkPaint blit;
209 if (debugMode) {
210 // Makes anything that's > 1/255 alpha fully opaque and sets color to medium green.
211 static constexpr float kFilter[] = {
212 0.f, 0.f, 0.f, 0.f, 16.f/255,
213 0.f, 0.f, 0.f, 0.f, 200.f/255,
214 0.f, 0.f, 0.f, 0.f, 16.f/255,
215 0.f, 0.f, 0.f, 255.f, 0.f
216 };
217
219 }
220
224
225 canvas->scale(scale, scale);
226 canvas->drawImageRect(fLastRendered.get(),
230 }
231
232private:
233 bool fForceRasterBackend;
234 sk_sp<SkImage> fLastRendered;
235 sk_sp<ShapeRenderer> fRenderer;
236 int fSupersampleFactor;
237
238 OffscreenShapeRenderer(sk_sp<ShapeRenderer> renderer, int supersample, bool forceRaster)
239 : fForceRasterBackend(forceRaster)
240 , fLastRendered(nullptr)
241 , fRenderer(std::move(renderer))
242 , fSupersampleFactor(supersample) { }
243};
244
245class ThinAASlide : public Slide {
246public:
247 ThinAASlide() { fName = "Thin-AA"; }
248
249 void load(SkScalar w, SkScalar h) override {
250 // Setup all base renderers
251 fShapes.push_back(RectRenderer::Make());
252 fShapes.push_back(PathRenderer::MakeLine());
253 fShapes.push_back(PathRenderer::MakeLines(4.f)); // 2 segments
254 fShapes.push_back(PathRenderer::MakeCurve(2.f)); // Shallow curve
255 fShapes.push_back(PathRenderer::MakeCurve(8.f)); // Deep curve
256
257 for (int i = 0; i < fShapes.size(); ++i) {
258 fNative.push_back(OffscreenShapeRenderer::Make(fShapes[i], 1));
259 fRaster.push_back(OffscreenShapeRenderer::Make(fShapes[i], 1, /* raster */ true));
260 fSS4.push_back(OffscreenShapeRenderer::Make(fShapes[i], 4)); // 4x4 -> 16 samples
261 fSS16.push_back(OffscreenShapeRenderer::Make(fShapes[i], 8)); // 8x8 -> 64 samples
262
263 fHairline.push_back(OffscreenShapeRenderer::Make(fRaster[i]->toHairline(), 1));
264 }
265
266 // Start it at something subpixel
267 fStrokeWidth = 0.5f;
268
269 fSubpixelX = 0.f;
270 fSubpixelY = 0.f;
271 fAngle = 0.f;
272
273 fCurrentStage = AnimStage::kMoveLeft;
274 fLastFrameTime = -1.f;
275
276 // Don't animate in the beginning
277 fAnimTranslate = false;
278 fAnimRotate = false;
279 }
280
281 void draw(SkCanvas* canvas) override {
282 canvas->clear(0xFFFFFFFF);
283 // Move away from screen edge and add instructions
286 canvas->translate(60.f, 20.f);
287 canvas->drawString("Each row features a rendering command under different AA strategies. "
288 "Native refers to the current backend of the viewer, e.g. OpenGL.",
289 0, 0, font, text);
290
291 canvas->drawString(SkStringPrintf("Stroke width: %.2f ('-' to decrease, '=' to increase)",
292 fStrokeWidth), 0, 24, font, text);
293 canvas->drawString(SkStringPrintf("Rotation: %.3f ('r' to animate, 'y' sets to 90, 'u' sets"
294 " to 0, 'space' adds 15)", fAngle), 0, 36, font, text);
295 canvas->drawString(SkStringPrintf("Translation: %.3f, %.3f ('t' to animate)",
296 fSubpixelX, fSubpixelY), 0, 48, font, text);
297
298 canvas->translate(0.f, 100.f);
299
300 // Draw with surface matching current viewer surface type
301 this->drawShapes(canvas, "Native", 0, fNative);
302
303 // Draw with forced raster backend so it's easy to compare side-by-side
304 this->drawShapes(canvas, "Raster", 1, fRaster);
305
306 // Draw paths as hairlines + alpha hack
307 this->drawShapes(canvas, "Hairline", 2, fHairline);
308
309 // Draw at 4x supersampling in bottom left
310 this->drawShapes(canvas, "SSx16", 3, fSS4);
311
312 // And lastly 16x supersampling in bottom right
313 this->drawShapes(canvas, "SSx64", 4, fSS16);
314 }
315
316 bool animate(double nanos) override {
317 SkScalar t = 1e-9 * nanos;
318 SkScalar dt = fLastFrameTime < 0.f ? 0.f : t - fLastFrameTime;
319 fLastFrameTime = t;
320
321 if (!fAnimRotate && !fAnimTranslate) {
322 // Keep returning true so that the last frame time is tracked
323 fLastFrameTime = -1.f;
324 return false;
325 }
326
327 switch(fCurrentStage) {
328 case AnimStage::kMoveLeft:
329 fSubpixelX += 2.f * dt;
330 if (fSubpixelX >= 1.f) {
331 fSubpixelX = 1.f;
332 fCurrentStage = AnimStage::kMoveDown;
333 }
334 break;
335 case AnimStage::kMoveDown:
336 fSubpixelY += 2.f * dt;
337 if (fSubpixelY >= 1.f) {
338 fSubpixelY = 1.f;
339 fCurrentStage = AnimStage::kMoveRight;
340 }
341 break;
342 case AnimStage::kMoveRight:
343 fSubpixelX -= 2.f * dt;
344 if (fSubpixelX <= -1.f) {
345 fSubpixelX = -1.f;
346 fCurrentStage = AnimStage::kMoveUp;
347 }
348 break;
349 case AnimStage::kMoveUp:
350 fSubpixelY -= 2.f * dt;
351 if (fSubpixelY <= -1.f) {
352 fSubpixelY = -1.f;
353 fCurrentStage = fAnimRotate ? AnimStage::kRotate : AnimStage::kMoveLeft;
354 }
355 break;
356 case AnimStage::kRotate: {
357 SkScalar newAngle = fAngle + dt * 15.f;
358 bool completed = SkScalarMod(newAngle, 15.f) < SkScalarMod(fAngle, 15.f);
359 fAngle = SkScalarMod(newAngle, 360.f);
360 if (completed) {
361 // Make sure we're on a 15 degree boundary
362 fAngle = 15.f * SkScalarRoundToScalar(fAngle / 15.f);
363 if (fAnimTranslate) {
364 fCurrentStage = this->getTranslationStage();
365 }
366 }
367 } break;
368 }
369
370 return true;
371 }
372
373 bool onChar(SkUnichar key) override {
374 switch(key) {
375 case 't':
376 // Toggle translation animation.
377 fAnimTranslate = !fAnimTranslate;
378 if (!fAnimTranslate && fAnimRotate && fCurrentStage != AnimStage::kRotate) {
379 // Turned off an active translation so go to rotating
380 fCurrentStage = AnimStage::kRotate;
381 } else if (fAnimTranslate && !fAnimRotate &&
382 fCurrentStage == AnimStage::kRotate) {
383 // Turned on translation, rotation had been paused too, so reset the stage
384 fCurrentStage = this->getTranslationStage();
385 }
386 return true;
387 case 'r':
388 // Toggle rotation animation.
389 fAnimRotate = !fAnimRotate;
390 if (!fAnimRotate && fAnimTranslate && fCurrentStage == AnimStage::kRotate) {
391 // Turned off an active rotation so go back to translation
392 fCurrentStage = this->getTranslationStage();
393 } else if (fAnimRotate && !fAnimTranslate &&
394 fCurrentStage != AnimStage::kRotate) {
395 // Turned on rotation, translation had been paused too, so reset to rotate
396 fCurrentStage = AnimStage::kRotate;
397 }
398 return true;
399 case 'u': fAngle = 0.f; return true;
400 case 'y': fAngle = 90.f; return true;
401 case ' ': fAngle = SkScalarMod(fAngle + 15.f, 360.f); return true;
402 case '-': fStrokeWidth = std::max(0.1f, fStrokeWidth - 0.05f); return true;
403 case '=': fStrokeWidth = std::min(1.f, fStrokeWidth + 0.05f); return true;
404 }
405 return false;
406 }
407
408private:
409 // Base renderers that get wrapped on the offscreen renderers so that they can be transformed
410 // for visualization, or supersampled.
412
418
419 SkScalar fStrokeWidth;
420
421 // Animated properties to stress the AA algorithms
422 enum class AnimStage {
423 kMoveRight, kMoveDown, kMoveLeft, kMoveUp, kRotate
424 } fCurrentStage;
425 SkScalar fLastFrameTime;
426 bool fAnimRotate;
427 bool fAnimTranslate;
428
429 // Current frame's animation state
430 SkScalar fSubpixelX;
431 SkScalar fSubpixelY;
432 SkScalar fAngle;
433
434 AnimStage getTranslationStage() {
435 // For paused translations (i.e. fAnimTranslate toggled while translating), the current
436 // stage moves to kRotate, but when restarting the translation animation, we want to
437 // go back to where we were without losing any progress.
438 if (fSubpixelX > -1.f) {
439 if (fSubpixelX >= 1.f) {
440 // Can only be moving down on right edge, given our transition states
441 return AnimStage::kMoveDown;
442 } else if (fSubpixelY > 0.f) {
443 // Can only be moving right along top edge
444 return AnimStage::kMoveRight;
445 } else {
446 // Must be moving left along bottom edge
447 return AnimStage::kMoveLeft;
448 }
449 } else {
450 // Moving up along the left edge, or is at the very top so start moving left
451 return fSubpixelY > -1.f ? AnimStage::kMoveUp : AnimStage::kMoveLeft;
452 }
453 }
454
455 void drawShapes(SkCanvas* canvas, const char* name, int gridX,
457 SkAutoCanvasRestore autoRestore(canvas, /* save */ true);
458
459 for (int i = 0; i < shapes.size(); ++i) {
460 this->drawShape(canvas, name, gridX, shapes[i].get(), i == 0);
461 // drawShape positions the canvas properly for the next iteration
462 }
463 }
464
465 void drawShape(SkCanvas* canvas, const char* name, int gridX,
466 OffscreenShapeRenderer* shape, bool drawNameLabels) {
467 static constexpr SkScalar kZoomGridWidth = 8 * ShapeRenderer::kTileWidth + 8.f;
468 static constexpr SkRect kTile = SkRect::MakeWH(ShapeRenderer::kTileWidth,
470 static constexpr SkRect kZoomTile = SkRect::MakeWH(8 * ShapeRenderer::kTileWidth,
472
473 // Labeling per shape and detailed labeling that isn't per-stroke
474 canvas->save();
477
478 if (gridX == 0) {
479 SkScalar centering = shape->name().size() * 4.f; // ad-hoc
480
481 canvas->save();
482 canvas->translate(-10.f, 4 * ShapeRenderer::kTileHeight + centering);
483 canvas->rotate(-90.f);
484 canvas->drawString(shape->name(), 0.f, 0.f, font, text);
485 canvas->restore();
486 }
487 if (drawNameLabels) {
488 canvas->drawString(name, gridX * kZoomGridWidth, -10.f, font, text);
489 }
490 canvas->restore();
491
492 // Paints for outlines and actual shapes
493 SkPaint outline;
495 SkPaint clear;
496 clear.setColor(SK_ColorWHITE);
497
499 paint.setAntiAlias(true);
500 paint.setStrokeWidth(fStrokeWidth);
501
502 // Generate a saved image of the correct stroke width, but don't put it into the canvas
503 // yet since we want to draw the "original" size on top of the zoomed in version
504 shape->prepareBuffer(canvas, &paint, fSubpixelX, fSubpixelY, fAngle);
505
506 // Draw it at 8X zoom
507 SkScalar x = gridX * kZoomGridWidth;
508
509 canvas->save();
510 canvas->translate(x, 0.f);
511 canvas->drawRect(kZoomTile, outline);
512 shape->redraw(canvas, 8.0f);
513 canvas->restore();
514
515 // Draw the original
516 canvas->save();
517 canvas->translate(x + 4.f, 4.f);
518 canvas->drawRect(kTile, clear);
519 canvas->drawRect(kTile, outline);
520 shape->redraw(canvas, 1.f);
521 canvas->restore();
522
523 // Now redraw it into the coverage location (just to the right of the original scale)
524 canvas->save();
525 canvas->translate(x + ShapeRenderer::kTileWidth + 8.f, 4.f);
526 canvas->drawRect(kTile, clear);
527 canvas->drawRect(kTile, outline);
528 shape->redraw(canvas, 1.f, /* debug */ true);
529 canvas->restore();
530
531 // Lastly, shift the canvas translation down by 8 * kTH + padding for the next set of shapes
532 canvas->translate(0.f, 8.f * ShapeRenderer::kTileHeight + 20.f);
533 }
534};
535
536//////////////////////////////////////////////////////////////////////////////
537
538DEF_SLIDE( return new ThinAASlide; )
539
540} // namespace skiagm
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
#define SkScalarMod(x, y)
Definition: SkScalar.h:41
#define SkScalarRoundToScalar(x)
Definition: SkScalar.h:32
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
int32_t SkUnichar
Definition: SkTypes.h:175
#define DEF_SLIDE(code)
Definition: Slide.h:25
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
Definition: SkCanvas.cpp:1195
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition: SkCanvas.h:1543
void clear(SkColor color)
Definition: SkCanvas.h:1199
void rotate(SkScalar degrees)
Definition: SkCanvas.cpp:1300
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
Definition: SkCanvas.cpp:2333
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
Definition: SkFont.h:35
@ kRound_Cap
adds circle
Definition: SkPaint.h:335
void setStyle(Style style)
Definition: SkPaint.cpp:105
void setColor(SkColor color)
Definition: SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
@ kMiter_Join
extends to miter limit
Definition: SkPaint.h:359
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
Definition: SkPath.h:59
void append(const char text[])
Definition: SkString.h:203
void void void void void prependf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:570
void void void appendf(const char format[],...) SK_PRINTF_LIKE(2
Definition: SkString.cpp:550
Definition: Slide.h:29
SkString fName
Definition: Slide.h:54
T * get() const
Definition: SkRefCnt.h:303
void redraw(SkCanvas *canvas, SkScalar scale=1.f, bool debugMode=false)
sk_sp< ShapeRenderer > toHairline() override
static sk_sp< OffscreenShapeRenderer > Make(sk_sp< ShapeRenderer > renderer, int supersample, bool forceRaster=false)
~OffscreenShapeRenderer() override=default
void prepareBuffer(SkCanvas *canvas, SkPaint *paint, SkScalar tx, SkScalar ty, SkScalar angle)
void draw(SkCanvas *canvas, SkPaint *paint, SkScalar tx, SkScalar ty, SkScalar angle) override
static sk_sp< ShapeRenderer > MakeCurve(SkScalar depth, bool hairline=false)
Definition: ThinAASlide.cpp:81
sk_sp< ShapeRenderer > toHairline() override
static sk_sp< ShapeRenderer > MakeLine(bool hairline=false)
Definition: ThinAASlide.cpp:73
void draw(SkCanvas *canvas, SkPaint *paint, SkScalar tx, SkScalar ty, SkScalar angle) override
SkString name() override
Definition: ThinAASlide.cpp:85
static sk_sp< ShapeRenderer > MakeLines(SkScalar depth, bool hairline=false)
Definition: ThinAASlide.cpp:77
void draw(SkCanvas *canvas, SkPaint *paint, SkScalar tx, SkScalar ty, SkScalar angle) override
Definition: ThinAASlide.cpp:57
static sk_sp< ShapeRenderer > Make()
Definition: ThinAASlide.cpp:46
SkString name() override
Definition: ThinAASlide.cpp:50
sk_sp< ShapeRenderer > toHairline() override
Definition: ThinAASlide.cpp:52
virtual sk_sp< ShapeRenderer > toHairline()=0
static constexpr SkScalar kTileHeight
Definition: ThinAASlide.cpp:25
static constexpr SkScalar kTileWidth
Definition: ThinAASlide.cpp:24
virtual void draw(SkCanvas *canvas, SkPaint *paint, SkScalar tx, SkScalar ty, SkScalar angle)=0
void applyLocalTransform(SkCanvas *canvas, SkScalar tx, SkScalar ty, SkScalar angle)
Definition: ThinAASlide.cpp:38
virtual SkString name()=0
void load(SkScalar w, SkScalar h) override
bool animate(double nanos) override
bool onChar(SkUnichar key) override
void draw(SkCanvas *canvas) override
const Paint & paint
Definition: color_source.cc:38
DlColor color
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
std::u16string text
double x
SkSamplingOptions sampling
Definition: SkRecords.h:337
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
sk_sp< SkTypeface > DefaultTypeface()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
font
Font Metadata and Metrics.
const myers::Point & get(const myers::Segment &)
static SkPath scale(const SkPath &path, SkScalar scale)
Definition: patheffects.cpp:68
SkSamplingOptions(SkFilterMode::kLinear))
Definition: ref_ptr.h:256
SkScalar w
SkScalar h
int32_t width
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646