Flutter Engine
The Flutter Engine
gpu_blur_utils.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 Google LLC.
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
15#include "src/gpu/BlurUtils.h"
20#include "src/gpu/ganesh/SkGr.h"
26
27namespace {
28
31 SkIRect dstB,
32 SkIRect srcB,
33 float sigmaX,
34 float sigmaY,
36 auto resultSDC = GrBlurUtils::GaussianBlur(ctx,
37 src,
40 nullptr,
41 dstB,
42 srcB,
43 sigmaX,
44 sigmaY,
45 mode);
46 if (!resultSDC) {
47 return {};
48 }
49 return resultSDC->readSurfaceView();
50};
51
52// Performs tiling first of the src into dst bounds with a surrounding skirt so the blur can use
53// clamp. Does repeated blurs rather than invoking downsampling.
54static GrSurfaceProxyView slow_blur(GrRecordingContext* rContext,
56 SkIRect dstB,
57 SkIRect srcB,
58 float sigmaX,
59 float sigmaY,
61 auto tileInto = [rContext](GrSurfaceProxyView src,
62 SkIRect srcTileRect,
63 SkISize resultSize,
67 auto sfc = rContext->priv().makeSFC(info, /*label=*/{});
68 if (!sfc) {
69 return GrSurfaceProxyView{};
70 }
75 sampler,
76 SkRect::Make(srcTileRect),
77 *rContext->priv().caps());
78 sfc->fillWithFP(std::move(fp));
79 return sfc->readSurfaceView();
80 };
81
83 SkISize size = {dstB.width() + 2*outset.x(), dstB.height() + 2*outset.y()};
84 src = tileInto(std::move(src), srcB, size, outset - dstB.topLeft(), mode);
85 if (!src) {
86 return {};
87 }
88 dstB = SkIRect::MakePtSize(outset, dstB.size());
89
90 while (sigmaX || sigmaY) {
91 float stepX = sigmaX;
92 if (stepX > skgpu::kMaxLinearBlurSigma) {
94 // A blur of sigma1 followed by a blur of sigma2 is equiv. to a single blur of
95 // sqrt(sigma1^2 + sigma2^2).
97 } else {
98 sigmaX = 0.f;
99 }
100 float stepY = sigmaY;
101 if (stepY > skgpu::kMaxLinearBlurSigma) {
104 } else {
105 sigmaY = 0.f;
106 }
107 auto bounds = SkIRect::MakeSize(src.dimensions());
108 auto sdc = GrBlurUtils::GaussianBlur(rContext,
109 std::move(src),
112 nullptr,
113 bounds,
114 bounds,
115 stepX,
116 stepY,
118 if (!sdc) {
119 return {};
120 }
121 src = sdc->readSurfaceView();
122 }
123 // We have o use the original mode here because we may have only blurred in X or Y and then
124 // the other dimension was not expanded.
125 auto srcRect = SkIRect::MakeSize(src.dimensions());
126 return tileInto(std::move(src), srcRect, dstB.size(), -outset, SkTileMode::kClamp);
127};
128
129// Makes a src texture for as a source for blurs. If 'contentArea' then the content will
130// be in that rect, the 1-pixel surrounding border will be transparent black, and red outside of
131// that. Otherwise, the content fills the dimensions.
133 SkISize dimensions,
134 const SkIRect* contentArea = nullptr) {
136 auto surf = SkSurfaces::RenderTarget(rContext, skgpu::Budgeted::kYes, srcII);
137 if (!surf) {
138 return {};
139 }
140
141 float w, h;
142 if (contentArea) {
143 surf->getCanvas()->clear(SK_ColorRED);
144 surf->getCanvas()->clipIRect(contentArea->makeOutset(1, 1));
145 surf->getCanvas()->clear(SK_ColorTRANSPARENT);
146 surf->getCanvas()->clipIRect(*contentArea);
147 surf->getCanvas()->translate(contentArea->top(), contentArea->left());
148 w = contentArea->width();
149 h = contentArea->height();
150 } else {
151 w = dimensions.width();
152 h = dimensions.height();
153 }
154
155 surf->getCanvas()->drawColor(SK_ColorDKGRAY);
157 paint.setAntiAlias(true);
159 // Draw four horizontal lines at 1/8, 1/4, 3/4, 7/8.
160 paint.setStrokeWidth(h/12.f);
161 paint.setColor(SK_ColorRED);
162 surf->getCanvas()->drawLine({0.f, 1.f*h/8.f}, {w, 1.f*h/8.f}, paint);
163 paint.setColor(/* sea foam */ 0xFF71EEB8);
164 surf->getCanvas()->drawLine({0.f, 1.f*h/4.f}, {w, 1.f*h/4.f}, paint);
165 paint.setColor(SK_ColorYELLOW);
166 surf->getCanvas()->drawLine({0.f, 3.f*h/4.f}, {w, 3.f*h/4.f}, paint);
167 paint.setColor(SK_ColorCYAN);
168 surf->getCanvas()->drawLine({0.f, 7.f*h/8.f}, {w, 7.f*h/8.f}, paint);
169
170 // Draw four vertical lines at 1/8, 1/4, 3/4, 7/8.
171 paint.setStrokeWidth(w/12.f);
172 paint.setColor(/* orange */ 0xFFFFA500);
173 surf->getCanvas()->drawLine({1.f*w/8.f, 0.f}, {1.f*h/8.f, h}, paint);
174 paint.setColor(SK_ColorBLUE);
175 surf->getCanvas()->drawLine({1.f*w/4.f, 0.f}, {1.f*h/4.f, h}, paint);
176 paint.setColor(SK_ColorMAGENTA);
177 surf->getCanvas()->drawLine({3.f*w/4.f, 0.f}, {3.f*h/4.f, h}, paint);
178 paint.setColor(SK_ColorGREEN);
179 surf->getCanvas()->drawLine({7.f*w/8.f, 0.f}, {7.f*h/8.f, h}, paint);
180
181 auto img = surf->makeImageSnapshot();
182 auto [src, ct] = skgpu::ganesh::AsView(rContext, img, skgpu::Mipmapped::kNo);
183 return src;
184}
185
186} // namespace
187
188namespace skiagm {
189
190static GM::DrawResult run(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg,
191 bool subsetSrc, bool ref) {
192 GrSurfaceProxyView src = make_src_image(rContext, {60, 60});
193 if (!src) {
194 *errorMsg = "Failed to create source image";
195 return DrawResult::kSkip;
196 }
197
199 if (!sdc) {
201 return DrawResult::kSkip;
202 }
203
204 SkIRect srcRect = SkIRect::MakeSize(src.dimensions());
205 if (subsetSrc) {
206 srcRect = SkIRect::MakeXYWH(2.f*srcRect.width() /8.f,
207 1.f*srcRect.height()/8.f,
208 5.f*srcRect.width() /8.f,
209 6.f*srcRect.height()/8.f);
210 }
211 int srcW = srcRect.width();
212 int srcH = srcRect.height();
213 // Each set of rects is drawn in one test area so they probably should not abut or overlap
214 // to visualize the blurs separately.
215 const std::vector<SkIRect> dstRectSets[] = {
216 // encloses source bounds.
217 {
218 srcRect.makeOutset(srcW/5, srcH/5)
219 },
220
221 // partial overlap from above/below.
222 {
223 SkIRect::MakeXYWH(srcRect.x(), srcRect.y() + 3*srcH/4, srcW, srcH),
224 SkIRect::MakeXYWH(srcRect.x(), srcRect.y() - 3*srcH/4, srcW, srcH)
225 },
226
227 // adjacent to each side of src bounds.
228 {
229 srcRect.makeOffset( 0, srcH),
230 srcRect.makeOffset( srcW, 0),
231 srcRect.makeOffset( 0, -srcH),
232 srcRect.makeOffset(-srcW, 0),
233 },
234
235 // fully outside src bounds in one direction.
236 {
237 SkIRect::MakeXYWH(-6.f*srcW/8.f, -7.f*srcH/8.f, 4.f*srcW/8.f, 20.f*srcH/8.f)
238 .makeOffset(srcRect.topLeft()),
239 SkIRect::MakeXYWH(-1.f*srcW/8.f, -7.f*srcH/8.f, 16.f*srcW/8.f, 2.f*srcH/8.f)
240 .makeOffset(srcRect.topLeft()),
241 SkIRect::MakeXYWH(10.f*srcW/8.f, -3.f*srcH/8.f, 4.f*srcW/8.f, 16.f*srcH/8.f)
242 .makeOffset(srcRect.topLeft()),
243 SkIRect::MakeXYWH(-7.f*srcW/8.f, 14.f*srcH/8.f, 18.f*srcW/8.f, 1.f*srcH/8.f)
244 .makeOffset(srcRect.topLeft()),
245 },
246
247 // outside of src bounds in both directions.
248 {
249 SkIRect::MakeXYWH(-5.f*srcW/8.f, -5.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
250 .makeOffset(srcRect.topLeft()),
251 SkIRect::MakeXYWH(-5.f*srcW/8.f, 12.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
252 .makeOffset(srcRect.topLeft()),
253 SkIRect::MakeXYWH(12.f*srcW/8.f, -5.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
254 .makeOffset(srcRect.topLeft()),
255 SkIRect::MakeXYWH(12.f*srcW/8.f, 12.f*srcH/8.f, 2.f*srcW/8.f, 2.f*srcH/8.f)
256 .makeOffset(srcRect.topLeft()),
257 },
258 };
259
260 const auto& caps = *rContext->priv().caps();
261
262 static constexpr SkScalar kPad = 10;
263 SkVector trans = {kPad, kPad};
264
265 sdc->clear(SK_PMColor4fWHITE);
266
267 SkIRect testArea = srcRect;
268 testArea.outset(testArea.width(), testArea.height());
269 for (const auto& dstRectSet : dstRectSets) {
270 for (int t = 0; t < kSkTileModeCount; ++t) {
271 auto mode = static_cast<SkTileMode>(t);
273 SkMatrix m = SkMatrix::Translate(trans.x() - testArea.x(), trans.y() - testArea.y());
274 // Draw the src subset in the tile mode faded as a reference before drawing the blur
275 // on top.
276 {
277 static constexpr float kAlpha = 0.2f;
279 sampler, SkRect::Make(srcRect), caps);
281 {kAlpha, kAlpha, kAlpha, kAlpha});
283 paint.setColorFragmentProcessor(std::move(fp));
284 sdc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, SkRect::Make(testArea));
285 }
286 // Do a blur for each dstRect in the set over our testArea-sized background.
287 for (const auto& dstRect : dstRectSet) {
288 const SkScalar sigmaX = src.width() / 10.f;
289 const SkScalar sigmaY = src.height() / 10.f;
290 auto blurFn = ref ? slow_blur : blur;
291 // Blur using the rect and draw on top.
292 if (auto blurView = blurFn(rContext,
293 src,
294 dstRect,
295 srcRect,
296 sigmaX,
297 sigmaY,
298 mode)) {
299 auto fp = GrTextureEffect::Make(blurView,
301 SkMatrix::I(),
302 sampler,
303 caps);
304 // Compose against white (default paint color)
305 fp = GrBlendFragmentProcessor::Make<SkBlendMode::kSrcOver>(std::move(fp),
306 /*dst=*/nullptr);
308 // Compose against white (default paint color) and then replace the dst
309 // (SkBlendMode::kSrc).
310 fp = GrBlendFragmentProcessor::Make<SkBlendMode::kSrcOver>(std::move(fp),
311 /*dst=*/nullptr);
312 paint.setColorFragmentProcessor(std::move(fp));
313 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
314 sdc->fillRectToRect(nullptr,
315 std::move(paint),
316 GrAA::kNo,
317 m,
318 SkRect::Make(dstRect),
319 SkRect::Make(blurView.dimensions()));
320 }
321 // Show the outline of the dst rect. Mostly for kDecal but also allows visual
322 // confirmation that the resulting blur is the right size and in the right place.
323 {
325 static constexpr float kAlpha = 0.6f;
326 paint.setColor4f({0, kAlpha, 0, kAlpha});
329 stroke.setStrokeWidth(1.f);
330 GrStyle style(stroke);
331 auto dstR = SkRect::Make(dstRect).makeOutset(0.5f, 0.5f);
332 sdc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, dstR, &style);
333 }
334 }
335 // Show the rect that's being blurred.
336 {
338 static constexpr float kAlpha = 0.3f;
339 paint.setColor4f({0, 0, 0, kAlpha});
342 stroke.setStrokeWidth(1.f);
343 GrStyle style(stroke);
344 auto srcR = SkRect::Make(srcRect).makeOutset(0.5f, 0.5f);
345 sdc->drawRect(nullptr, std::move(paint), GrAA::kNo, m, srcR, &style);
346 }
347 trans.fX += testArea.width() + kPad;
348 }
349 trans.fX = kPad;
350 trans.fY += testArea.height() + kPad;
351 }
352
353 return DrawResult::kOk;
354}
355
356DEF_SIMPLE_GPU_GM_CAN_FAIL(gpu_blur_utils, rContext, canvas, errorMsg, 765, 955) {
357 return run(rContext, canvas, errorMsg, false, false);
358}
359
360DEF_SIMPLE_GPU_GM_CAN_FAIL(gpu_blur_utils_ref, rContext, canvas, errorMsg, 765, 955) {
361 return run(rContext, canvas, errorMsg, false, true);
362}
363
364DEF_SIMPLE_GPU_GM_CAN_FAIL(gpu_blur_utils_subset_rect, rContext, canvas, errorMsg, 485, 730) {
365 return run(rContext, canvas, errorMsg, true, false);
366}
367
368DEF_SIMPLE_GPU_GM_CAN_FAIL(gpu_blur_utils_subset_ref, rContext, canvas, errorMsg, 485, 730) {
369 return run(rContext, canvas, errorMsg, true, true);
370}
371
372// Because of the way blur sigmas concat (sigTotal = sqrt(sig1^2 + sig2^2) generating these images
373// for very large sigmas is incredibly slow. This can be enabled while working on the blur code to
374// check results.
375static bool constexpr kShowSlowRefImages = false;
376
378 SkCanvas* canvas,
379 SkString* errorMsg,
381 SkIRect srcB) {
383 if (!sdc) {
385 return DrawResult::kSkip;
386 }
387
388 // Clear to a color other than gray to contrast with test image.
389 sdc->clear(SkColor4f{0.3f, 0.4f, 0.2f, 1});
390
391 int x = 10;
392 int y = 10;
393 for (auto blurDirs : {0b01, 0b10, 0b11}) {
394 for (int t = 0; t < kSkTileModeCount; ++t) {
395 auto tm = static_cast<SkTileMode>(t);
396 auto dstB = srcB.makeOutset(30, 30);
397 for (float sigma : {0.f, 5.f, 25.f, 80.f}) {
398 std::vector<decltype(blur)*> blurs;
399 blurs.push_back(blur);
400 if (kShowSlowRefImages) {
401 blurs.push_back(slow_blur);
402 }
403 for (auto b : blurs) {
404 float sigX = sigma*((blurDirs & 0b01) >> 0);
405 float sigY = sigma*((blurDirs & 0b10) >> 1);
406 GrSurfaceProxyView result = b(rContext, src, dstB, srcB, sigX, sigY, tm);
407 auto dstRect = SkIRect::MakeSize(dstB.size()).makeOffset(x, y);
408 // Draw a rect to show where the result should be so it's obvious if it's
409 // missing.
411 paint.setColor4f(b == blur ? SkPMColor4f{0, 0, 1, 1} : SkPMColor4f{1, 0, 0, 1});
412 sdc->drawRect(nullptr,
413 std::move(paint),
414 GrAA::kNo,
415 SkMatrix::I(),
416 SkRect::Make(dstRect).makeOutset(0.5, 0.5),
418 if (result) {
419 std::unique_ptr<GrFragmentProcessor> fp =
421 fp = GrBlendFragmentProcessor::Make<SkBlendMode::kSrcOver>(std::move(fp),
422 /*dst=*/nullptr);
423 sdc->fillRectToRectWithFP(SkIRect::MakeSize(dstB.size()),
424 dstRect,
425 std::move(fp));
426 }
427 x += dstB.width() + 10;
428 }
429 }
430 x = 10;
431 y += dstB.height() + 10;
432 }
433 }
434
435 return DrawResult::kOk;
436}
437
438DEF_SIMPLE_GPU_GM_CAN_FAIL(very_large_sigma_gpu_blur, rContext, canvas, errorMsg, 350, 1030) {
439 auto src = make_src_image(rContext, {15, 15});
440 auto srcB = SkIRect::MakeSize(src.dimensions());
441 return do_very_large_blur_gm(rContext, canvas, errorMsg, std::move(src), srcB);
442}
443
444DEF_SIMPLE_GPU_GM_CAN_FAIL(very_large_sigma_gpu_blur_subset,
445 rContext,
446 canvas,
447 errorMsg,
448 350, 1030) {
449 auto srcB = SkIRect::MakeXYWH(2, 2, 15, 15);
450 SkISize imageSize = SkISize{srcB.width() + 4, srcB.height() + 4};
451 auto src = make_src_image(rContext, imageSize, &srcB);
452 return do_very_large_blur_gm(rContext, canvas, errorMsg, std::move(src), srcB);
453}
454
455DEF_SIMPLE_GPU_GM_CAN_FAIL(very_large_sigma_gpu_blur_subset_transparent_border,
456 rContext,
457 canvas,
458 errorMsg,
459 355, 1055) {
460 auto srcB = SkIRect::MakeXYWH(3, 3, 15, 15);
461 SkISize imageSize = SkISize{srcB.width() + 4, srcB.height() + 4};
462 auto src = make_src_image(rContext, imageSize, &srcB);
463 return do_very_large_blur_gm(rContext, canvas, errorMsg, std::move(src), srcB.makeOutset(1, 1));
464}
465
466} // namespace skiagm
static const int outset
Definition: BlurTest.cpp:58
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static sk_sp< SkImage > make_src_image()
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
constexpr SkPMColor4f SK_PMColor4fWHITE
Definition: SkColorData.h:380
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorYELLOW
Definition: SkColor.h:139
constexpr SkColor SK_ColorMAGENTA
Definition: SkColor.h:147
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorDKGRAY
Definition: SkColor.h:108
static constexpr GrSamplerState::WrapMode SkTileModeToWrapMode(SkTileMode tileMode)
Definition: SkGr.h:77
SkTileMode
Definition: SkTileMode.h:13
static constexpr int kSkTileModeCount
Definition: SkTileMode.h:39
constexpr int kPad
const GrCaps * caps() const
static std::unique_ptr< GrFragmentProcessor > ModulateRGBA(std::unique_ptr< GrFragmentProcessor > child, const SkPMColor4f &color)
std::unique_ptr< skgpu::ganesh::SurfaceFillContext > makeSFC(GrImageInfo, std::string_view label, SkBackingFit=SkBackingFit::kExact, int sampleCount=1, skgpu::Mipmapped=skgpu::Mipmapped::kNo, skgpu::Protected=skgpu::Protected::kNo, GrSurfaceOrigin=kTopLeft_GrSurfaceOrigin, skgpu::Budgeted=skgpu::Budgeted::kYes)
GrRecordingContextPriv priv()
static const GrStyle & SimpleHairline()
Definition: GrStyle.h:39
static std::unique_ptr< GrFragmentProcessor > MakeSubset(GrSurfaceProxyView, SkAlphaType, const SkMatrix &, GrSamplerState, const SkRect &subset, const GrCaps &caps, const float border[4]=kDefaultBorder, bool alwaysUseShaderTileMode=false)
static std::unique_ptr< GrFragmentProcessor > Make(GrSurfaceProxyView, SkAlphaType, const SkMatrix &=SkMatrix::I(), GrSamplerState::Filter=GrSamplerState::Filter::kNearest, GrSamplerState::MipmapMode mipmapMode=GrSamplerState::MipmapMode::kNone)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
static constexpr char kErrorMsg_DrawSkippedGpuOnly[]
Definition: gm.h:127
const Paint & paint
Definition: color_source.cc:38
float SkScalar
Definition: extension.cpp:12
static bool b
GAsyncResult * result
double y
double x
std::unique_ptr< skgpu::ganesh::SurfaceDrawContext > GaussianBlur(GrRecordingContext *rContext, GrSurfaceProxyView srcView, GrColorType srcColorType, SkAlphaType srcAlphaType, sk_sp< SkColorSpace > colorSpace, SkIRect dstBounds, SkIRect srcBounds, float sigmaX, float sigmaY, SkTileMode mode, SkBackingFit fit)
Optional< SkRect > bounds
Definition: SkRecords.h:189
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
const uint32_t fp
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
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 keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SurfaceDrawContext * TopDeviceSurfaceDrawContext(const SkCanvas *canvas)
Definition: GrCanvas.cpp:20
std::tuple< GrSurfaceProxyView, GrColorType > AsView(GrRecordingContext *rContext, const SkImage *img, skgpu::Mipmapped mipmapped, GrImageTexGenPolicy policy)
static constexpr float kMaxLinearBlurSigma
Definition: BlurUtils.h:36
int BlurSigmaRadius(float sigma)
Definition: BlurUtils.h:33
static DrawResult do_very_large_blur_gm(GrRecordingContext *rContext, SkCanvas *canvas, SkString *errorMsg, GrSurfaceProxyView src, SkIRect srcB)
static GM::DrawResult run(GrRecordingContext *rContext, SkCanvas *canvas, SkString *errorMsg, bool subsetSrc, bool ref)
DEF_SIMPLE_GPU_GM_CAN_FAIL(clear_swizzle, rContext, canvas, errorMsg, 6 *kSize, 2 *kSize)
static bool constexpr kShowSlowRefImages
DrawResult
Definition: gm.h:104
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition: SkVx.h:706
SkScalar w
SkScalar h
SeparatedVector2 offset
Definition: SkRect.h:32
constexpr int32_t x() const
Definition: SkRect.h:141
SkIRect makeOutset(int32_t dx, int32_t dy) const
Definition: SkRect.h:350
constexpr int32_t y() const
Definition: SkRect.h:148
constexpr SkISize size() const
Definition: SkRect.h:172
constexpr int32_t height() const
Definition: SkRect.h:165
static constexpr SkIRect MakeSize(const SkISize &size)
Definition: SkRect.h:66
constexpr int32_t width() const
Definition: SkRect.h:158
constexpr SkIRect makeOffset(int32_t dx, int32_t dy) const
Definition: SkRect.h:300
constexpr SkIPoint topLeft() const
Definition: SkRect.h:151
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
void outset(int32_t dx, int32_t dy)
Definition: SkRect.h:428
static constexpr SkIRect MakePtSize(SkIPoint pt, SkISize size)
Definition: SkRect.h:78
Definition: SkSize.h:16
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
constexpr float y() const
Definition: SkPoint_impl.h:187
constexpr float x() const
Definition: SkPoint_impl.h:181
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
SkRect makeOutset(float dx, float dy) const
Definition: SkRect.h:1002