Flutter Engine
The Flutter Engine
drawimageset.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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"
19#include "include/core/SkRect.h"
23#include "include/core/SkSize.h"
30#include "tools/GpuToolUtils.h"
31#include "tools/ToolUtils.h"
32
33#include <algorithm>
34#include <initializer_list>
35#include <utility>
36
37// Makes a set of m x n tiled images to be drawn with SkCanvas::experimental_drawImageSetV1().
38static void make_image_tiles(int tileW, int tileH, int m, int n, const SkColor colors[4],
40 const int w = tileW * m;
41 const int h = tileH * n;
42 auto surf = SkSurfaces::Raster(
44 surf->getCanvas()->clear(bgColor);
45
46 static constexpr SkScalar kStripeW = 10;
47 static constexpr SkScalar kStripeSpacing = 30;
49
50 SkPoint pts1[] = {{0.f, 0.f}, {(SkScalar)w, (SkScalar)h}};
51 auto grad = SkGradientShader::MakeLinear(pts1, colors, nullptr, 2, SkTileMode::kClamp);
52 paint.setShader(std::move(grad));
53 paint.setAntiAlias(true);
55 paint.setStrokeWidth(kStripeW);
56 SkPoint stripePts[] = {{-w - kStripeW, -kStripeW}, {kStripeW, h + kStripeW}};
57 while (stripePts[0].fX <= w) {
58 surf->getCanvas()->drawPoints(SkCanvas::kLines_PointMode, 2, stripePts, paint);
59 stripePts[0].fX += kStripeSpacing;
60 stripePts[1].fX += kStripeSpacing;
61 }
62
63 SkPoint pts2[] = {{0.f, (SkScalar)h}, {(SkScalar)w, 0.f}};
64 grad = SkGradientShader::MakeLinear(pts2, colors + 2, nullptr, 2, SkTileMode::kClamp);
65 paint.setShader(std::move(grad));
66 paint.setBlendMode(SkBlendMode::kMultiply);
67 stripePts[0] = {-w - kStripeW, h + kStripeW};
68 stripePts[1] = {kStripeW, -kStripeW};
69 while (stripePts[0].fX <= w) {
70 surf->getCanvas()->drawPoints(SkCanvas::kLines_PointMode, 2, stripePts, paint);
71 stripePts[0].fX += kStripeSpacing;
72 stripePts[1].fX += kStripeSpacing;
73 }
74 auto fullImage = surf->makeImageSnapshot();
75 for (int y = 0; y < n; ++y) {
76 for (int x = 0; x < m; ++x) {
77 // Images will have 1 pixel of overlap at interior seams for filtering continuity.
78 SkIRect subset = SkIRect::MakeXYWH(x * tileW - 1, y * tileH - 1, tileW + 2, tileH + 2);
79 set[y * m + x].fAAFlags = SkCanvas::kNone_QuadAAFlags;
80 if (x == 0) {
81 subset.fLeft = 0;
82 set[y * m + x].fAAFlags |= SkCanvas::kLeft_QuadAAFlag;
83 }
84 if (x == m - 1) {
85 subset.fRight = w;
86 set[y * m + x].fAAFlags |= SkCanvas::kRight_QuadAAFlag;
87 }
88 if (y == 0) {
89 subset.fTop = 0;
90 set[y * m + x].fAAFlags |= SkCanvas::kTop_QuadAAFlag;
91 }
92 if (y == n - 1) {
93 subset.fBottom = h;
94 set[y * m + x].fAAFlags |= SkCanvas::kBottom_QuadAAFlag;
95 }
96 set[y * m + x].fImage = fullImage->makeSubset(nullptr, subset);
97 set[y * m + x].fSrcRect =
98 SkRect::MakeXYWH(x == 0 ? 0 : 1, y == 0 ? 0 : 1, tileW, tileH);
99 set[y * m + x].fDstRect = SkRect::MakeXYWH(x * tileW, y * tileH, tileW, tileH);
100 set[y * m + x].fAlpha = 1.f;
101 SkASSERT(set[y * m + x].fImage);
102 }
103 }
104}
105
106namespace skiagm {
107
108class DrawImageSetGM : public GM {
109private:
110 SkString getName() const override { return SkString("draw_image_set"); }
111 SkISize getISize() override { return {1000, 725}; }
112 void onOnceBeforeDraw() override {
113 static constexpr SkColor kColors[] = {SK_ColorCYAN, SK_ColorBLACK,
115 make_image_tiles(kTileW, kTileH, kM, kN, kColors, fSet);
116 }
117
118 void onDraw(SkCanvas* canvas) override {
119 SkScalar d = SkVector{kM * kTileW, kN * kTileH}.length();
120 SkMatrix matrices[4];
121 // rotation
122 matrices[0].setRotate(30);
123 matrices[0].postTranslate(d / 3, 0);
124 // perespective
125 SkPoint src[4];
126 SkRect::MakeWH(kM * kTileW, kN * kTileH).toQuad(src);
127 SkPoint dst[4] = {{0, 0},
128 {kM * kTileW + 10.f, -5.f},
129 {kM * kTileW - 28.f, kN * kTileH + 40.f},
130 {45.f, kN * kTileH - 25.f}};
131 SkAssertResult(matrices[1].setPolyToPoly(src, dst, 4));
132 matrices[1].postTranslate(d, 50.f);
133 // skew
134 matrices[2].setRotate(-60.f);
135 matrices[2].postSkew(0.5f, -1.15f);
136 matrices[2].postScale(0.6f, 1.05f);
137 matrices[2].postTranslate(d, 2.6f * d);
138 // perspective + mirror in x.
139 dst[1] = {-.25 * kM * kTileW, 0};
140 dst[0] = {5.f / 4.f * kM * kTileW, 0};
141 dst[3] = {2.f / 3.f * kM * kTileW, 1 / 2.f * kN * kTileH};
142 dst[2] = {1.f / 3.f * kM * kTileW, 1 / 2.f * kN * kTileH - 0.1f * kTileH};
143 SkAssertResult(matrices[3].setPolyToPoly(src, dst, 4));
144 matrices[3].postTranslate(100.f, d);
146 SkPaint setPaint;
149
150 for (size_t m = 0; m < std::size(matrices); ++m) {
151 // Draw grid of red lines at interior tile boundaries.
152 static constexpr SkScalar kLineOutset = 10.f;
154 paint.setAntiAlias(true);
155 paint.setColor(SK_ColorRED);
157 paint.setStrokeWidth(0.f);
158 for (int x = 1; x < kM; ++x) {
159 SkPoint pts[] = {{x * kTileW, 0}, {x * kTileW, kN * kTileH}};
160 matrices[m].mapPoints(pts, 2);
161 SkVector v = pts[1] - pts[0];
162 v.setLength(v.length() + kLineOutset);
163 canvas->drawLine(pts[1] - v, pts[0] + v, paint);
164 }
165 for (int y = 1; y < kN; ++y) {
166 SkPoint pts[] = {{0, y * kTileH}, {kTileW * kM, y * kTileH}};
167 matrices[m].mapPoints(pts, 2);
168 SkVector v = pts[1] - pts[0];
169 v.setLength(v.length() + kLineOutset);
170 canvas->drawLine(pts[1] - v, pts[0] + v, paint);
171 }
172 canvas->save();
173 canvas->concat(matrices[m]);
174 canvas->experimental_DrawEdgeAAImageSet(fSet, kM * kN, nullptr, nullptr, sampling,
175 &setPaint,
177 canvas->restore();
178 }
179 // A more exotic case with an unusual blend mode, mixed aa flags set, and alpha,
180 // subsets the image. And another with all the above plus a color filter.
182 entry.fSrcRect = SkRect::MakeWH(kTileW, kTileH).makeInset(kTileW / 4.f, kTileH / 4.f);
183 entry.fDstRect = SkRect::MakeWH(1.5 * kTileW, 1.5 * kTileH).makeOffset(d / 4, 2 * d);
184 entry.fImage = fSet[0].fImage;
185 entry.fAlpha = 0.7f;
187 canvas->save();
188 canvas->rotate(3.f);
189
191 canvas->experimental_DrawEdgeAAImageSet(&entry, 1, nullptr, nullptr, sampling,
193 canvas->translate(entry.fDstRect.width() + 8.f, 0);
194 SkPaint cfPaint = setPaint;
196 canvas->experimental_DrawEdgeAAImageSet(&entry, 1, nullptr, nullptr, sampling,
198 canvas->restore();
199 canvas->translate(2 * d, 0);
200 }
201 }
202 inline static constexpr int kM = 4;
203 inline static constexpr int kN = 3;
204 inline static constexpr SkScalar kTileW = 30;
205 inline static constexpr SkScalar kTileH = 60;
206 SkCanvas::ImageSetEntry fSet[kM * kN];
207};
208
209// This GM exercises rect-stays-rect type matrices to test that filtering and antialiasing are not
210// incorrectly disabled.
212private:
213 SkString getName() const override { return SkString("draw_image_set_rect_to_rect"); }
214 SkISize getISize() override { return {1250, 850}; }
215 void onOnceBeforeDraw() override {
216 static constexpr SkColor kColors[] = {SK_ColorBLUE, SK_ColorWHITE,
218 make_image_tiles(kTileW, kTileH, kM, kN, kColors, fSet);
219 }
220
221 void onDraw(SkCanvas* canvas) override {
223 static constexpr SkScalar kW = kM * kTileW;
224 static constexpr SkScalar kH = kN * kTileH;
225 SkMatrix matrices[5];
226 // Identity
227 matrices[0].reset();
228 // 90 degree rotation
229 matrices[1].setRotate(90, kW / 2.f, kH / 2.f);
230 // Scaling
231 matrices[2].setScale(2.f, 0.5f);
232 // Mirror in x and y
233 matrices[3].setScale(-1.f, -1.f);
234 matrices[3].postTranslate(kW, kH);
235 // Mirror in y, rotate, and scale.
236 matrices[4].setScale(1.f, -1.f);
237 matrices[4].postTranslate(0, kH);
238 matrices[4].postRotate(90, kW / 2.f, kH / 2.f);
239 matrices[4].postScale(2.f, 0.5f);
240
242 paint.setBlendMode(SkBlendMode::kSrcOver);
243
244 static constexpr SkScalar kTranslate = std::max(kW, kH) * 2.f + 10.f;
245 canvas->translate(5.f, 5.f);
246 canvas->save();
247 for (SkScalar frac : {0.f, 0.5f}) {
248 canvas->save();
249 canvas->translate(frac, frac);
250 for (size_t m = 0; m < std::size(matrices); ++m) {
251 canvas->save();
252 canvas->concat(matrices[m]);
253 canvas->experimental_DrawEdgeAAImageSet(fSet, kM * kN, nullptr, nullptr,
256 canvas->restore();
257 canvas->translate(kTranslate, 0);
258 }
259 canvas->restore();
260 canvas->restore();
261 canvas->translate(0, kTranslate);
262 canvas->save();
263 }
264 for (SkVector scale : {SkVector{2.f, 0.5f}, SkVector{0.5, 2.f}}) {
265 SkCanvas::ImageSetEntry scaledSet[kM * kN];
266 std::copy_n(fSet, kM * kN, scaledSet);
267 for (int i = 0; i < kM * kN; ++i) {
268 scaledSet[i].fDstRect.fLeft *= scale.fX;
269 scaledSet[i].fDstRect.fTop *= scale.fY;
270 scaledSet[i].fDstRect.fRight *= scale.fX;
271 scaledSet[i].fDstRect.fBottom *= scale.fY;
272 scaledSet[i].fAlpha = 0 == (i % 3) ? 0.4f : 1.f;
273 }
274 for (size_t m = 0; m < std::size(matrices); ++m) {
275 canvas->save();
276 canvas->concat(matrices[m]);
277 canvas->experimental_DrawEdgeAAImageSet(scaledSet, kM * kN, nullptr, nullptr,
280 canvas->restore();
281 canvas->translate(kTranslate, 0);
282 }
283 canvas->restore();
284 canvas->translate(0, kTranslate);
285 canvas->save();
286 }
287 }
288 inline static constexpr int kM = 2;
289 inline static constexpr int kN = 2;
290 inline static constexpr int kTileW = 40;
291 inline static constexpr int kTileH = 50;
292 SkCanvas::ImageSetEntry fSet[kM * kN];
293};
294
295// This GM exercises alpha-only and color textures being combined correctly with the paint's color.
297private:
298 SkString getName() const override { return SkString("draw_image_set_alpha_only"); }
299 SkISize getISize() override { return {kM * kTileW, 2 * kN * kTileH}; }
300
301 DrawResult onGpuSetup(SkCanvas* canvas, SkString*, GraphiteTestContext*) override {
302 auto direct = GrAsDirectContext(canvas->recordingContext());
303#if defined(SK_GRAPHITE)
304 auto recorder = canvas->recorder();
305#endif
306 static constexpr SkColor kColors[] = {SK_ColorBLUE, SK_ColorTRANSPARENT,
308 static constexpr SkColor kBGColor = SkColorSetARGB(128, 128, 128, 128);
309 make_image_tiles(kTileW, kTileH, kM, kN, kColors, fSet, kBGColor);
310
311 // Modify the alpha of the entries, decreasing by column, and convert even rows to
312 // alpha-only textures.
314 for (int y = 0; y < kN; ++y) {
315 for (int x = 0; x < kM; ++x) {
316 int i = y * kM + x;
317 fSet[i].fAlpha = (kM - x) / (float) kM;
318 if (y % 2 == 0) {
319#if defined(SK_GRAPHITE)
320 if (recorder) {
322 recorder, kAlpha_8_SkColorType, alphaSpace, {});
323 } else
324#endif
325 {
327 direct, kAlpha_8_SkColorType, alphaSpace);
328 }
329 }
330 }
331 }
333 }
334
335 void onDraw(SkCanvas* canvas) override {
337
339 paint.setBlendMode(SkBlendMode::kSrcOver);
340 paint.setColor4f({0.2f, 0.8f, 0.4f, 1.f}); // colorizes even rows, no effect on odd rows
341
342 // Top rows use experimental edge set API
343 canvas->experimental_DrawEdgeAAImageSet(fSet, kM * kN, nullptr, nullptr,
346
347 canvas->translate(0.f, kN * kTileH);
348
349 // Bottom rows draw each image from the set using the regular API
350 for (int y = 0; y < kN; ++y) {
351 for (int x = 0; x < kM; ++x) {
352 int i = y * kM + x;
353 SkPaint entryPaint = paint;
354 entryPaint.setAlphaf(fSet[i].fAlpha * paint.getAlphaf());
355 sk_sp<SkImage> orig = sk_ref_sp(const_cast<SkImage*>(fSet[i].fImage.get()));
356 canvas->drawImageRect(ToolUtils::MakeTextureImage(canvas, std::move(orig)),
357 fSet[i].fSrcRect, fSet[i].fDstRect,
358 SkSamplingOptions(), &entryPaint,
360 }
361 }
362 }
363
364 inline static constexpr int kM = 4;
365 inline static constexpr int kN = 4;
366 inline static constexpr int kTileW = 50;
367 inline static constexpr int kTileH = 50;
368 SkCanvas::ImageSetEntry fSet[kM * kN];
369};
370
371DEF_GM(return new DrawImageSetGM();)
372DEF_GM(return new DrawImageSetRectToRectGM();)
373DEF_GM(return new DrawImageSetAlphaOnlyGM();)
374
375} // namespace skiagm
static const SkColor bgColor
Definition: BlurTest.cpp:59
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kExclusion
rc = s + d - two(s*d), ra = kSrcOver
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kSrcOver
r = s + (1-sa)*d
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorLTGRAY
Definition: SkColor.h:118
constexpr SkColor SK_ColorMAGENTA
Definition: SkColor.h:147
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorGRAY
Definition: SkColor.h:113
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
constexpr SkColor SK_ColorDKGRAY
Definition: SkColor.h:108
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
constexpr SkColor kBGColor
Definition: aaxfermodes.cpp:36
constexpr int kH
constexpr int kW
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
virtual skgpu::graphite::Recorder * recorder() const
Definition: SkCanvas.cpp:1641
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
Definition: SkCanvas.cpp:2700
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition: SkCanvas.h:1543
void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt, const SkPoint dstClips[], const SkMatrix preViewMatrices[], const SkSamplingOptions &, const SkPaint *paint=nullptr, SrcRectConstraint constraint=kStrict_SrcRectConstraint)
Definition: SkCanvas.cpp:1853
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 concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
@ kLines_PointMode
draw each pair of points as a line segment
Definition: SkCanvas.h:1242
@ kTop_QuadAAFlag
Definition: SkCanvas.h:1660
@ kRight_QuadAAFlag
Definition: SkCanvas.h:1661
@ kLeft_QuadAAFlag
Definition: SkCanvas.h:1659
@ kBottom_QuadAAFlag
Definition: SkCanvas.h:1662
@ kNone_QuadAAFlags
Definition: SkCanvas.h:1664
static sk_sp< SkColorFilter > LinearToSRGBGamma()
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
virtual sk_sp< SkImage > makeColorTypeAndColorSpace(GrDirectContext *direct, SkColorType targetColorType, sk_sp< SkColorSpace > targetCS) const =0
SkMatrix & postTranslate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.cpp:281
SkMatrix & postRotate(SkScalar degrees, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:474
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:360
void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
Definition: SkMatrix.cpp:770
SkMatrix & setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:296
SkMatrix & postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:524
SkMatrix & setRotate(SkScalar degrees, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:452
SkMatrix & reset()
Definition: SkMatrix.cpp:49
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
void setBlendMode(SkBlendMode mode)
Definition: SkPaint.cpp:151
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
void setAlphaf(float a)
Definition: SkPaint.cpp:130
Definition: gm.h:110
const Paint & paint
Definition: color_source.cc:38
static void make_image_tiles(int tileW, int tileH, int m, int n, const SkColor colors[4], SkCanvas::ImageSetEntry set[], const SkColor bgColor=SK_ColorLTGRAY)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
float SkScalar
Definition: extension.cpp:12
static float max(float r, float g, float b)
Definition: hsl.cpp:49
double y
double x
PODArray< SkColor > colors
Definition: SkRecords.h:276
SkSamplingOptions sampling
Definition: SkRecords.h:337
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
void draw_checkerboard(SkCanvas *canvas, SkColor c1, SkColor c2, int size)
Definition: ToolUtils.cpp:174
sk_sp< SkImage > MakeTextureImage(SkCanvas *canvas, sk_sp< SkImage > orig)
const DlColor kColors[]
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
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
dst
Definition: cp.py:12
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
static SkPath scale(const SkPath &path, SkScalar scale)
Definition: patheffects.cpp:68
SkSamplingOptions(SkFilterMode::kLinear))
DrawResult
Definition: gm.h:104
SkScalar w
SkScalar h
sk_sp< const SkImage > fImage
Definition: SkCanvas.h:1681
Definition: SkRect.h:32
int32_t fBottom
larger y-axis bounds
Definition: SkRect.h:36
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
static constexpr SkIRect MakeXYWH(int32_t x, int32_t y, int32_t w, int32_t h)
Definition: SkRect.h:104
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
int32_t fRight
larger x-axis bounds
Definition: SkRect.h:35
Definition: SkSize.h:16
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
bool setLength(float length)
Definition: SkPoint.cpp:30
float fX
x-axis value
Definition: SkPoint_impl.h:164
float length() const
Definition: SkPoint_impl.h:282
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
void toQuad(SkPoint quad[4]) const
Definition: SkRect.cpp:50
constexpr SkRect makeOffset(float dx, float dy) const
Definition: SkRect.h:965
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
SkRect makeInset(float dx, float dy) const
Definition: SkRect.h:987
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
constexpr float width() const
Definition: SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15