Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
blurrect.cpp
Go to the documentation of this file.
1/*
2* Copyright 2012 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 <cmath>
9#include "gm/gm.h"
21#include "include/core/SkRect.h"
25#include "include/core/SkSize.h"
33#include "src/core/SkBlurMask.h"
34#include "src/core/SkMask.h"
37
38#include <vector>
39
40#define STROKE_WIDTH SkIntToScalar(10)
41
42typedef void (*Proc)(SkCanvas*, const SkRect&, const SkPaint&);
43
44static void fill_rect(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
45 canvas->drawRect(r, p);
46}
47
48static void draw_donut(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
49 SkRect rect;
50 SkPathBuilder path;
51
52 rect = r;
53 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
54 path.addRect(rect);
55 rect = r;
56 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
57
58 path.addRect(rect);
59 path.setFillType(SkPathFillType::kEvenOdd);
60
61 canvas->drawPath(path.detach(), p);
62}
63
64static void draw_donut_skewed(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
65 SkRect rect;
66 SkPathBuilder path;
67
68 rect = r;
69 rect.outset(STROKE_WIDTH/2, STROKE_WIDTH/2);
70 path.addRect(rect);
71 rect = r;
72 rect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
73
74 rect.offset(7, -7);
75
76 path.addRect(rect);
77 path.setFillType(SkPathFillType::kEvenOdd);
78
79 canvas->drawPath(path.detach(), p);
80}
81
82/*
83 * Spits out an arbitrary gradient to test blur with shader on paint
84 */
86 SkPoint pts[2] = {
87 { 0, 0 },
88 { SkIntToScalar(100), SkIntToScalar(100) }
89 };
91 const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, };
92 const SkScalar pos[] = { SK_Scalar1/4, SK_Scalar1*3/4 };
94 scale.setScale(0.5f, 0.5f);
95 scale.postTranslate(25.f, 25.f);
96 SkPoint center0, center1;
97 center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
98 SkScalarAve(pts[0].fY, pts[1].fY));
99 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
100 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
101 return SkGradientShader::MakeTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7,
102 center0, (pts[1].fX - pts[0].fX) / 2,
103 colors, pos, std::size(colors), tm,
104 0, &scale);
105}
106
107typedef void (*PaintProc)(SkPaint*, SkScalar width);
108
109class BlurRectGM : public skiagm::GM {
110public:
111 BlurRectGM(const char name[], U8CPU alpha) : fName(name), fAlpha(SkToU8(alpha)) {}
112
113private:
115 const char* fName;
116 SkAlpha fAlpha;
117
118 void onOnceBeforeDraw() override {
119 for (int i = 0; i <= kLastEnum_SkBlurStyle; ++i) {
120 fMaskFilters[i] = SkMaskFilter::MakeBlur((SkBlurStyle)i,
122 }
123 }
124
125 SkString getName() const override { return SkString(fName); }
126
127 SkISize getISize() override { return {860, 820}; }
128
129 void onDraw(SkCanvas* canvas) override {
130 canvas->translate(STROKE_WIDTH*3/2, STROKE_WIDTH*3/2);
131
132 SkRect r = { 0, 0, 100, 50 };
133 SkScalar scales[] = { SK_Scalar1, 0.6f };
134
135 for (size_t s = 0; s < std::size(scales); ++s) {
136 canvas->save();
137 for (size_t f = 0; f < std::size(fMaskFilters); ++f) {
139 paint.setMaskFilter(fMaskFilters[f]);
140 paint.setAlpha(fAlpha);
141
142 SkPaint paintWithRadial = paint;
143 paintWithRadial.setShader(make_radial());
144
145 constexpr Proc procs[] = {
147 };
148
149 canvas->save();
150 canvas->scale(scales[s], scales[s]);
151 this->drawProcs(canvas, r, paint, false, procs, std::size(procs));
152 canvas->translate(r.width() * 4/3, 0);
153 this->drawProcs(canvas, r, paintWithRadial, false, procs, std::size(procs));
154 canvas->translate(r.width() * 4/3, 0);
155 this->drawProcs(canvas, r, paint, true, procs, std::size(procs));
156 canvas->translate(r.width() * 4/3, 0);
157 this->drawProcs(canvas, r, paintWithRadial, true, procs, std::size(procs));
158 canvas->restore();
159
160 canvas->translate(0, std::size(procs) * r.height() * 4/3 * scales[s]);
161 }
162 canvas->restore();
163 canvas->translate(4 * r.width() * 4/3 * scales[s], 0);
164 }
165 }
166
167 void drawProcs(SkCanvas* canvas, const SkRect& r, const SkPaint& paint,
168 bool doClip, const Proc procs[], size_t procsCount) {
169 SkAutoCanvasRestore acr(canvas, true);
170 for (size_t i = 0; i < procsCount; ++i) {
171 if (doClip) {
172 SkRect clipRect(r);
173 clipRect.inset(STROKE_WIDTH/2, STROKE_WIDTH/2);
174 canvas->save();
175 canvas->clipRect(r);
176 }
177 procs[i](canvas, r, paint);
178 if (doClip) {
179 canvas->restore();
180 }
181 canvas->translate(0, r.height() * 4/3);
182 }
183 }
184};
185
186DEF_SIMPLE_GM(blurrect_gallery, canvas, 1200, 1024) {
187 const int fGMWidth = 1200;
188 const int fPadding = 10;
189 const int fMargin = 100;
190
191 const int widths[] = {25, 5, 5, 100, 150, 25};
192 const int heights[] = {100, 100, 5, 25, 150, 25};
194 const float radii[] = {20, 5, 10};
195
196 canvas->translate(50,20);
197
198 int cur_x = 0;
199 int cur_y = 0;
200
201 int max_height = 0;
202
203 for (size_t i = 0 ; i < std::size(widths) ; i++) {
204 int width = widths[i];
205 int height = heights[i];
206 SkRect r;
208 SkAutoCanvasRestore autoRestore(canvas, true);
209
210 for (size_t j = 0 ; j < std::size(radii) ; j++) {
211 float radius = radii[j];
212 for (size_t k = 0 ; k < std::size(styles) ; k++) {
213 SkBlurStyle style = styles[k];
214
215 SkMaskBuilder mask;
217 &mask, r, style)) {
218 continue;
219 }
220
221 SkAutoMaskFreeImage amfi(mask.image());
222
223 SkBitmap bm;
224 bm.installMaskPixels(mask);
225
226 if (cur_x + bm.width() >= fGMWidth - fMargin) {
227 cur_x = 0;
228 cur_y += max_height + fPadding;
229 max_height = 0;
230 }
231
232 canvas->save();
233 canvas->translate((SkScalar)cur_x, (SkScalar)cur_y);
234 canvas->translate(-(bm.width() - r.width())/2, -(bm.height()-r.height())/2);
235 canvas->drawImage(bm.asImage(), 0.f, 0.f);
236 canvas->restore();
237
238 cur_x += bm.width() + fPadding;
239 if (bm.height() > max_height)
240 max_height = bm.height();
241 }
242 }
243 }
244}
245
246namespace skiagm {
247
248// Compares actual blur rects with reference masks created by the GM. Animates sigma in viewer.
249class BlurRectCompareGM : public GM {
250protected:
251 SkString getName() const override { return SkString("blurrect_compare"); }
252
253 SkISize getISize() override { return {900, 1220}; }
254
255 void onOnceBeforeDraw() override { this->prepareReferenceMasks(); }
256
257 DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
258 if (canvas->imageInfo().colorType() == kUnknown_SkColorType ||
259 (canvas->recordingContext() && !canvas->recordingContext()->asDirectContext())) {
260 *errorMsg = "Not supported when recording, relies on canvas->makeSurface()";
261 return DrawResult::kSkip;
262 }
263 int32_t ctxID = canvas->recordingContext() ? canvas->recordingContext()->priv().contextID()
264 : 0;
265 if (fRecalcMasksForAnimation || !fActualMasks[0][0][0] || ctxID != fLastContextUniqueID) {
266 if (fRecalcMasksForAnimation) {
267 // Sigma is changing so references must also be recalculated.
268 this->prepareReferenceMasks();
269 }
270 this->prepareActualMasks(canvas);
271 this->prepareMaskDifferences(canvas);
272 fLastContextUniqueID = ctxID;
273 fRecalcMasksForAnimation = false;
274 }
275 canvas->clear(SK_ColorBLACK);
276 static constexpr float kMargin = 30;
277 float totalW = 0;
278 for (auto w : kSizes) {
279 totalW += w + kMargin;
280 }
281 canvas->translate(kMargin, kMargin);
282 for (int mode = 0; mode < 3; ++mode) {
283 canvas->save();
284 for (size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
285 auto sigma = kSigmas[sigmaIdx] + fSigmaAnimationBoost;
286 for (size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
287 auto h = kSizes[heightIdx];
288 canvas->save();
289 for (size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
290 auto w = kSizes[widthIdx];
292 paint.setColor(SK_ColorWHITE);
293 SkImage* img;
294 switch (mode) {
295 case 0:
296 img = fReferenceMasks[sigmaIdx][heightIdx][widthIdx].get();
297 break;
298 case 1:
299 img = fActualMasks[sigmaIdx][heightIdx][widthIdx].get();
300 break;
301 case 2:
302 img = fMaskDifferences[sigmaIdx][heightIdx][widthIdx].get();
303 // The error images are opaque, use kPlus so they are additive if
304 // the overlap between test cases.
305 paint.setBlendMode(SkBlendMode::kPlus);
306 break;
307 }
308 auto pad = PadForSigma(sigma);
309 canvas->drawImage(img, -pad, -pad, SkSamplingOptions(), &paint);
310#if 0 // Uncomment to hairline stroke around blurred rect in red on top of the blur result.
311 // The rect is defined at integer coords. We inset by 1/2 pixel so our stroke lies on top
312 // of the edge pixels.
313 SkPaint stroke;
314 stroke.setColor(SK_ColorRED);
315 stroke.setStrokeWidth(0.f);
317 canvas->drawRect(SkRect::MakeWH(w, h).makeInset(0.5, 0.5), stroke);
318#endif
319 canvas->translate(w + kMargin, 0.f);
320 }
321 canvas->restore();
322 canvas->translate(0, h + kMargin);
323 }
324 }
325 canvas->restore();
326 canvas->translate(totalW + 2 * kMargin, 0);
327 }
328 return DrawResult::kOk;
329 }
330 bool onAnimate(double nanos) override {
331 fSigmaAnimationBoost = TimeUtils::SineWave(nanos, 5, 2.5f, 0.f, 2.f);
332 fRecalcMasksForAnimation = true;
333 return true;
334 }
335
336private:
337 void prepareReferenceMasks() {
338 auto create_reference_mask = [](int w, int h, float sigma, int numSubpixels) {
339 int pad = PadForSigma(sigma);
340 int maskW = w + 2 * pad;
341 int maskH = h + 2 * pad;
342 // We'll do all our calculations at subpixel resolution, so adjust params
343 w *= numSubpixels;
344 h *= numSubpixels;
345 sigma *= numSubpixels;
346 auto scale = SK_ScalarRoot2Over2 / sigma;
347 auto def_integral_approx = [scale](float a, float b) {
348 return 0.5f * (std::erf(b * scale) - std::erf(a * scale));
349 };
350 // Do the x-pass. Above/below rect are rows of zero. All rows that intersect the rect
351 // are the same. The row is calculated and stored at subpixel resolution.
352 SkASSERT(!(numSubpixels & 0b1));
353 std::unique_ptr<float[]> row(new float[maskW * numSubpixels]);
354 for (int col = 0; col < maskW * numSubpixels; ++col) {
355 // Compute distance to rect left in subpixel units
356 float ldiff = numSubpixels * pad - (col + 0.5f);
357 float rdiff = ldiff + w;
358 row[col] = def_integral_approx(ldiff, rdiff);
359 }
360 // y-pass
361 SkBitmap bmp;
362 bmp.allocPixels(SkImageInfo::MakeA8(maskW, maskH));
363 std::unique_ptr<float[]> accums(new float[maskW]);
364 const float accumScale = 1.f / (numSubpixels * numSubpixels);
365 for (int y = 0; y < maskH; ++y) {
366 // Initialize subpixel accumulation buffer for this row.
367 std::fill_n(accums.get(), maskW, 0);
368 for (int ys = 0; ys < numSubpixels; ++ys) {
369 // At each subpixel we want to integrate over the kernel centered at the
370 // subpixel multiplied by the x-pass. The x-pass is zero above and below the
371 // rect and constant valued from rect top to rect bottom. So we can get the
372 // integral of just the kernel from rect top to rect bottom and multiply by
373 // the single x-pass value from our precomputed row.
374 float tdiff = numSubpixels * pad - (y * numSubpixels + ys + 0.5f);
375 float bdiff = tdiff + h;
376 auto integral = def_integral_approx(tdiff, bdiff);
377 for (int x = 0; x < maskW; ++x) {
378 for (int xs = 0; xs < numSubpixels; ++xs) {
379 int rowIdx = x * numSubpixels + xs;
380 accums[x] += integral * row[rowIdx];
381 }
382 }
383 }
384 for (int x = 0; x < maskW; ++x) {
385 auto result = accums[x] * accumScale;
386 *bmp.getAddr8(x, y) = SkToU8(sk_float_round2int(255.f * result));
387 }
388 }
389 return bmp.asImage();
390 };
391
392 // Number of times to subsample (in both X and Y). If fRecalcMasksForAnimation is true
393 // then we're animating, don't subsample as much to keep fps higher.
394 const int numSubpixels = fRecalcMasksForAnimation ? 2 : 8;
395
396 for (size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
397 auto sigma = kSigmas[sigmaIdx] + fSigmaAnimationBoost;
398 for (size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
399 auto h = kSizes[heightIdx];
400 for (size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
401 auto w = kSizes[widthIdx];
402 fReferenceMasks[sigmaIdx][heightIdx][widthIdx] =
403 create_reference_mask(w, h, sigma, numSubpixels);
404 }
405 }
406 }
407 }
408
409 void prepareActualMasks(SkCanvas* canvas) {
410 for (size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
411 auto sigma = kSigmas[sigmaIdx] + fSigmaAnimationBoost;
412 for (size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
413 auto h = kSizes[heightIdx];
414 for (size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
415 auto w = kSizes[widthIdx];
416 auto pad = PadForSigma(sigma);
417 auto ii = SkImageInfo::MakeA8(w + 2 * pad, h + 2 * pad);
418 auto surf = canvas->makeSurface(ii);
419 if (!surf) {
420 // Some GPUs don't have renderable A8 :(
421 surf = canvas->makeSurface(ii.makeColorType(kRGBA_8888_SkColorType));
422 if (!surf) {
423 return;
424 }
425 }
426 auto rect = SkRect::MakeXYWH(pad, pad, w, h);
428 // Color doesn't matter if we're rendering to A8 but does if we promoted to
429 // RGBA above.
430 paint.setColor(SK_ColorWHITE);
431 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma));
432 surf->getCanvas()->drawRect(rect, paint);
433 fActualMasks[sigmaIdx][heightIdx][widthIdx] = surf->makeImageSnapshot();
434 }
435 }
436 }
437 }
438
439 void prepareMaskDifferences(SkCanvas* canvas) {
440 for (size_t sigmaIdx = 0; sigmaIdx < kNumSigmas; ++sigmaIdx) {
441 for (size_t heightIdx = 0; heightIdx < kNumSizes; ++heightIdx) {
442 for (size_t widthIdx = 0; widthIdx < kNumSizes; ++widthIdx) {
443 const auto& r = fReferenceMasks[sigmaIdx][heightIdx][widthIdx];
444 const auto& a = fActualMasks[sigmaIdx][heightIdx][widthIdx];
445 auto& d = fMaskDifferences[sigmaIdx][heightIdx][widthIdx];
446 // The actual image might not be present if we're on an abandoned GrContext.
447 if (!a) {
448 d.reset();
449 continue;
450 }
451 SkASSERT(r->width() == a->width());
452 SkASSERT(r->height() == a->height());
453 auto ii = SkImageInfo::Make(r->width(), r->height(),
455 auto surf = canvas->makeSurface(ii);
456 if (!surf) {
457 return;
458 }
459 // We visualize the difference by turning both the alpha masks into opaque green
460 // images (where alpha becomes the green channel) and then perform a
461 // SkBlendMode::kDifference between them.
462 SkPaint filterPaint;
463 filterPaint.setColor(SK_ColorWHITE);
464 // Actually 8 * alpha becomes green to really highlight differences.
465 static constexpr float kGreenifyM[] = {0, 0, 0, 0, 0,
466 0, 0, 0, 8, 0,
467 0, 0, 0, 0, 0,
468 0, 0, 0, 0, 1};
469 auto greenifyCF = SkColorFilters::Matrix(kGreenifyM);
471 paint.setBlendMode(SkBlendMode::kSrc);
472 paint.setColorFilter(std::move(greenifyCF));
473 surf->getCanvas()->drawImage(a, 0, 0, SkSamplingOptions(), &paint);
474 paint.setBlendMode(SkBlendMode::kDifference);
475 surf->getCanvas()->drawImage(r, 0, 0, SkSamplingOptions(), &paint);
476 d = surf->makeImageSnapshot();
477 }
478 }
479 }
480 }
481
482 // Per side padding around mask images for a sigma. Make this overly generous to ensure bugs
483 // related to big blurs are fully visible.
484 static int PadForSigma(float sigma) { return sk_float_ceil2int(4 * sigma); }
485
486 inline static constexpr int kSizes[] = {1, 2, 4, 8, 16, 32};
487 inline static constexpr float kSigmas[] = {0.5f, 1.2f, 2.3f, 3.9f, 7.4f};
488 inline static constexpr size_t kNumSizes = std::size(kSizes);
489 inline static constexpr size_t kNumSigmas = std::size(kSigmas);
490
491 sk_sp<SkImage> fReferenceMasks[kNumSigmas][kNumSizes][kNumSizes];
492 sk_sp<SkImage> fActualMasks[kNumSigmas][kNumSizes][kNumSizes];
493 sk_sp<SkImage> fMaskDifferences[kNumSigmas][kNumSizes][kNumSizes];
494 int32_t fLastContextUniqueID;
495 // These are used only when animating.
496 float fSigmaAnimationBoost = 0;
497 bool fRecalcMasksForAnimation = false;
498};
499
500} // namespace skiagm
501
502//////////////////////////////////////////////////////////////////////////////
503
504DEF_GM(return new BlurRectGM("blurrects", 0xFF);)
505DEF_GM(return new skiagm::BlurRectCompareGM();)
506
507//////////////////////////////////////////////////////////////////////////////
508
509DEF_SIMPLE_GM(blur_matrix_rect, canvas, 650, 685) {
510 static constexpr auto kRect = SkRect::MakeWH(14, 60);
511 static constexpr float kSigmas[] = {0.5f, 1.2f, 2.3f, 3.9f, 7.4f};
512 static constexpr size_t kNumSigmas = std::size(kSigmas);
513
514 const SkPoint c = {kRect.centerX(), kRect.centerY()};
515
516 std::vector<SkMatrix> matrices;
517
518 matrices.push_back(SkMatrix::RotateDeg(4.f, c));
519
520 matrices.push_back(SkMatrix::RotateDeg(63.f, c));
521
522 matrices.push_back(SkMatrix::RotateDeg(30.f, c));
523 matrices.back().preScale(1.1f, .5f);
524
525 matrices.push_back(SkMatrix::RotateDeg(147.f, c));
526 matrices.back().preScale(3.f, .1f);
527
529 mirror.setAll(0, 1, 0,
530 1, 0, 0,
531 0, 0, 1);
532 matrices.push_back(SkMatrix::Concat(mirror, matrices.back()));
533
534 matrices.push_back(SkMatrix::RotateDeg(197.f, c));
535 matrices.back().preSkew(.3f, -.5f);
536
537 auto bounds = SkRect::MakeEmpty();
538 for (const auto& m : matrices) {
539 SkRect mapped;
540 m.mapRect(&mapped, kRect);
541 bounds.joinNonEmptyArg(mapped.makeSorted());
542 }
543 float blurPad = 2.f*kSigmas[kNumSigmas - 1];
544 bounds.outset(blurPad, blurPad);
545 canvas->translate(-bounds.left(), -bounds.top());
546 for (auto sigma : kSigmas) {
548 paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, sigma));
549 canvas->save();
550 for (const auto& m : matrices) {
551 canvas->save();
552 canvas->concat(m);
553 canvas->drawRect(kRect, paint);
554 canvas->restore();
555 canvas->translate(0, bounds.height());
556 }
557 canvas->restore();
558 canvas->translate(bounds.width(), 0);
559 }
560}
const char * fName
SkPoint pos
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkASSERT(cond)
Definition SkAssert.h:116
static unsigned mirror(SkFixed fx, int max)
@ kPlus
r = min(s + d, 1)
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
SkBlurStyle
Definition SkBlurTypes.h:11
@ kOuter_SkBlurStyle
nothing inside, fuzzy outside
Definition SkBlurTypes.h:14
@ kInner_SkBlurStyle
fuzzy inside, nothing outside
Definition SkBlurTypes.h:15
@ kNormal_SkBlurStyle
fuzzy inside and outside
Definition SkBlurTypes.h:12
@ kLastEnum_SkBlurStyle
Definition SkBlurTypes.h:17
unsigned U8CPU
Definition SkCPUTypes.h:18
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kUnknown_SkColorType
uninitialized
Definition SkColorType.h:20
uint32_t SkColor
Definition SkColor.h:37
uint8_t SkAlpha
Definition SkColor.h:26
constexpr SkColor SK_ColorRED
Definition SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
#define sk_float_ceil2int(x)
#define sk_float_round2int(x)
std::unique_ptr< uint8_t, SkFunctionObject< SkMaskBuilder::FreeImage > > SkAutoMaskFreeImage
Definition SkMask.h:316
#define SK_Scalar1
Definition SkScalar.h:18
#define SkScalarAve(a, b)
Definition SkScalar.h:74
#define SkIntToScalar(x)
Definition SkScalar.h:57
static SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t)
Definition SkScalar.h:131
#define SK_ScalarRoot2Over2
Definition SkScalar.h:23
SkTileMode
Definition SkTileMode.h:13
constexpr uint8_t SkToU8(S x)
Definition SkTo.h:22
const SkScalar widths[]
@ kMargin
static void draw_donut(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
Definition blurrect.cpp:48
#define STROKE_WIDTH
Definition blurrect.cpp:40
static void draw_donut_skewed(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
Definition blurrect.cpp:64
static void fill_rect(SkCanvas *canvas, const SkRect &r, const SkPaint &p)
Definition blurrect.cpp:44
void(* PaintProc)(SkPaint *, SkScalar width)
Definition blurrect.cpp:107
static sk_sp< SkShader > make_radial()
Definition blurrect.cpp:85
void(* Proc)(SkCanvas *, const SkRect &, const SkPaint &)
Definition blurrect.cpp:42
constexpr SkRect kRect
BlurRectGM(const char name[], U8CPU alpha)
Definition blurrect.cpp:111
void onDraw(SkCanvas *canvas) override
Definition blurrect.cpp:129
SkString getName() const override
Definition blurrect.cpp:125
void onOnceBeforeDraw() override
Definition blurrect.cpp:118
SkISize getISize() override
Definition blurrect.cpp:127
uint32_t contextID() const
virtual GrDirectContext * asDirectContext()
GrRecordingContextPriv priv()
bool installMaskPixels(SkMaskBuilder &mask)
Definition SkBitmap.cpp:349
void allocPixels(const SkImageInfo &info, size_t rowBytes)
Definition SkBitmap.cpp:258
sk_sp< SkImage > asImage() const
Definition SkBitmap.cpp:645
uint8_t * getAddr8(int x, int y) const
Definition SkBitmap.h:1270
int width() const
Definition SkBitmap.h:149
int height() const
Definition SkBitmap.h:158
static bool BlurRect(SkScalar sigma, SkMaskBuilder *dst, const SkRect &src, SkBlurStyle, SkIPoint *margin=nullptr, SkMaskBuilder::CreateMode createMode=SkMaskBuilder::kComputeBoundsAndRenderImage_CreateMode)
static SkScalar SK_SPI ConvertRadiusToSigma(SkScalar radius)
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)
sk_sp< SkSurface > makeSurface(const SkImageInfo &info, const SkSurfaceProps *props=nullptr)
virtual GrRecordingContext * recordingContext() const
void clear(SkColor color)
Definition SkCanvas.h:1199
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void concat(const SkMatrix &matrix)
SkImageInfo imageInfo() const
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkShader > MakeTwoPointConical(const SkPoint &start, SkScalar startRadius, const SkPoint &end, SkScalar endRadius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
Definition SkMatrix.cpp:281
SkMatrix & preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
Definition SkMatrix.cpp:512
static SkMatrix RotateDeg(SkScalar deg)
Definition SkMatrix.h:104
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
Definition SkMatrix.h:562
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition SkMatrix.h:1775
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition SkMatrix.cpp:296
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
void setShader(sk_sp< SkShader > shader)
void setStrokeWidth(SkScalar width)
Definition SkPaint.cpp:159
skiagm::DrawResult DrawResult
Definition gm.h:112
virtual void onDraw(SkCanvas *)
Definition gm.cpp:143
const Paint & paint
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
float SkScalar
Definition extension.cpp:12
static bool b
struct MyStruct s
struct MyStruct a[10]
GAsyncResult * result
const char * name
Definition fuchsia.cc:50
#define DEF_GM(CODE)
Definition gm.h:40
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
double y
double x
sk_sp< SkBlender > blender SkRect rect
Definition SkRecords.h:350
static float SineWave(double time, float periodInSecs, float phaseInSecs, float min, float max)
Definition TimeUtils.h:48
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition switches.h:228
SkScalar w
SkScalar h
int32_t height
int32_t width
const Scalar scale
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkColorType colorType() const
static SkImageInfo MakeA8(int width, int height)
uint8_t *& image()
Definition SkMask.h:236
void set(float x, float y)
SkRect makeSorted() const
Definition SkRect.h:1330
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
void setWH(float width, float height)
Definition SkRect.h:944
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition SkRect.h:659
constexpr float centerX() const
Definition SkRect.h:776
constexpr float height() const
Definition SkRect.h:769
constexpr float centerY() const
Definition SkRect.h:785
constexpr float width() const
Definition SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609