blob: 1c70f4e9086876a3c795c125675858d914af6d53 [file] [log] [blame]
Cary Clark8032b982017-07-28 11:04:54 -04001#Topic Canvas
Cary Clark137b8742018-05-30 09:21:49 -04002#Alias Canvas_Reference ##
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clarke4aa3712017-09-15 02:56:12 -04004#Class SkCanvas
5
Cary Clark61313f32018-10-08 14:57:48 -04006#Code
7#Populate
8##
9
Cary Clark8032b982017-07-28 11:04:54 -040010Canvas provides an interface for drawing, and how the drawing is clipped and transformed.
11Canvas contains a stack of Matrix and Clip values.
12
13Canvas and Paint together provide the state to draw into Surface or Device.
Cary Clarkbad5ad72017-08-03 17:14:08 -040014Each Canvas draw call transforms the geometry of the object by the concatenation of all
15Matrix values in the stack. The transformed geometry is clipped by the intersection
16of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing
17state such as Color, Typeface, text size, stroke width, Shader and so on.
Cary Clark8032b982017-07-28 11:04:54 -040018
Herb Derbyefe39bc2018-05-01 17:06:20 -040019To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
20Request Canvas from Surface to obtain the interface to draw.
21Canvas generated by Raster_Surface draws to memory visible to the CPU.
Cary Clark8032b982017-07-28 11:04:54 -040022Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
23
Cary Clarkbad5ad72017-08-03 17:14:08 -040024To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
Cary Clark09d80c02018-10-31 12:14:03 -040025Document based Canvas and other Canvas subclasses reference Device describing the
Cary Clarkbad5ad72017-08-03 17:14:08 -040026destination.
27
Cary Clark8032b982017-07-28 11:04:54 -040028Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
Herb Derbyefe39bc2018-05-01 17:06:20 -040029This approach may be deprecated in the future.
Cary Clark8032b982017-07-28 11:04:54 -040030
Cary Clark09d80c02018-10-31 12:14:03 -040031Canvas may be created directly when no Surface is required; some Canvas methods
32implicitly create Raster_Surface.
Cary Clark8032b982017-07-28 11:04:54 -040033
34# ------------------------------------------------------------------------------
35
Cary Clarka560c472017-11-27 10:44:06 -050036#Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
37 size_t rowBytes,
38 const SkSurfaceProps* props = nullptr)
Cary Clark61313f32018-10-08 14:57:48 -040039#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -050040#Line # creates from SkImageInfo and Pixel_Storage ##
Cary Clark09d80c02018-10-31 12:14:03 -040041#Populate
Cary Clark8032b982017-07-28 11:04:54 -040042
43#Example
44 #Description
45 Allocates a three by three bitmap, clears it to white, and draws a black pixel
46 in the center.
47 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -040048void draw(SkCanvas* ) {
Cary Clarkce101242017-09-01 15:51:02 -040049 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied
Cary Clarkbad5ad72017-08-03 17:14:08 -040050 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row
Cary Clarka560c472017-11-27 10:44:06 -050051 const size_t size = info.computeMinByteSize(); // bytes used by all rows
Cary Clarkbad5ad72017-08-03 17:14:08 -040052 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels
53 SkPMColor* pixels = storage.get(); // get pointer to allocated storage
54 // create a SkCanvas backed by a raster device, and delete it when the
55 // function goes out of scope.
56 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
Cary Clarkce101242017-09-01 15:51:02 -040057 canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clarkbad5ad72017-08-03 17:14:08 -040058 canvas->flush(); // ensure that pixels are cleared
Cary Clarkce101242017-09-01 15:51:02 -040059 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clarkbad5ad72017-08-03 17:14:08 -040060 SkPaint paint; // by default, draws black
61 canvas->drawPoint(1, 1, paint); // draw in the center
62 canvas->flush(); // ensure that point was drawn
63 for (int y = 0; y < info.height(); ++y) {
64 for (int x = 0; x < info.width(); ++x) {
65 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
66 }
67 SkDebugf("\n");
68 }
Cary Clark8032b982017-07-28 11:04:54 -040069}
70 #StdOut
71 ---
72 -x-
73 ---
74 ##
75##
76
Cary Clark8032b982017-07-28 11:04:54 -040077#SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
Cary Clark2ade9972017-11-02 17:49:34 -040078
Cary Clark8032b982017-07-28 11:04:54 -040079##
80
81# ------------------------------------------------------------------------------
82
83#Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
Herb Derbyefe39bc2018-05-01 17:06:20 -040084 size_t rowBytes)
Cary Clark61313f32018-10-08 14:57:48 -040085#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -050086#Line # creates from image data and Pixel_Storage ##
Cary Clark09d80c02018-10-31 12:14:03 -040087#Populate
Cary Clark8032b982017-07-28 11:04:54 -040088
89#Example
90 #Description
91 Allocates a three by three bitmap, clears it to white, and draws a black pixel
92 in the center.
93 ##
94void draw(SkCanvas* ) {
95 const int width = 3;
96 const int height = 3;
Cary Clark77b3f3a2018-11-07 14:59:03 -050097 SkPMColor pixels[height][width]; // allocate a 3 by 3 Premultiplied bitmap on the stack
Cary Clark8032b982017-07-28 11:04:54 -040098 // create a SkCanvas backed by a raster device, and delete it when the
99 // function goes out of scope.
100 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
101 width,
102 height,
Cary Clarkbc5697d2017-10-04 14:31:33 -0400103 pixels[0], // top-left of the bitmap
Cary Clark8032b982017-07-28 11:04:54 -0400104 sizeof(pixels[0])); // byte width of the each row
Cary Clark682c58d2018-05-16 07:07:07 -0400105 // write a Premultiplied value for white into all pixels in the bitmap
Cary Clark8032b982017-07-28 11:04:54 -0400106 canvas->clear(SK_ColorWHITE);
Cary Clarkce101242017-09-01 15:51:02 -0400107 SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400108 SkPaint paint; // by default, draws black
109 canvas->drawPoint(1, 1, paint); // draw in the center
110 canvas->flush(); // ensure that pixels is ready to be read
111 for (int y = 0; y < height; ++y) {
112 for (int x = 0; x < width; ++x) {
113 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
114 }
115 SkDebugf("\n");
116 }
117}
118 #StdOut
119 ---
120 -x-
121 ---
122 ##
123##
124
Cary Clark2ade9972017-11-02 17:49:34 -0400125#SeeAlso MakeRasterDirect SkSurface::MakeRasterDirect SkImageInfo::MakeN32Premul
Cary Clark8032b982017-07-28 11:04:54 -0400126
127##
128
129# ------------------------------------------------------------------------------
130
131#Method SkCanvas()
132
Cary Clarkab2621d2018-01-30 10:08:57 -0500133#Line # creates with no Surface, no dimensions ##
Cary Clark09d80c02018-10-31 12:14:03 -0400134#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400135
136#Example
137
138#Description
139Passes a placeholder to a function that requires one.
140##
141
142#Function
Mike Reed07055a32018-10-23 13:57:46 -0400143static void check_for_rotated_ctm(const SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400144 const SkMatrix& matrix = canvas->getTotalMatrix();
Mike Reed07055a32018-10-23 13:57:46 -0400145 SkDebugf("rect stays rect is %s\n", matrix.rectStaysRect() ? "true" : "false");
Cary Clarkbad5ad72017-08-03 17:14:08 -0400146}
147
Cary Clark8032b982017-07-28 11:04:54 -0400148##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400149void draw(SkCanvas* canvas) {
Mike Reed07055a32018-10-23 13:57:46 -0400150 check_for_rotated_ctm(canvas);
151 canvas->rotate(30);
152 check_for_rotated_ctm(canvas);
153
154 SkCanvas defaultCanvas;
155 check_for_rotated_ctm(&defaultCanvas);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400156}
Cary Clark8032b982017-07-28 11:04:54 -0400157
158 #StdOut
Mike Reed07055a32018-10-23 13:57:46 -0400159 rect stays rect is true
160 rect stays rect is false
161 rect stays rect is true
Cary Clark8032b982017-07-28 11:04:54 -0400162 ##
163##
164
Cary Clark2ade9972017-11-02 17:49:34 -0400165#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400166
167##
168
169# ------------------------------------------------------------------------------
170
Cary Clark73fa9722017-08-29 17:36:51 -0400171#Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -0400172
Cary Clark682c58d2018-05-16 07:07:07 -0400173#Line # creates with no Surface, set dimensions, Surface_Properties ##
Cary Clark09d80c02018-10-31 12:14:03 -0400174#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400175
176#Example
177 SkCanvas canvas(10, 20); // 10 units wide, 20 units high
178 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device
179 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
180
181 #StdOut
182 canvas is empty
183 ##
184##
185
Cary Clark2ade9972017-11-02 17:49:34 -0400186#SeeAlso MakeRasterDirect SkSurfaceProps SkPixelGeometry SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400187
188##
189
190# ------------------------------------------------------------------------------
191
Cary Clark8032b982017-07-28 11:04:54 -0400192#Method explicit SkCanvas(const SkBitmap& bitmap)
193
Cary Clarkab2621d2018-01-30 10:08:57 -0500194#Line # uses existing Bitmap ##
Cary Clark09d80c02018-10-31 12:14:03 -0400195#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400196
197#Example
198#Description
199The actual output depends on the installed fonts.
200##
201 SkBitmap bitmap;
202 // create a bitmap 5 wide and 11 high
203 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
204 SkCanvas canvas(bitmap);
Cary Clarkce101242017-09-01 15:51:02 -0400205 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400206 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
207 if (!canvas.peekPixels(&pixmap)) {
208 SkDebugf("peekPixels should never fail.\n");
209 }
Cary Clarkbc5697d2017-10-04 14:31:33 -0400210 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400211 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400212 SkPaint paint; // by default, draws black, 12 point text
Mike Reed33535cb2019-01-09 11:25:18 -0500213 canvas.drawString("!", 1, 10, SkFont(), paint); // 1 char at baseline (1, 10)
Cary Clark8032b982017-07-28 11:04:54 -0400214 for (int y = 0; y < bitmap.height(); ++y) {
215 for (int x = 0; x < bitmap.width(); ++x) {
216 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
217 }
218 SkDebugf("\n");
219 }
Cary Clark8032b982017-07-28 11:04:54 -0400220##
221
Cary Clark2ade9972017-11-02 17:49:34 -0400222#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400223
224##
225
Cary Clark8032b982017-07-28 11:04:54 -0400226# ------------------------------------------------------------------------------
227
228#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
229
Cary Clarkab2621d2018-01-30 10:08:57 -0500230#Line # uses existing Bitmap and Surface_Properties ##
Cary Clark09d80c02018-10-31 12:14:03 -0400231#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400232
233#Example
234#Description
235The actual output depends on the installed fonts.
236##
237 SkBitmap bitmap;
238 // create a bitmap 5 wide and 11 high
239 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
240 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
Cary Clarkce101242017-09-01 15:51:02 -0400241 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400242 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
243 if (!canvas.peekPixels(&pixmap)) {
244 SkDebugf("peekPixels should never fail.\n");
245 }
Cary Clarkbc5697d2017-10-04 14:31:33 -0400246 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400247 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400248 SkPaint paint; // by default, draws black, 12 point text
Mike Reed33535cb2019-01-09 11:25:18 -0500249 canvas.drawString("!", 1, 10, SkFont(), paint); // 1 char at baseline (1, 10)
Cary Clark8032b982017-07-28 11:04:54 -0400250 for (int y = 0; y < bitmap.height(); ++y) {
251 for (int x = 0; x < bitmap.width(); ++x) {
252 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
253 }
254 SkDebugf("\n");
255 }
Cary Clark8032b982017-07-28 11:04:54 -0400256##
257
Cary Clark2ade9972017-11-02 17:49:34 -0400258#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400259
260##
261
262# ------------------------------------------------------------------------------
263
264#Method virtual ~SkCanvas()
265
Cary Clarkab2621d2018-01-30 10:08:57 -0500266#Line # draws saved Layers, frees resources ##
Cary Clark09d80c02018-10-31 12:14:03 -0400267#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400268
269#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -0400270#Description
Cary Clarkce101242017-09-01 15:51:02 -0400271Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
272drawing surface that blends with the bitmap. When Layer goes out of
Cary Clark09d80c02018-10-31 12:14:03 -0400273scope, Layer destructor is called. The saved Layer is restored, drawing
Cary Clarkbad5ad72017-08-03 17:14:08 -0400274transparent letters.
275##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400276void draw(SkCanvas* canvas) {
277 SkBitmap bitmap;
278 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
279 {
280 SkCanvas offscreen(bitmap);
281 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -0500282 SkFont font(nullptr, 100);
283 offscreen.drawString("ABC", 20, 160, font, paint);
Cary Clarkf05bdda2017-08-24 12:59:48 -0400284 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
285 offscreen.saveLayerAlpha(&layerBounds, 128);
286 offscreen.clear(SK_ColorWHITE);
Mike Reed33535cb2019-01-09 11:25:18 -0500287 offscreen.drawString("DEF", 20, 160, font, paint);
Cary Clarkf05bdda2017-08-24 12:59:48 -0400288 }
289 canvas->drawBitmap(bitmap, 0, 0, nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400290}
Cary Clark8032b982017-07-28 11:04:54 -0400291##
292
Cary Clarkbad5ad72017-08-03 17:14:08 -0400293#SeeAlso State_Stack
Cary Clark8032b982017-07-28 11:04:54 -0400294
295##
296
297# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500298#Subtopic Property
Cary Clark78de7512018-02-07 07:27:09 -0500299#Line # metrics and attributes ##
300##
Cary Clark8032b982017-07-28 11:04:54 -0400301
Cary Clark8032b982017-07-28 11:04:54 -0400302#Method SkImageInfo imageInfo() const
Cary Clark78de7512018-02-07 07:27:09 -0500303#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500304#Line # returns Image_Info for Canvas ##
Cary Clark09d80c02018-10-31 12:14:03 -0400305#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400306
307#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400308 SkCanvas emptyCanvas;
309 SkImageInfo canvasInfo = emptyCanvas.imageInfo();
310 SkImageInfo emptyInfo;
311 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
312
313 #StdOut
314 emptyInfo == canvasInfo
315 ##
Cary Clark8032b982017-07-28 11:04:54 -0400316##
317
Cary Clark2ade9972017-11-02 17:49:34 -0400318#SeeAlso SkImageInfo MakeRasterDirect makeSurface
Cary Clark8032b982017-07-28 11:04:54 -0400319
320##
321
322# ------------------------------------------------------------------------------
323
324#Method bool getProps(SkSurfaceProps* props) const
Cary Clark78de7512018-02-07 07:27:09 -0500325#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500326#Line # copies Surface_Properties if available ##
Cary Clark09d80c02018-10-31 12:14:03 -0400327#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400328
329#Example
330 SkBitmap bitmap;
331 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
332 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
333 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
334 if (!canvas.getProps(&surfaceProps)) {
335 SkDebugf("getProps failed unexpectedly.\n");
336 }
337 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
338
339 #StdOut
340 isRGB:0
341 isRGB:1
342 #StdOut ##
343##
344
Cary Clark2ade9972017-11-02 17:49:34 -0400345#SeeAlso SkSurfaceProps makeSurface
Cary Clark8032b982017-07-28 11:04:54 -0400346
347##
348
349# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500350#Subtopic Utility
Cary Clark78de7512018-02-07 07:27:09 -0500351#Line # rarely called management functions ##
352##
Cary Clark8032b982017-07-28 11:04:54 -0400353
354#Method void flush()
Cary Clark78de7512018-02-07 07:27:09 -0500355#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -0500356#Line # triggers execution of all pending draw operations ##
Cary Clark09d80c02018-10-31 12:14:03 -0400357#Populate
Cary Clark2ade9972017-11-02 17:49:34 -0400358
Cary Clark08895c42018-02-01 09:37:32 -0500359#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400360##
361
Cary Clarkabaffd82018-11-15 08:25:12 -0500362#SeeAlso peekPixels SkSurface::flush GrContext::flush GrContext::abandonContext
Cary Clark8032b982017-07-28 11:04:54 -0400363
364##
365
366# ------------------------------------------------------------------------------
367
368#Method virtual SkISize getBaseLayerSize() const
Cary Clark78de7512018-02-07 07:27:09 -0500369#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500370#Line # returns size of base Layer in global coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -0400371#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400372
373#Example
374 SkBitmap bitmap;
375 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
376 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
377 canvas.clipRect(SkRect::MakeWH(10, 40));
378 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
379 if (clipDeviceBounds.isEmpty()) {
380 SkDebugf("Empty clip bounds is unexpected!\n");
381 }
382 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
383 SkISize baseLayerSize = canvas.getBaseLayerSize();
384 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
385
386 #StdOut
387 clip=10,30
388 size=20,30
389 ##
390##
391
392#ToDo is this the same as the width and height of surface? ##
393
Cary Clark2ade9972017-11-02 17:49:34 -0400394#SeeAlso getDeviceClipBounds
395
Cary Clark8032b982017-07-28 11:04:54 -0400396##
397
398# ------------------------------------------------------------------------------
399
400#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
Cary Clark61313f32018-10-08 14:57:48 -0400401#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -0500402#Line # creates Surface matching SkImageInfo and SkSurfaceProps ##
Cary Clark09d80c02018-10-31 12:14:03 -0400403#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400404
405#Example
406 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
407 SkCanvas* smallCanvas = surface->getCanvas();
408 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
409 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
410 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
411 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
412
413 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -0400414 compatible != nullptr
Cary Clark8032b982017-07-28 11:04:54 -0400415 size = 3, 4
416 ##
417##
418
Cary Clark2ade9972017-11-02 17:49:34 -0400419#SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps
Cary Clark8032b982017-07-28 11:04:54 -0400420
421##
422
423# ------------------------------------------------------------------------------
424
425#Method virtual GrContext* getGrContext()
Cary Clark78de7512018-02-07 07:27:09 -0500426#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500427#Line # returns GPU_Context of the GPU_Surface ##
Cary Clark09d80c02018-10-31 12:14:03 -0400428#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400429
430#Example
431void draw(SkCanvas* canvas) {
432 if (canvas->getGrContext()) {
433 canvas->clear(SK_ColorRED);
434 } else {
435 canvas->clear(SK_ColorBLUE);
436 }
437}
438##
439
440#ToDo fiddle should show both CPU and GPU out ##
441
Herb Derbyefe39bc2018-05-01 17:06:20 -0400442#SeeAlso GrContext
Cary Clark2ade9972017-11-02 17:49:34 -0400443
Cary Clark8032b982017-07-28 11:04:54 -0400444##
445
446# ------------------------------------------------------------------------------
447
Cary Clark73fa9722017-08-29 17:36:51 -0400448#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -0500449#In Utility
450#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500451#Line # returns writable pixel access if available ##
Cary Clark09d80c02018-10-31 12:14:03 -0400452#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400453
454#Example
455void draw(SkCanvas* canvas) {
456 if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
457 canvas->clear(SK_ColorRED);
458 } else {
459 canvas->clear(SK_ColorBLUE);
460 }
461}
462##
463
464#Example
465#Description
Cary Clarkce101242017-09-01 15:51:02 -0400466Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
467Layer to add a large dotted "DEF". Finally blends Layer with the
Herb Derbyefe39bc2018-05-01 17:06:20 -0400468device.
Cary Clark8032b982017-07-28 11:04:54 -0400469
Cary Clarkce101242017-09-01 15:51:02 -0400470The Layer and blended result appear on the CPU and GPU but the large dotted
Cary Clark8032b982017-07-28 11:04:54 -0400471"DEF" appear only on the CPU.
472##
473void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400474 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -0500475 SkFont font(nullptr, 100);
476 canvas->drawString("ABC", 20, 160, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400477 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
478 canvas->saveLayerAlpha(&layerBounds, 128);
479 canvas->clear(SK_ColorWHITE);
Mike Reed33535cb2019-01-09 11:25:18 -0500480 canvas->drawString("DEF", 20, 160, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400481 SkImageInfo imageInfo;
482 size_t rowBytes;
483 SkIPoint origin;
484 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
485 if (access) {
486 int h = imageInfo.height();
487 int v = imageInfo.width();
488 int rowWords = rowBytes / sizeof(uint32_t);
489 for (int y = 0; y < h; ++y) {
490 int newY = (y - h / 2) * 2 + h / 2;
491 if (newY < 0 || newY >= h) {
492 continue;
493 }
494 for (int x = 0; x < v; ++x) {
495 int newX = (x - v / 2) * 2 + v / 2;
496 if (newX < 0 || newX >= v) {
497 continue;
498 }
499 if (access[y * rowWords + x] == SK_ColorBLACK) {
500 access[newY * rowWords + newX] = SK_ColorGRAY;
501 }
502 }
503 }
504
505 }
Cary Clark8032b982017-07-28 11:04:54 -0400506 canvas->restore();
507}
508##
509
510#ToDo there are no callers of this that I can find. Deprecate? ##
511#ToDo fiddle should show both CPU and GPU out ##
512
Cary Clark2ade9972017-11-02 17:49:34 -0400513#SeeAlso SkImageInfo SkPixmap
514
Cary Clark8032b982017-07-28 11:04:54 -0400515##
516
517# ------------------------------------------------------------------------------
518
519#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
Cary Clark78de7512018-02-07 07:27:09 -0500520#In Utility
521#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500522#Line # returns context that tracks Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -0400523#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400524
525#Example
526#Description
527#ToDo ##
528##
529#Function
530 static void DeleteCallback(void*, void* context) {
531 delete (char*) context;
532 }
533
534 class CustomAllocator : public SkRasterHandleAllocator {
535 public:
536 bool allocHandle(const SkImageInfo& info, Rec* rec) override {
537 char* context = new char[4]{'s', 'k', 'i', 'a'};
538 rec->fReleaseProc = DeleteCallback;
539 rec->fReleaseCtx = context;
540 rec->fHandle = context;
541 rec->fPixels = context;
542 rec->fRowBytes = 4;
543 return true;
544 }
545
546 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
547 // apply canvas matrix and clip to custom environment
548 }
549 };
550
551##
552 void draw(SkCanvas* canvas) {
553 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
554 std::unique_ptr<SkCanvas> c2 =
555 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
556 new CustomAllocator()), info);
557 char* context = (char*) c2->accessTopRasterHandle();
558 SkDebugf("context = %.4s\n", context);
559
560 }
561 #StdOut
562 context = skia
563 ##
564 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
565##
566
567#SeeAlso SkRasterHandleAllocator
568
569##
570
571# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500572#Subtopic Pixels
Cary Clark78de7512018-02-07 07:27:09 -0500573#Line # read and write pixel values ##
574##
Cary Clark8032b982017-07-28 11:04:54 -0400575
576#Method bool peekPixels(SkPixmap* pixmap)
Cary Clark78de7512018-02-07 07:27:09 -0500577#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500578#Line # returns if Canvas has direct access to its pixels ##
Cary Clark09d80c02018-10-31 12:14:03 -0400579#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400580
581#Example
582 SkPixmap pixmap;
583 if (canvas->peekPixels(&pixmap)) {
584 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
585 }
586 #StdOut
587 width=256 height=256
588 ##
589##
590
Cary Clark2ade9972017-11-02 17:49:34 -0400591#SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels
592
Cary Clark8032b982017-07-28 11:04:54 -0400593##
594
595# ------------------------------------------------------------------------------
596
597#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
598 int srcX, int srcY)
Cary Clark78de7512018-02-07 07:27:09 -0500599#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500600#Line # copies and converts rectangle of pixels from Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400601
Cary Clark154beea2017-10-26 07:58:48 -0400602Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are
Herb Derbyefe39bc2018-05-01 17:06:20 -0400603ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400604
Cary Clarka560c472017-11-27 10:44:06 -0500605Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
606Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400607Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400608converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400609
Cary Clarkf05bdda2017-08-24 12:59:48 -0400610Pixels are readable when Device is raster, or backed by a GPU.
611Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
612returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500613class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400614
Cary Clarkf05bdda2017-08-24 12:59:48 -0400615The destination pixel storage must be allocated by the caller.
Cary Clark8032b982017-07-28 11:04:54 -0400616
Cary Clark2dc84ad2018-01-26 12:56:22 -0500617Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400618do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400619are copied. dstPixels contents outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400620
621Pass negative values for srcX or srcY to offset pixels across or down destination.
Cary Clark8032b982017-07-28 11:04:54 -0400622
623Does not copy, and returns false if:
624
625#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400626# Source and destination rectangles do not intersect. ##
627# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
628# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400629# dstRowBytes is too small to contain one row of pixels. ##
630##
631
Cary Clark2dc84ad2018-01-26 12:56:22 -0500632#Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400633#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
634#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
Cary Clark5538c132018-06-14 12:28:14 -0400635#Param srcX offset into readable pixels on x-axis; may be negative ##
636#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400637
Cary Clarkbad5ad72017-08-03 17:14:08 -0400638#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400639
640#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400641#Width 64
642#Height 64
643#Description
644 A black circle drawn on a blue background provides an image to copy.
645 readPixels copies one quarter of the canvas into each of the four corners.
Cary Clarka560c472017-11-27 10:44:06 -0500646 The copied quarter circles overdraw the original circle.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400647##
648 canvas->clear(SK_ColorBLUE);
649 SkPaint paint;
650 canvas->drawCircle(32, 32, 28, paint);
651 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
652 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
653 sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
654 for (int x : { 32, -32 } ) {
655 for (int y : { 32, -32 } ) {
656 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
Herb Derbyefe39bc2018-05-01 17:06:20 -0400657 }
Cary Clarkf05bdda2017-08-24 12:59:48 -0400658 }
659 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
660 canvas->drawImage(image, 0, 0);
661##
662
663#Example
Cary Clark8032b982017-07-28 11:04:54 -0400664#Description
Cary Clarkce101242017-09-01 15:51:02 -0400665 Canvas returned by Raster_Surface has Premultiplied pixel values.
666 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400667 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400668 to generate Premultiplied value 0x802B5580. readPixels converts pixel back
669 to Unpremultiplied value 0x8056A9FF, introducing error.
Cary Clark8032b982017-07-28 11:04:54 -0400670##
671 canvas->clear(0x8055aaff);
672 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
673 uint32_t pixel = 0;
674 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
675 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
676 SkDebugf("pixel = %08x\n", pixel);
677 }
678 }
679
680 #StdOut
681 pixel = 802b5580
682 pixel = 8056a9ff
683 ##
684##
685
Cary Clark2ade9972017-11-02 17:49:34 -0400686#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400687
688##
689
690# ------------------------------------------------------------------------------
691
692#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
693
Cary Clark154beea2017-10-26 07:58:48 -0400694Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are
Cary Clarka560c472017-11-27 10:44:06 -0500695ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400696
Cary Clarka560c472017-11-27 10:44:06 -0500697Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
698Destination Rect corners are (0, 0) and (pixmap.width(), pixmap.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400699Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400700converting to pixmap.colorType() and pixmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400701
Cary Clarkf05bdda2017-08-24 12:59:48 -0400702Pixels are readable when Device is raster, or backed by a GPU.
703Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
704returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500705class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400706
Cary Clark6fc50412017-09-21 12:31:06 -0400707Caller must allocate pixel storage in pixmap if needed.
Cary Clark8032b982017-07-28 11:04:54 -0400708
Cary Clark2dc84ad2018-01-26 12:56:22 -0500709Pixel values are converted only if Color_Type and Alpha_Type
Cary Clark154beea2017-10-26 07:58:48 -0400710do not match. Only pixels within both source and destination Rects
711are copied. pixmap pixels contents outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400712
713Pass negative values for srcX or srcY to offset pixels across or down pixmap.
Cary Clark8032b982017-07-28 11:04:54 -0400714
715Does not copy, and returns false if:
716
717#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400718# Source and destination rectangles do not intersect. ##
719# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
720# Canvas pixels are not readable; for instance, Canvas is document-based. ##
721# Pixmap pixels could not be allocated. ##
722# pixmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -0400723##
724
Cary Clarkbad5ad72017-08-03 17:14:08 -0400725#Param pixmap storage for pixels copied from Canvas ##
Cary Clark5538c132018-06-14 12:28:14 -0400726#Param srcX offset into readable pixels on x-axis; may be negative ##
727#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400728
Cary Clarkbad5ad72017-08-03 17:14:08 -0400729#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400730
731#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400732 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400733 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400734 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400735 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400736 ##
737 void draw(SkCanvas* canvas) {
738 canvas->clear(0x8055aaff);
739 uint32_t pixels[1] = { 0 };
740 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
741 canvas->readPixels(pixmap, 0, 0);
742 SkDebugf("pixel = %08x\n", pixels[0]);
743 }
Cary Clark8032b982017-07-28 11:04:54 -0400744 #StdOut
745 pixel = 802b5580
746 ##
747##
748
Cary Clark2ade9972017-11-02 17:49:34 -0400749#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400750
751##
752
753# ------------------------------------------------------------------------------
754
755#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
756
Cary Clark154beea2017-10-26 07:58:48 -0400757Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are
Cary Clarka560c472017-11-27 10:44:06 -0500758ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400759
Cary Clarka560c472017-11-27 10:44:06 -0500760Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
Cary Clark154beea2017-10-26 07:58:48 -0400761Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clarkf05bdda2017-08-24 12:59:48 -0400762Copies each readable pixel intersecting both rectangles, without scaling,
763converting to bitmap.colorType() and bitmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400764
Cary Clarkf05bdda2017-08-24 12:59:48 -0400765Pixels are readable when Device is raster, or backed by a GPU.
766Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
767returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500768class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400769
Cary Clark6fc50412017-09-21 12:31:06 -0400770Caller must allocate pixel storage in bitmap if needed.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400771
Cary Clark2dc84ad2018-01-26 12:56:22 -0500772Bitmap values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400773do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400774are copied. Bitmap pixels outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400775
776Pass negative values for srcX or srcY to offset pixels across or down bitmap.
Cary Clark8032b982017-07-28 11:04:54 -0400777
778Does not copy, and returns false if:
779
780#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400781# Source and destination rectangles do not intersect. ##
782# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
783# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400784# bitmap pixels could not be allocated. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400785# bitmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -0400786##
787
Cary Clarkbad5ad72017-08-03 17:14:08 -0400788#Param bitmap storage for pixels copied from Canvas ##
Cary Clark5538c132018-06-14 12:28:14 -0400789#Param srcX offset into readable pixels on x-axis; may be negative ##
790#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400791
Cary Clarkbad5ad72017-08-03 17:14:08 -0400792#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400793
794#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400795 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400796 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400797 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400798 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400799 ##
Cary Clark8032b982017-07-28 11:04:54 -0400800void draw(SkCanvas* canvas) {
801 canvas->clear(0x8055aaff);
802 SkBitmap bitmap;
803 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
804 canvas->readPixels(bitmap, 0, 0);
805 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
806}
807 #StdOut
808 pixel = 802b5580
809 ##
810##
811
Cary Clark2ade9972017-11-02 17:49:34 -0400812#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400813
814##
815
816# ------------------------------------------------------------------------------
817
818#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
Cary Clark78de7512018-02-07 07:27:09 -0500819#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500820#Line # copies and converts rectangle of pixels to Canvas ##
Cary Clark154beea2017-10-26 07:58:48 -0400821Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
822Source Rect corners are (0, 0) and (info.width(), info.height()).
823Destination Rect corners are (x, y) and
824(imageInfo().width(), imageInfo().height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400825
826Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clark154beea2017-10-26 07:58:48 -0400827converting to imageInfo().colorType() and imageInfo().alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400828
Cary Clarkf05bdda2017-08-24 12:59:48 -0400829Pixels are writable when Device is raster, or backed by a GPU.
830Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
831returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500832class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400833
Cary Clark2dc84ad2018-01-26 12:56:22 -0500834Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400835do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400836are copied. Canvas pixels outside Rect intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -0400837
Cary Clarkf05bdda2017-08-24 12:59:48 -0400838Pass negative values for x or y to offset pixels to the left or
839above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400840
841Does not copy, and returns false if:
842
843#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400844# Source and destination rectangles do not intersect. ##
Cary Clarkac47b882018-01-11 10:35:44 -0500845# pixels could not be converted to Canvas imageInfo().colorType() or
846 imageInfo().alphaType(). ##
Cary Clark8032b982017-07-28 11:04:54 -0400847# Canvas pixels are not writable; for instance, Canvas is document-based. ##
848# rowBytes is too small to contain one row of pixels. ##
849##
850
Cary Clark2dc84ad2018-01-26 12:56:22 -0500851#Param info width, height, Color_Type, and Alpha_Type of pixels ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400852#Param pixels pixels to copy, of size info.height() times rowBytes, or larger ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400853#Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ##
Cary Clark5538c132018-06-14 12:28:14 -0400854#Param x offset into Canvas writable pixels on x-axis; may be negative ##
855#Param y offset into Canvas writable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400856
Cary Clarkbad5ad72017-08-03 17:14:08 -0400857#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400858
859#Example
860 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
861 for (int y = 0; y < 256; ++y) {
862 uint32_t pixels[256];
863 for (int x = 0; x < 256; ++x) {
864 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
865 }
866 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
867 }
868##
869
Cary Clark2ade9972017-11-02 17:49:34 -0400870#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -0400871
872##
873
874# ------------------------------------------------------------------------------
875
876#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
877
Cary Clark154beea2017-10-26 07:58:48 -0400878Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
879Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400880
Cary Clark154beea2017-10-26 07:58:48 -0400881Destination Rect corners are (x, y) and
882(imageInfo().width(), imageInfo().height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400883
884Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clark154beea2017-10-26 07:58:48 -0400885converting to imageInfo().colorType() and imageInfo().alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400886
Cary Clarkf05bdda2017-08-24 12:59:48 -0400887Pixels are writable when Device is raster, or backed by a GPU.
888Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
889returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500890class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400891
Cary Clark2dc84ad2018-01-26 12:56:22 -0500892Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400893do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400894are copied. Canvas pixels outside Rect intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -0400895
Cary Clarkf05bdda2017-08-24 12:59:48 -0400896Pass negative values for x or y to offset pixels to the left or
897above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400898
899Does not copy, and returns false if:
900
901#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400902# Source and destination rectangles do not intersect. ##
Cary Clark8032b982017-07-28 11:04:54 -0400903# bitmap does not have allocated pixels. ##
Cary Clarkac47b882018-01-11 10:35:44 -0500904# bitmap pixels could not be converted to Canvas imageInfo().colorType() or
905 imageInfo().alphaType(). ##
Cary Clarkce101242017-09-01 15:51:02 -0400906# Canvas pixels are not writable; for instance, Canvas is document based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400907# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
908##
909
Cary Clarkbad5ad72017-08-03 17:14:08 -0400910#Param bitmap contains pixels copied to Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400911#Param x offset into Canvas writable pixels in x; may be negative ##
912#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400913
Cary Clarkbad5ad72017-08-03 17:14:08 -0400914#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400915
916#Example
917void draw(SkCanvas* canvas) {
918 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
919 SkBitmap bitmap;
920 bitmap.setInfo(imageInfo);
921 uint32_t pixels[4];
922 bitmap.setPixels(pixels);
923 for (int y = 0; y < 256; y += 2) {
924 for (int x = 0; x < 256; x += 2) {
925 pixels[0] = SkColorSetRGB(x, y, x | y);
926 pixels[1] = SkColorSetRGB(x ^ y, y, x);
927 pixels[2] = SkColorSetRGB(x, x & y, y);
928 pixels[3] = SkColorSetRGB(~x, ~y, x);
929 canvas->writePixels(bitmap, x, y);
930 }
931 }
932}
933##
934
Cary Clark2ade9972017-11-02 17:49:34 -0400935#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -0400936
937##
938
939# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500940#Subtopic State_Stack
941#Line # stack of state for hierarchical drawing ##
Cary Clark8032b982017-07-28 11:04:54 -0400942
943Canvas maintains a stack of state that allows hierarchical drawing, commonly used
Cary Clarkbad5ad72017-08-03 17:14:08 -0400944to implement windows and views. The initial state has an identity matrix and and
945an infinite clip. Even with a wide-open clip, drawing is constrained by the
946bounds of the Canvas Surface or Device.
Cary Clark8032b982017-07-28 11:04:54 -0400947
Cary Clark939fd6c2018-07-12 08:40:13 -0400948Canvas savable state consists of Clip and Matrix.
Cary Clark8032b982017-07-28 11:04:54 -0400949Clip describes the area that may be drawn to.
950Matrix transforms the geometry.
Cary Clark8032b982017-07-28 11:04:54 -0400951
Mike Reed9a229e92019-01-08 10:52:52 -0500952save(), saveLayer, and saveLayerAlpha
Cary Clark8032b982017-07-28 11:04:54 -0400953save state and return the depth of the stack.
954
Cary Clarkbad5ad72017-08-03 17:14:08 -0400955restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
Cary Clark8032b982017-07-28 11:04:54 -0400956
957Each state on the stack intersects Clip with the previous Clip,
958and concatenates Matrix with the previous Matrix.
959The intersected Clip makes the drawing area the same or smaller;
960the concatenated Matrix may move the origin and potentially scale or rotate
961the coordinate space.
962
963Canvas does not require balancing the state stack but it is a good idea
964to do so. Calling save() without restore() will eventually cause Skia to fail;
965mismatched save() and restore() create hard to find bugs.
966
967It is not possible to use state to draw outside of the clip defined by the
968previous state.
969
970#Example
971#Description
972Draw to ever smaller clips; then restore drawing to full canvas.
973Note that the second clipRect is not permitted to enlarge Clip.
974##
975#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -0400976void draw(SkCanvas* canvas) {
977 SkPaint paint;
Herb Derbyefe39bc2018-05-01 17:06:20 -0400978 canvas->save(); // records stack depth to restore
Cary Clarkbad5ad72017-08-03 17:14:08 -0400979 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
980 canvas->clear(SK_ColorRED); // draws to limit of clip
Herb Derbyefe39bc2018-05-01 17:06:20 -0400981 canvas->save(); // records stack depth to restore
Cary Clarkbad5ad72017-08-03 17:14:08 -0400982 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
983 canvas->clear(SK_ColorBLUE); // draws to smaller clip
984 canvas->restore(); // enlarges clip
985 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
986 canvas->restore(); // enlarges clip
987 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
Cary Clark8032b982017-07-28 11:04:54 -0400988}
Herb Derbyefe39bc2018-05-01 17:06:20 -0400989##
Cary Clark8032b982017-07-28 11:04:54 -0400990
991Each Clip uses the current Matrix for its coordinates.
992
993#Example
994#Description
995While clipRect is given the same rectangle twice, Matrix makes the second
996clipRect draw at half the size of the first.
997##
998#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -0400999void draw(SkCanvas* canvas) {
1000 canvas->clipRect(SkRect::MakeWH(100, 100));
1001 canvas->clear(SK_ColorRED);
1002 canvas->scale(.5, .5);
1003 canvas->clipRect(SkRect::MakeWH(100, 100));
1004 canvas->clear(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001005}
1006##
1007
Mike Reed9a229e92019-01-08 10:52:52 -05001008#SeeAlso save saveLayer saveLayerAlpha restore() restoreToCount
Cary Clark8032b982017-07-28 11:04:54 -04001009
1010#Method int save()
1011
Cary Clarkab2621d2018-01-30 10:08:57 -05001012#In State_Stack
1013#Line # saves Clip and Matrix on stack ##
Cary Clark09d80c02018-10-31 12:14:03 -04001014#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001015
1016#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001017#Description
Cary Clark8032b982017-07-28 11:04:54 -04001018The black square is translated 50 pixels down and to the right.
1019Restoring Canvas state removes translate() from Canvas stack;
1020the red square is not translated, and is drawn at the origin.
1021##
1022#Height 100
1023void draw(SkCanvas* canvas) {
1024 SkPaint paint;
1025 SkRect rect = { 0, 0, 25, 25 };
1026 canvas->drawRect(rect, paint);
1027 canvas->save();
1028 canvas->translate(50, 50);
1029 canvas->drawRect(rect, paint);
1030 canvas->restore();
1031 paint.setColor(SK_ColorRED);
1032 canvas->drawRect(rect, paint);
1033}
1034##
1035
Mike Reed9a229e92019-01-08 10:52:52 -05001036#SeeAlso saveLayer saveLayerAlpha restore restoreToCount
Cary Clark8032b982017-07-28 11:04:54 -04001037
1038##
1039
1040# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001041
1042#Method void restore()
1043
Cary Clarkab2621d2018-01-30 10:08:57 -05001044#In State_Stack
1045#Line # restores changes to Clip and Matrix, pops save stack ##
Cary Clark09d80c02018-10-31 12:14:03 -04001046#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001047
1048#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001049void draw(SkCanvas* canvas) {
1050 SkCanvas simple;
1051 SkDebugf("depth = %d\n", simple.getSaveCount());
1052 simple.restore();
1053 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001054}
1055##
1056
Mike Reed9a229e92019-01-08 10:52:52 -05001057#SeeAlso save saveLayer saveLayerAlpha restoreToCount
Cary Clark2ade9972017-11-02 17:49:34 -04001058
Cary Clark8032b982017-07-28 11:04:54 -04001059##
1060
1061# ------------------------------------------------------------------------------
1062
1063#Method int getSaveCount() const
1064
Cary Clarkab2621d2018-01-30 10:08:57 -05001065#In State_Stack
1066#Line # returns depth of stack containing Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001067#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001068
1069#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001070void draw(SkCanvas* canvas) {
1071 SkCanvas simple;
1072 SkDebugf("depth = %d\n", simple.getSaveCount());
1073 simple.save();
1074 SkDebugf("depth = %d\n", simple.getSaveCount());
1075 simple.restore();
1076 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001077}
1078#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001079depth = 1
1080depth = 2
Cary Clark8032b982017-07-28 11:04:54 -04001081depth = 1
1082##
1083##
1084
Cary Clarka90ea222018-10-16 10:30:28 -04001085#SeeAlso save restore restoreToCount
Cary Clark2ade9972017-11-02 17:49:34 -04001086
Cary Clark8032b982017-07-28 11:04:54 -04001087##
1088
1089# ------------------------------------------------------------------------------
1090
1091#Method void restoreToCount(int saveCount)
1092
Cary Clarkab2621d2018-01-30 10:08:57 -05001093#In State_Stack
1094#Line # restores changes to Clip and Matrix to given depth ##
Cary Clark09d80c02018-10-31 12:14:03 -04001095#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001096
1097#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001098void draw(SkCanvas* canvas) {
1099 SkDebugf("depth = %d\n", canvas->getSaveCount());
1100 canvas->save();
1101 canvas->save();
1102 SkDebugf("depth = %d\n", canvas->getSaveCount());
1103 canvas->restoreToCount(0);
1104 SkDebugf("depth = %d\n", canvas->getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001105}
1106#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001107depth = 1
1108depth = 3
Cary Clark8032b982017-07-28 11:04:54 -04001109depth = 1
1110##
1111##
1112
Cary Clarka90ea222018-10-16 10:30:28 -04001113#SeeAlso restore getSaveCount save
Cary Clark2ade9972017-11-02 17:49:34 -04001114
Cary Clark8032b982017-07-28 11:04:54 -04001115##
1116
Cary Clark08895c42018-02-01 09:37:32 -05001117#Subtopic State_Stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001118
1119# ------------------------------------------------------------------------------
Cary Clarkce101242017-09-01 15:51:02 -04001120
Cary Clark08895c42018-02-01 09:37:32 -05001121#Subtopic Layer
Cary Clarkd0530ba2017-09-14 11:25:39 -04001122#Substitute layer
Cary Clarkce101242017-09-01 15:51:02 -04001123#Alias Layers
Cary Clark137b8742018-05-30 09:21:49 -04001124#Substitute layers
1125##
Cary Clark08895c42018-02-01 09:37:32 -05001126#Line # temporary Bitmap to draw into ##
Cary Clarkce101242017-09-01 15:51:02 -04001127
1128Layer allocates a temporary Bitmap to draw into. When the drawing is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001129complete, the Bitmap is drawn into the Canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001130
1131Layer is saved in a stack along with other saved state. When state with a Layer
1132is restored, the Bitmap is drawn into the previous Layer.
1133
1134Layer may be initialized with the contents of the previous Layer. When Layer is
1135restored, its Bitmap can be modified by Paint passed to Layer to apply
1136Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
1137
1138#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1139
Cary Clarkab2621d2018-01-30 10:08:57 -05001140#In Layer
1141#Line # saves Clip and Matrix on stack; creates Layer ##
Cary Clark09d80c02018-10-31 12:14:03 -04001142#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001143
1144#Example
1145#Description
1146Rectangles are blurred by Image_Filter when restore() draws Layer to main
1147Canvas.
1148##
1149#Height 128
Cary Clark81abc432018-06-25 16:30:08 -04001150#Function
1151###$
1152#include "SkBlurImageFilter.h"
1153$$$#
1154##
1155
Cary Clarkce101242017-09-01 15:51:02 -04001156void draw(SkCanvas* canvas) {
1157 SkPaint paint, blur;
Cary Clarka560c472017-11-27 10:44:06 -05001158 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
Cary Clarkce101242017-09-01 15:51:02 -04001159 canvas->saveLayer(nullptr, &blur);
1160 SkRect rect = { 25, 25, 50, 50};
1161 canvas->drawRect(rect, paint);
1162 canvas->translate(50, 50);
1163 paint.setColor(SK_ColorRED);
1164 canvas->drawRect(rect, paint);
1165 canvas->restore();
1166}
1167##
1168
Mike Reed9a229e92019-01-08 10:52:52 -05001169#SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001170
1171##
1172
Herb Derbyefe39bc2018-05-01 17:06:20 -04001173#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
Cary Clarkce101242017-09-01 15:51:02 -04001174
Cary Clarkab2621d2018-01-30 10:08:57 -05001175#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001176#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001177
1178#Example
1179#Description
1180Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001181The red rectangle is clipped; it does not fully fit on Layer.
Cary Clarkce101242017-09-01 15:51:02 -04001182Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
1183##
1184#Height 128
Cary Clark81abc432018-06-25 16:30:08 -04001185#Function
1186###$
1187#include "SkBlurImageFilter.h"
1188$$$#
1189##
1190
Cary Clarkce101242017-09-01 15:51:02 -04001191void draw(SkCanvas* canvas) {
1192 SkPaint paint, blur;
Cary Clarka560c472017-11-27 10:44:06 -05001193 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
Cary Clarkce101242017-09-01 15:51:02 -04001194 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1195 SkRect rect = { 25, 25, 50, 50};
1196 canvas->drawRect(rect, paint);
1197 canvas->translate(50, 50);
1198 paint.setColor(SK_ColorRED);
1199 canvas->drawRect(rect, paint);
1200 canvas->restore();
1201}
1202##
1203
Mike Reed9a229e92019-01-08 10:52:52 -05001204#SeeAlso save restore saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001205
1206##
1207
1208#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1209
Cary Clarkab2621d2018-01-30 10:08:57 -05001210#In Layer
1211#Line # saves Clip and Matrix on stack; creates Layer; sets opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001212#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001213
1214#Example
1215 SkPaint paint;
1216 paint.setColor(SK_ColorRED);
1217 canvas->drawCircle(50, 50, 50, paint);
1218 canvas->saveLayerAlpha(nullptr, 128);
1219 paint.setColor(SK_ColorBLUE);
1220 canvas->drawCircle(100, 50, 50, paint);
1221 paint.setColor(SK_ColorGREEN);
1222 paint.setAlpha(128);
1223 canvas->drawCircle(75, 90, 50, paint);
1224 canvas->restore();
1225##
1226
Mike Reed9a229e92019-01-08 10:52:52 -05001227#SeeAlso save restore saveLayer SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001228
1229##
1230
Cary Clarkd98f78c2018-04-26 08:32:37 -04001231#Enum SaveLayerFlagsSet
Cary Clark08895c42018-02-01 09:37:32 -05001232#Line # sets SaveLayerRec options ##
Cary Clarkce101242017-09-01 15:51:02 -04001233#Code
Cary Clark61313f32018-10-08 14:57:48 -04001234#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001235##
1236
Cary Clark682c58d2018-05-16 07:07:07 -04001237
1238#Typedef uint32_t SaveLayerFlags
1239#Line # options for SaveLayerRec ##
Cary Clark137b8742018-05-30 09:21:49 -04001240##
Cary Clark682c58d2018-05-16 07:07:07 -04001241
Cary Clarkce101242017-09-01 15:51:02 -04001242SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
Mike Reed9a229e92019-01-08 10:52:52 -05001243defining how Layer allocated by saveLayer operates. It may be set to zero or
1244kInitWithPrevious_SaveLayerFlag.
Cary Clarkce101242017-09-01 15:51:02 -04001245
1246#Const kInitWithPrevious_SaveLayerFlag 4
Cary Clark682c58d2018-05-16 07:07:07 -04001247#Line # initializes with previous contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001248 Initializes Layer with the contents of the previous Layer.
1249##
1250
Cary Clarkce101242017-09-01 15:51:02 -04001251#Example
1252#Height 160
1253#Description
1254Canvas Layer captures red and blue circles scaled up by four.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001255scalePaint blends Layer back with transparency.
Cary Clarkce101242017-09-01 15:51:02 -04001256##
1257void draw(SkCanvas* canvas) {
1258 SkPaint redPaint, bluePaint, scalePaint;
1259 redPaint.setColor(SK_ColorRED);
1260 canvas->drawCircle(21, 21, 8, redPaint);
1261 bluePaint.setColor(SK_ColorBLUE);
1262 canvas->drawCircle(31, 21, 8, bluePaint);
1263 SkMatrix matrix;
1264 matrix.setScale(4, 4);
1265 scalePaint.setAlpha(0x40);
1266 scalePaint.setImageFilter(
1267 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1268 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04001269 SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001270 canvas->saveLayer(saveLayerRec);
1271 canvas->restore();
1272}
1273##
1274
Mike Reed9a229e92019-01-08 10:52:52 -05001275#SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001276
1277#Enum ##
1278
Cary Clark682c58d2018-05-16 07:07:07 -04001279#Subtopic SaveLayerRec
1280#Line # contains the state used to create the Layer ##
Cary Clarka560c472017-11-27 10:44:06 -05001281
Cary Clarkce101242017-09-01 15:51:02 -04001282#Struct SaveLayerRec
Cary Clark08895c42018-02-01 09:37:32 -05001283#Line # contains the state used to create the Layer ##
Cary Clark682c58d2018-05-16 07:07:07 -04001284
Cary Clarkce101242017-09-01 15:51:02 -04001285#Code
Cary Clark61313f32018-10-08 14:57:48 -04001286#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001287##
1288
Cary Clark137b8742018-05-30 09:21:49 -04001289SaveLayerRec contains the state used to create the Layer.
1290
Cary Clarkce101242017-09-01 15:51:02 -04001291#Member const SkRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04001292#Line # hints at Layer size limit ##
Cary Clarkce101242017-09-01 15:51:02 -04001293 fBounds is used as a hint to limit the size of Layer; may be nullptr.
1294 fBounds suggests but does not define Layer size. To clip drawing to
1295 a specific rectangle, use clipRect.
1296##
1297
1298#Member const SkPaint* fPaint
Cary Clark682c58d2018-05-16 07:07:07 -04001299#Line # modifies overlay ##
Cary Clarkce101242017-09-01 15:51:02 -04001300 fPaint modifies how Layer overlays the prior Layer; may be nullptr.
1301 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1302 Mask_Filter affect Layer draw.
1303##
1304
1305#Member const SkImageFilter* fBackdrop
Cary Clark682c58d2018-05-16 07:07:07 -04001306#Line # applies Image_Filter to prior Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001307 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
1308 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1309 prior Layer without an Image_Filter.
1310##
1311
1312#Member const SkImage* fClipMask
Cary Clark682c58d2018-05-16 07:07:07 -04001313#Line # clips Layer with Mask_Alpha ##
Cary Clarkce101242017-09-01 15:51:02 -04001314 restore() clips Layer by the Color_Alpha channel of fClipMask when
1315 Layer is copied to Device. fClipMask may be nullptr. .
1316##
1317
1318#Member const SkMatrix* fClipMatrix
Cary Clark682c58d2018-05-16 07:07:07 -04001319#Line # transforms Mask_Alpha used to clip ##
Herb Derbyefe39bc2018-05-01 17:06:20 -04001320 fClipMatrix transforms fClipMask before it clips Layer. If
Cary Clarkce101242017-09-01 15:51:02 -04001321 fClipMask describes a translucent gradient, it may be scaled and rotated
1322 without introducing artifacts. fClipMatrix may be nullptr.
1323##
1324
1325#Member SaveLayerFlags fSaveLayerFlags
Mike Reed9a229e92019-01-08 10:52:52 -05001326#Line # creates with prior Layer contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001327 fSaveLayerFlags are used to create Layer without transparency,
Mike Reed186669c2019-02-13 14:26:37 -05001328 and to create Layer with the contents of the previous Layer.
Cary Clarkce101242017-09-01 15:51:02 -04001329##
1330
1331#Example
1332#Height 160
1333#Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001334Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled
Cary Clarkce101242017-09-01 15:51:02 -04001335up by four. After drawing another red circle without scaling on top, the Layer is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001336transferred to the main canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001337##
1338void draw(SkCanvas* canvas) {
1339 SkPaint redPaint, bluePaint;
1340 redPaint.setAntiAlias(true);
1341 redPaint.setColor(SK_ColorRED);
1342 canvas->drawCircle(21, 21, 8, redPaint);
1343 bluePaint.setColor(SK_ColorBLUE);
1344 canvas->drawCircle(31, 21, 8, bluePaint);
1345 SkMatrix matrix;
1346 matrix.setScale(4, 4);
1347 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
Herb Derbyefe39bc2018-05-01 17:06:20 -04001348 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
Cary Clarkce101242017-09-01 15:51:02 -04001349 canvas->saveLayer(saveLayerRec);
1350 canvas->drawCircle(125, 85, 8, redPaint);
1351 canvas->restore();
1352}
1353##
1354
Cary Clark61313f32018-10-08 14:57:48 -04001355#Subtopic Constructors
Cary Clark682c58d2018-05-16 07:07:07 -04001356##
Cary Clarkce101242017-09-01 15:51:02 -04001357
Cary Clark682c58d2018-05-16 07:07:07 -04001358#Method SaveLayerRec()
1359#Line # constructs SaveLayerRec ##
Cary Clark09d80c02018-10-31 12:14:03 -04001360#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001361
1362#Example
1363 SkCanvas::SaveLayerRec rec1;
Mike Reed9a229e92019-01-08 10:52:52 -05001364 rec1.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1365 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001366 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1367 && rec1.fPaint == rec2.fPaint
1368 && rec1.fBackdrop == rec2.fBackdrop
1369 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1370 #StdOut
1371 rec1 == rec2
1372 ##
1373##
1374
Mike Reed9a229e92019-01-08 10:52:52 -05001375#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001376
Cary Clarkce101242017-09-01 15:51:02 -04001377##
1378
Cary Clark224c7002018-06-27 11:00:21 -04001379#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
Cary Clark09d80c02018-10-31 12:14:03 -04001380#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001381
1382#Example
1383 SkCanvas::SaveLayerRec rec1;
1384 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1385 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1386 && rec1.fPaint == rec2.fPaint
1387 && rec1.fBackdrop == rec2.fBackdrop
1388 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1389 #StdOut
1390 rec1 == rec2
1391 ##
1392##
1393
Mike Reed9a229e92019-01-08 10:52:52 -05001394#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001395
Cary Clarkce101242017-09-01 15:51:02 -04001396##
1397
1398#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1399 SaveLayerFlags saveLayerFlags)
Cary Clark09d80c02018-10-31 12:14:03 -04001400#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001401
1402#Example
1403 SkCanvas::SaveLayerRec rec1;
1404 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1405 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1406 && rec1.fPaint == rec2.fPaint
1407 && rec1.fBackdrop == rec2.fBackdrop
1408 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1409 #StdOut
1410 rec1 == rec2
1411 ##
1412##
1413
Mike Reed9a229e92019-01-08 10:52:52 -05001414#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001415
Cary Clarkce101242017-09-01 15:51:02 -04001416##
1417
Cary Clarkce101242017-09-01 15:51:02 -04001418#Struct ##
1419
Cary Clark682c58d2018-05-16 07:07:07 -04001420#Subtopic ##
1421
Cary Clarkce101242017-09-01 15:51:02 -04001422#Method int saveLayer(const SaveLayerRec& layerRec)
1423
Cary Clarkab2621d2018-01-30 10:08:57 -05001424#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001425#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001426
1427#Example
1428#Description
1429The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
1430Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
1431Where Layer was cleared, the original image will draw unchanged.
1432Outside of the circle the mandrill is brightened.
1433##
1434 #Image 3
Hal Canaryc465d132017-12-08 10:21:31 -05001435 // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png");
Cary Clarkce101242017-09-01 15:51:02 -04001436 canvas->drawImage(image, 0, 0, nullptr);
1437 SkCanvas::SaveLayerRec rec;
1438 SkPaint paint;
1439 paint.setBlendMode(SkBlendMode::kPlus);
1440 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1441 rec.fPaint = &paint;
1442 canvas->saveLayer(rec);
1443 paint.setBlendMode(SkBlendMode::kClear);
1444 canvas->drawCircle(128, 128, 96, paint);
1445 canvas->restore();
1446##
1447
1448#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
1449
Mike Reed9a229e92019-01-08 10:52:52 -05001450#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001451
Cary Clarkce101242017-09-01 15:51:02 -04001452##
1453
Cary Clark08895c42018-02-01 09:37:32 -05001454#Subtopic Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001455
1456# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001457#Subtopic Matrix
1458#Line # coordinate transformation ##
Cary Clark8032b982017-07-28 11:04:54 -04001459
1460#Method void translate(SkScalar dx, SkScalar dy)
1461
Cary Clarkab2621d2018-01-30 10:08:57 -05001462#In Matrix
1463#Line # translates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001464#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001465
1466#Example
1467#Height 128
1468#Description
1469scale() followed by translate() produces different results from translate() followed
Herb Derbyefe39bc2018-05-01 17:06:20 -04001470by scale().
Cary Clark8032b982017-07-28 11:04:54 -04001471
1472The blue stroke follows translate of (50, 50); a black
Herb Derbyefe39bc2018-05-01 17:06:20 -04001473fill follows scale of (2, 1/2.f). After restoring the clip, which resets
Cary Clark8032b982017-07-28 11:04:54 -04001474Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
1475follows translate of (50, 50).
1476##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001477void draw(SkCanvas* canvas) {
1478 SkPaint filledPaint;
1479 SkPaint outlinePaint;
1480 outlinePaint.setStyle(SkPaint::kStroke_Style);
1481 outlinePaint.setColor(SK_ColorBLUE);
1482 canvas->save();
1483 canvas->translate(50, 50);
1484 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
1485 canvas->scale(2, 1/2.f);
1486 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
1487 canvas->restore();
1488 filledPaint.setColor(SK_ColorGRAY);
1489 outlinePaint.setColor(SK_ColorRED);
1490 canvas->scale(2, 1/2.f);
1491 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
1492 canvas->translate(50, 50);
1493 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04001494}
1495##
1496
Cary Clark2ade9972017-11-02 17:49:34 -04001497#SeeAlso concat() scale() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001498
1499##
1500
1501# ------------------------------------------------------------------------------
1502
1503#Method void scale(SkScalar sx, SkScalar sy)
1504
Cary Clarkab2621d2018-01-30 10:08:57 -05001505#In Matrix
1506#Line # scales Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001507#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001508
1509#Example
1510#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001511void draw(SkCanvas* canvas) {
1512 SkPaint paint;
1513 SkRect rect = { 10, 20, 60, 120 };
1514 canvas->translate(20, 20);
1515 canvas->drawRect(rect, paint);
1516 canvas->scale(2, .5f);
1517 paint.setColor(SK_ColorGRAY);
1518 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001519}
1520##
1521
Cary Clark2ade9972017-11-02 17:49:34 -04001522#SeeAlso concat() translate() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001523
1524##
1525
1526# ------------------------------------------------------------------------------
1527
1528#Method void rotate(SkScalar degrees)
1529
Cary Clarkab2621d2018-01-30 10:08:57 -05001530#In Matrix
1531#Line # rotates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001532#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001533
1534#Example
1535#Description
1536Draw clock hands at time 5:10. The hour hand and minute hand point up and
1537are rotated clockwise.
1538##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001539void draw(SkCanvas* canvas) {
1540 SkPaint paint;
1541 paint.setStyle(SkPaint::kStroke_Style);
1542 canvas->translate(128, 128);
1543 canvas->drawCircle(0, 0, 60, paint);
1544 canvas->save();
1545 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
Herb Derbyefe39bc2018-05-01 17:06:20 -04001546 canvas->drawLine(0, 0, 0, -50, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001547 canvas->restore();
1548 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
1549 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001550}
1551##
1552
Cary Clark2ade9972017-11-02 17:49:34 -04001553#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001554
1555##
1556
1557# ------------------------------------------------------------------------------
1558
1559#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
1560
Cary Clarkab2621d2018-01-30 10:08:57 -05001561#In Matrix
Cary Clark09d80c02018-10-31 12:14:03 -04001562#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001563
1564#Example
1565#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04001566void draw(SkCanvas* canvas) {
1567 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001568 SkFont font(nullptr, 96);
1569 canvas->drawString("A1", 130, 100, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001570 canvas->rotate(180, 130, 100);
Mike Reed33535cb2019-01-09 11:25:18 -05001571 canvas->drawString("A1", 130, 100, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001572}
1573##
1574
Cary Clark2ade9972017-11-02 17:49:34 -04001575#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001576
1577##
1578
1579# ------------------------------------------------------------------------------
1580
1581#Method void skew(SkScalar sx, SkScalar sy)
1582
Cary Clarkab2621d2018-01-30 10:08:57 -05001583#In Matrix
1584#Line # skews Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001585#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04001586
Cary Clark8032b982017-07-28 11:04:54 -04001587#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001588 #Description
Cary Clark5538c132018-06-14 12:28:14 -04001589 Black text mimics an oblique text style by using a negative skew on x-axis
1590 that shifts the geometry to the right as the y-axis values decrease.
1591 Red text uses a positive skew on y-axis to shift the geometry down
1592 as the x-axis values increase.
1593 Blue text combines sx and sy skew to rotate and scale.
Cary Clark8032b982017-07-28 11:04:54 -04001594 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001595 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001596 SkFont font(nullptr, 128);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001597 canvas->translate(30, 130);
1598 canvas->save();
1599 canvas->skew(-.5, 0);
Mike Reed33535cb2019-01-09 11:25:18 -05001600 canvas->drawString("A1", 0, 0, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001601 canvas->restore();
1602 canvas->save();
1603 canvas->skew(0, .5);
1604 paint.setColor(SK_ColorRED);
Mike Reed33535cb2019-01-09 11:25:18 -05001605 canvas->drawString("A1", 0, 0, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001606 canvas->restore();
1607 canvas->skew(-.5, .5);
1608 paint.setColor(SK_ColorBLUE);
Mike Reed33535cb2019-01-09 11:25:18 -05001609 canvas->drawString("A1", 0, 0, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001610##
1611
Cary Clark2ade9972017-11-02 17:49:34 -04001612#SeeAlso concat() translate() rotate() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001613
1614##
1615
1616# ------------------------------------------------------------------------------
1617
1618#Method void concat(const SkMatrix& matrix)
1619
Cary Clarkab2621d2018-01-30 10:08:57 -05001620#In Matrix
1621#Line # multiplies Matrix by Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001622#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001623
1624#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001625void draw(SkCanvas* canvas) {
1626 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001627 SkFont font(nullptr, 80);
1628 font.setScaleX(.3);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001629 SkMatrix matrix;
1630 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
1631 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
1632 canvas->drawRect(rect[0], paint);
1633 canvas->drawRect(rect[1], paint);
1634 paint.setColor(SK_ColorWHITE);
Mike Reed33535cb2019-01-09 11:25:18 -05001635 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001636 canvas->concat(matrix);
Mike Reed33535cb2019-01-09 11:25:18 -05001637 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001638}
1639##
1640
Cary Clark2ade9972017-11-02 17:49:34 -04001641#SeeAlso translate() rotate() scale() skew() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001642
1643##
1644
1645# ------------------------------------------------------------------------------
1646
1647#Method void setMatrix(const SkMatrix& matrix)
1648
Cary Clarkab2621d2018-01-30 10:08:57 -05001649#In Matrix
1650#Line # sets Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001651#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001652
1653#Example
1654#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001655void draw(SkCanvas* canvas) {
1656 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001657 SkFont font;
Cary Clarkbad5ad72017-08-03 17:14:08 -04001658 canvas->scale(4, 6);
Mike Reed33535cb2019-01-09 11:25:18 -05001659 canvas->drawString("truth", 2, 10, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001660 SkMatrix matrix;
1661 matrix.setScale(2.8f, 6);
1662 canvas->setMatrix(matrix);
Mike Reed33535cb2019-01-09 11:25:18 -05001663 canvas->drawString("consequences", 2, 20, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001664}
1665##
1666
Cary Clark2ade9972017-11-02 17:49:34 -04001667#SeeAlso resetMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001668
1669##
1670
1671# ------------------------------------------------------------------------------
1672
1673#Method void resetMatrix()
1674
Cary Clarkab2621d2018-01-30 10:08:57 -05001675#In Matrix
1676#Line # resets Matrix to identity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001677#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001678
1679#Example
1680#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001681void draw(SkCanvas* canvas) {
1682 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001683 SkFont font;
Cary Clarkbad5ad72017-08-03 17:14:08 -04001684 canvas->scale(4, 6);
Mike Reed33535cb2019-01-09 11:25:18 -05001685 canvas->drawString("truth", 2, 10, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001686 canvas->resetMatrix();
1687 canvas->scale(2.8f, 6);
Mike Reed33535cb2019-01-09 11:25:18 -05001688 canvas->drawString("consequences", 2, 20, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001689}
1690##
1691
Cary Clark2ade9972017-11-02 17:49:34 -04001692#SeeAlso setMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001693
1694##
1695
1696# ------------------------------------------------------------------------------
1697
1698#Method const SkMatrix& getTotalMatrix() const
1699
Cary Clarkab2621d2018-01-30 10:08:57 -05001700#In Matrix
1701#Line # returns Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001702#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001703
1704#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001705 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
1706 #StdOut
1707 isIdentity true
1708 ##
Cary Clark8032b982017-07-28 11:04:54 -04001709##
1710
Cary Clark2ade9972017-11-02 17:49:34 -04001711#SeeAlso setMatrix resetMatrix concat()
Cary Clark8032b982017-07-28 11:04:54 -04001712
1713##
1714
Cary Clark08895c42018-02-01 09:37:32 -05001715#Subtopic Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04001716
1717# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001718#Subtopic Clip
1719#Line # stack of clipping Paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001720
1721Clip is built from a stack of clipping paths. Each Path in the
Herb Derbyefe39bc2018-05-01 17:06:20 -04001722stack can be constructed from one or more Path_Contour elements. The
Cary Clark8032b982017-07-28 11:04:54 -04001723Path_Contour may be composed of any number of Path_Verb segments. Each
1724Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
1725by Path_Contour.
1726
1727Clip stack of Path elements successfully restrict the Path area. Each
Herb Derbyefe39bc2018-05-01 17:06:20 -04001728Path is transformed by Matrix, then intersected with or subtracted from the
Cary Clark8032b982017-07-28 11:04:54 -04001729prior Clip to form the replacement Clip. Use SkClipOp::kDifference
1730to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
1731with Clip.
1732
Cary Clarkffb3d682018-05-17 12:17:28 -04001733A clipping Path may be Anti_Aliased; if Path, after transformation, is
1734composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels
Cary Clarkce101242017-09-01 15:51:02 -04001735to either be inside or outside the clip. The fastest drawing has a Aliased,
1736rectangular clip.
Cary Clark8032b982017-07-28 11:04:54 -04001737
Cary Clarkffb3d682018-05-17 12:17:28 -04001738If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring
Herb Derbyefe39bc2018-05-01 17:06:20 -04001739that drawing blend partially with the destination along the edge. A rotated
Cary Clarkffb3d682018-05-17 12:17:28 -04001740rectangular Anti_Aliased clip looks smoother but draws slower.
Cary Clark8032b982017-07-28 11:04:54 -04001741
1742Clip can combine with Rect and Round_Rect primitives; like
1743Path, these are transformed by Matrix before they are combined with Clip.
1744
1745Clip can combine with Region. Region is assumed to be in Device coordinates
1746and is unaffected by Matrix.
1747
1748#Example
1749#Height 90
1750 #Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001751 Draw a red circle with an Aliased clip and an Anti_Aliased clip.
Cary Clark8032b982017-07-28 11:04:54 -04001752 Use an image filter to zoom into the pixels drawn.
Cary Clarkce101242017-09-01 15:51:02 -04001753 The edge of the Aliased clip fully draws pixels in the red circle.
Cary Clarkffb3d682018-05-17 12:17:28 -04001754 The edge of the Anti_Aliased clip partially draws pixels in the red circle.
Cary Clark8032b982017-07-28 11:04:54 -04001755 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001756 SkPaint redPaint, scalePaint;
1757 redPaint.setAntiAlias(true);
1758 redPaint.setColor(SK_ColorRED);
1759 canvas->save();
1760 for (bool antialias : { false, true } ) {
1761 canvas->save();
1762 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
1763 canvas->drawCircle(17, 11, 8, redPaint);
1764 canvas->restore();
1765 canvas->translate(16, 0);
1766 }
1767 canvas->restore();
1768 SkMatrix matrix;
1769 matrix.setScale(6, 6);
1770 scalePaint.setImageFilter(
1771 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1772 SkCanvas::SaveLayerRec saveLayerRec(
Herb Derbyefe39bc2018-05-01 17:06:20 -04001773 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001774 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04001775 canvas->restore();
1776##
1777
1778#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
1779
Cary Clarkab2621d2018-01-30 10:08:57 -05001780#In Clip
1781#Line # combines Clip with Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001782#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001783
1784#Example
1785#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001786void draw(SkCanvas* canvas) {
1787 canvas->rotate(10);
1788 SkPaint paint;
1789 paint.setAntiAlias(true);
1790 for (auto alias: { false, true } ) {
1791 canvas->save();
1792 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
1793 canvas->drawCircle(100, 60, 60, paint);
1794 canvas->restore();
1795 canvas->translate(80, 0);
1796 }
Cary Clark8032b982017-07-28 11:04:54 -04001797}
1798##
1799
Cary Clark2ade9972017-11-02 17:49:34 -04001800#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001801
1802##
1803
Herb Derbyefe39bc2018-05-01 17:06:20 -04001804#Method void clipRect(const SkRect& rect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001805
Cary Clarkab2621d2018-01-30 10:08:57 -05001806#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001807#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001808
1809#Example
1810#Height 192
1811#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04001812void draw(SkCanvas* canvas) {
1813 SkPaint paint;
1814 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
1815 canvas->save();
1816 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
1817 canvas->drawCircle(100, 100, 60, paint);
1818 canvas->restore();
1819 canvas->translate(80, 0);
1820 }
Cary Clark8032b982017-07-28 11:04:54 -04001821}
1822##
1823
Cary Clark2ade9972017-11-02 17:49:34 -04001824#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001825
1826##
1827
Herb Derbyefe39bc2018-05-01 17:06:20 -04001828#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001829
Cary Clarkab2621d2018-01-30 10:08:57 -05001830#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001831#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001832
1833#Example
1834#Height 133
1835 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001836 A circle drawn in pieces looks uniform when drawn Aliased.
Cary Clarkffb3d682018-05-17 12:17:28 -04001837 The same circle pieces blend with pixels more than once when Anti_Aliased,
Cary Clark8032b982017-07-28 11:04:54 -04001838 visible as a thin pair of lines through the right circle.
1839 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001840void draw(SkCanvas* canvas) {
1841 canvas->clear(SK_ColorWHITE);
1842 SkPaint paint;
1843 paint.setAntiAlias(true);
1844 paint.setColor(0x8055aaff);
1845 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
1846 for (auto alias: { false, true } ) {
1847 canvas->save();
1848 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
1849 canvas->drawCircle(67, 67, 60, paint);
1850 canvas->restore();
1851 canvas->save();
1852 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
1853 canvas->drawCircle(67, 67, 60, paint);
1854 canvas->restore();
1855 canvas->translate(120, 0);
1856 }
Cary Clark8032b982017-07-28 11:04:54 -04001857}
1858##
1859
Cary Clark2ade9972017-11-02 17:49:34 -04001860#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001861
1862##
1863
Cary Clark8032b982017-07-28 11:04:54 -04001864#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
1865
Cary Clarkab2621d2018-01-30 10:08:57 -05001866#In Clip
1867#Line # combines Clip with Round_Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001868#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001869
1870#Example
1871#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001872void draw(SkCanvas* canvas) {
1873 canvas->clear(SK_ColorWHITE);
1874 SkPaint paint;
1875 paint.setAntiAlias(true);
1876 paint.setColor(0x8055aaff);
1877 SkRRect oval;
1878 oval.setOval({10, 20, 90, 100});
1879 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
1880 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001881}
1882##
1883
Cary Clark2ade9972017-11-02 17:49:34 -04001884#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001885
1886##
1887
Herb Derbyefe39bc2018-05-01 17:06:20 -04001888#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001889
Cary Clarkab2621d2018-01-30 10:08:57 -05001890#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001891#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001892
1893#Example
1894#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001895void draw(SkCanvas* canvas) {
1896 SkPaint paint;
1897 paint.setColor(0x8055aaff);
1898 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
1899 canvas->clipRRect(oval, SkClipOp::kIntersect);
1900 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001901}
1902##
1903
Cary Clark2ade9972017-11-02 17:49:34 -04001904#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001905
1906##
1907
Herb Derbyefe39bc2018-05-01 17:06:20 -04001908#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001909
Cary Clarkab2621d2018-01-30 10:08:57 -05001910#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001911#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001912
1913#Example
1914#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001915void draw(SkCanvas* canvas) {
1916 SkPaint paint;
1917 paint.setAntiAlias(true);
1918 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
1919 canvas->clipRRect(oval, true);
1920 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001921}
1922##
1923
Cary Clark2ade9972017-11-02 17:49:34 -04001924#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001925
1926##
1927
1928#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
1929
Cary Clarkab2621d2018-01-30 10:08:57 -05001930#In Clip
1931#Line # combines Clip with Path ##
Cary Clark09d80c02018-10-31 12:14:03 -04001932#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001933
1934#Example
1935#Description
1936Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
1937area outside clip is subtracted from circle.
1938
1939Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
1940area inside clip is intersected with circle.
1941##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001942void draw(SkCanvas* canvas) {
1943 SkPaint paint;
1944 paint.setAntiAlias(true);
1945 SkPath path;
1946 path.addRect({20, 30, 100, 110});
1947 path.setFillType(SkPath::kInverseWinding_FillType);
1948 canvas->save();
1949 canvas->clipPath(path, SkClipOp::kDifference, false);
1950 canvas->drawCircle(70, 100, 60, paint);
1951 canvas->restore();
1952 canvas->translate(100, 100);
1953 path.setFillType(SkPath::kWinding_FillType);
1954 canvas->clipPath(path, SkClipOp::kIntersect, false);
1955 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001956}
1957##
1958
Cary Clark2ade9972017-11-02 17:49:34 -04001959#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001960
1961##
1962
Herb Derbyefe39bc2018-05-01 17:06:20 -04001963#Method void clipPath(const SkPath& path, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001964
Cary Clarkab2621d2018-01-30 10:08:57 -05001965#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001966#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001967
1968#Example
1969#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04001970Overlapping Rects form a clip. When clip Path_Fill_Type is set to
Herb Derbyefe39bc2018-05-01 17:06:20 -04001971SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04001972SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
1973##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001974void draw(SkCanvas* canvas) {
1975 SkPaint paint;
1976 paint.setAntiAlias(true);
1977 SkPath path;
1978 path.addRect({20, 15, 100, 95});
1979 path.addRect({50, 65, 130, 135});
1980 path.setFillType(SkPath::kWinding_FillType);
1981 canvas->save();
1982 canvas->clipPath(path, SkClipOp::kIntersect);
1983 canvas->drawCircle(70, 85, 60, paint);
1984 canvas->restore();
1985 canvas->translate(100, 100);
1986 path.setFillType(SkPath::kEvenOdd_FillType);
1987 canvas->clipPath(path, SkClipOp::kIntersect);
1988 canvas->drawCircle(70, 85, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001989}
1990##
1991
Cary Clark2ade9972017-11-02 17:49:34 -04001992#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001993
1994##
1995
Herb Derbyefe39bc2018-05-01 17:06:20 -04001996#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001997
Cary Clarkab2621d2018-01-30 10:08:57 -05001998#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001999#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002000
2001#Example
2002#Height 212
2003#Description
Herb Derbyefe39bc2018-05-01 17:06:20 -04002004Clip loops over itself covering its center twice. When clip Path_Fill_Type
2005is set to SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002006SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2007##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002008void draw(SkCanvas* canvas) {
2009 SkPaint paint;
2010 paint.setAntiAlias(true);
2011 SkPath path;
2012 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2013 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2014 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2015 path.setFillType(SkPath::kWinding_FillType);
2016 canvas->save();
2017 canvas->clipPath(path, SkClipOp::kIntersect);
2018 canvas->drawCircle(50, 50, 45, paint);
2019 canvas->restore();
2020 canvas->translate(100, 100);
2021 path.setFillType(SkPath::kEvenOdd_FillType);
2022 canvas->clipPath(path, SkClipOp::kIntersect);
2023 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002024}
2025##
2026
Cary Clark2ade9972017-11-02 17:49:34 -04002027#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002028
2029##
2030
2031# ------------------------------------------------------------------------------
2032
Cary Clark8032b982017-07-28 11:04:54 -04002033#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2034
Cary Clarkab2621d2018-01-30 10:08:57 -05002035#In Clip
2036#Line # combines Clip with Region ##
Cary Clark09d80c02018-10-31 12:14:03 -04002037#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002038
2039#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002040#Description
Cary Clarkce101242017-09-01 15:51:02 -04002041 region is unaffected by canvas rotation; iRect is affected by canvas rotation.
2042 Both clips are Aliased; this is not noticeable on Region clip because it
Cary Clarkbad5ad72017-08-03 17:14:08 -04002043 aligns to pixel boundaries.
2044##
2045void draw(SkCanvas* canvas) {
2046 SkPaint paint;
2047 paint.setAntiAlias(true);
2048 SkIRect iRect = {30, 40, 120, 130 };
2049 SkRegion region(iRect);
2050 canvas->rotate(10);
2051 canvas->save();
2052 canvas->clipRegion(region, SkClipOp::kIntersect);
2053 canvas->drawCircle(50, 50, 45, paint);
2054 canvas->restore();
2055 canvas->translate(100, 100);
2056 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2057 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002058}
2059##
2060
Cary Clark2ade9972017-11-02 17:49:34 -04002061#SeeAlso clipRect clipRRect clipPath
Cary Clark8032b982017-07-28 11:04:54 -04002062
2063##
2064
2065#Method bool quickReject(const SkRect& rect) const
2066
Cary Clarkab2621d2018-01-30 10:08:57 -05002067#In Clip
2068#Line # returns if Rect is outside Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002069#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002070
2071#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002072void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002073 SkRect testRect = {30, 30, 120, 129 };
2074 SkRect clipRect = {30, 130, 120, 230 };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002075 canvas->save();
2076 canvas->clipRect(clipRect);
2077 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2078 canvas->restore();
2079 canvas->rotate(10);
2080 canvas->clipRect(clipRect);
2081 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002082}
2083 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002084 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002085 quickReject false
2086 ##
2087##
2088
Cary Clark2ade9972017-11-02 17:49:34 -04002089#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002090
2091##
2092
2093#Method bool quickReject(const SkPath& path) const
2094
Cary Clarkab2621d2018-01-30 10:08:57 -05002095#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002096#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002097
2098#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002099void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002100 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2101 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002102 SkPath testPath, clipPath;
2103 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2104 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2105 canvas->save();
2106 canvas->clipPath(clipPath);
2107 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2108 canvas->restore();
2109 canvas->rotate(10);
2110 canvas->clipPath(clipPath);
2111 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002112 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002113 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002114 quickReject false
2115 ##
2116}
2117##
2118
Cary Clark2ade9972017-11-02 17:49:34 -04002119#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002120
2121##
2122
Herb Derbyefe39bc2018-05-01 17:06:20 -04002123#Method SkRect getLocalClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002124
Cary Clarkab2621d2018-01-30 10:08:57 -05002125#In Clip
2126#Line # returns Clip bounds in source coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -04002127#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002128
2129#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002130 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002131 Initial bounds is device bounds outset by 1 on all sides.
2132 Clipped bounds is clipPath bounds outset by 1 on all sides.
Cary Clark5538c132018-06-14 12:28:14 -04002133 Scaling the canvas by two on both axes scales the local bounds by 1/2
2134 on both axes.
Cary Clark8032b982017-07-28 11:04:54 -04002135 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002136 SkCanvas local(256, 256);
2137 canvas = &local;
2138 SkRect bounds = canvas->getLocalClipBounds();
2139 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2140 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002141 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002142 SkPath clipPath;
2143 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2144 canvas->clipPath(clipPath);
2145 bounds = canvas->getLocalClipBounds();
2146 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2147 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2148 canvas->scale(2, 2);
2149 bounds = canvas->getLocalClipBounds();
2150 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2151 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2152 #StdOut
2153 left:-1 top:-1 right:257 bottom:257
2154 left:29 top:129 right:121 bottom:231
2155 left:14.5 top:64.5 right:60.5 bottom:115.5
2156 ##
Cary Clark8032b982017-07-28 11:04:54 -04002157##
2158
2159# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002160#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002161#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002162
2163##
2164
Herb Derbyefe39bc2018-05-01 17:06:20 -04002165#Method bool getLocalClipBounds(SkRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002166
Cary Clarkab2621d2018-01-30 10:08:57 -05002167#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002168#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002169
2170#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002171 void draw(SkCanvas* canvas) {
2172 SkCanvas local(256, 256);
2173 canvas = &local;
2174 SkRect bounds;
2175 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2176 ? "false" : "true");
2177 SkPath path;
2178 canvas->clipPath(path);
2179 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2180 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002181 }
2182 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002183 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002184 local bounds empty = true
2185 ##
2186##
2187
2188# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002189#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002190#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002191
2192##
2193
Herb Derbyefe39bc2018-05-01 17:06:20 -04002194#Method SkIRect getDeviceClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002195
Cary Clarkab2621d2018-01-30 10:08:57 -05002196#In Clip
2197#Line # returns IRect bounds of Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002198#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002199
2200#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002201void draw(SkCanvas* canvas) {
2202 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002203 Initial bounds is device bounds, not outset.
2204 Clipped bounds is clipPath bounds, not outset.
Cary Clark5538c132018-06-14 12:28:14 -04002205 Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2
2206 on both axes.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002207 ##
2208 SkCanvas device(256, 256);
2209 canvas = &device;
2210 SkIRect bounds = canvas->getDeviceClipBounds();
2211 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2212 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002213 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002214 SkPath clipPath;
2215 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2216 canvas->save();
2217 canvas->clipPath(clipPath);
2218 bounds = canvas->getDeviceClipBounds();
2219 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2220 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2221 canvas->restore();
2222 canvas->scale(1.f/2, 1.f/2);
2223 canvas->clipPath(clipPath);
2224 bounds = canvas->getDeviceClipBounds();
2225 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2226 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002227 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002228 left:0 top:0 right:256 bottom:256
2229 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002230 left:15 top:65 right:60 bottom:115
2231 ##
2232}
2233##
2234
2235#ToDo some confusion on why with an identity Matrix local and device are different ##
Cary Clark2ade9972017-11-02 17:49:34 -04002236#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002237
2238# device canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002239#Bug 6524
Cary Clark8032b982017-07-28 11:04:54 -04002240
2241##
2242
Herb Derbyefe39bc2018-05-01 17:06:20 -04002243#Method bool getDeviceClipBounds(SkIRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002244
Cary Clarkab2621d2018-01-30 10:08:57 -05002245#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002246#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002247
2248#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002249 void draw(SkCanvas* canvas) {
2250 SkIRect bounds;
2251 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2252 ? "false" : "true");
2253 SkPath path;
2254 canvas->clipPath(path);
2255 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2256 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002257 }
2258 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002259 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002260 device bounds empty = true
2261 ##
2262##
2263
Cary Clark2ade9972017-11-02 17:49:34 -04002264#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002265
2266##
2267
Cary Clark08895c42018-02-01 09:37:32 -05002268#Subtopic Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002269
2270# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05002271#Subtopic Draw
Cary Clark78de7512018-02-07 07:27:09 -05002272#Line # draws into Canvas ##
2273##
Cary Clark8032b982017-07-28 11:04:54 -04002274
2275#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
Cary Clark78de7512018-02-07 07:27:09 -05002276#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002277#Line # fills Clip with Color and Blend_Mode ##
Cary Clark09d80c02018-10-31 12:14:03 -04002278#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002279
2280#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002281 canvas->drawColor(SK_ColorRED);
2282 canvas->clipRect(SkRect::MakeWH(150, 150));
2283 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
2284 canvas->clipRect(SkRect::MakeWH(75, 75));
2285 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04002286##
2287
Cary Clark2ade9972017-11-02 17:49:34 -04002288#SeeAlso clear SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002289
2290##
2291
2292# ------------------------------------------------------------------------------
2293
Herb Derbyefe39bc2018-05-01 17:06:20 -04002294#Method void clear(SkColor color)
Cary Clark78de7512018-02-07 07:27:09 -05002295#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002296#Line # fills Clip with Color ##
Cary Clark09d80c02018-10-31 12:14:03 -04002297#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002298
2299#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002300void draw(SkCanvas* canvas) {
2301 canvas->save();
2302 canvas->clipRect(SkRect::MakeWH(256, 128));
Herb Derbyefe39bc2018-05-01 17:06:20 -04002303 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
Cary Clarkbad5ad72017-08-03 17:14:08 -04002304 canvas->restore();
2305 canvas->save();
2306 canvas->clipRect(SkRect::MakeWH(150, 192));
2307 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
2308 canvas->restore();
2309 canvas->clipRect(SkRect::MakeWH(75, 256));
2310 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04002311}
2312##
2313
Cary Clark2ade9972017-11-02 17:49:34 -04002314#SeeAlso drawColor SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002315
2316##
2317
2318# ------------------------------------------------------------------------------
2319
Herb Derbyefe39bc2018-05-01 17:06:20 -04002320#Method void discard()
Cary Clark78de7512018-02-07 07:27:09 -05002321#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05002322#Line # makes Canvas contents undefined ##
Cary Clark09d80c02018-10-31 12:14:03 -04002323#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002324
Herb Derbyefe39bc2018-05-01 17:06:20 -04002325#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04002326##
2327
Cary Clarkabaffd82018-11-15 08:25:12 -05002328#SeeAlso flush() GrContext::abandonContext
Cary Clark09d80c02018-10-31 12:14:03 -04002329
Cary Clark8032b982017-07-28 11:04:54 -04002330##
2331
2332# ------------------------------------------------------------------------------
2333
2334#Method void drawPaint(const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002335#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002336#Line # fills Clip with Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002337#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002338
2339#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002340void draw(SkCanvas* canvas) {
2341 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
2342 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
2343 SkPaint paint;
2344 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
2345 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04002346}
2347##
2348
Cary Clark2ade9972017-11-02 17:49:34 -04002349#SeeAlso clear drawColor SkBitmap::erase
Cary Clark8032b982017-07-28 11:04:54 -04002350
2351##
2352
2353# ------------------------------------------------------------------------------
2354
2355#Enum PointMode
Cary Clark08895c42018-02-01 09:37:32 -05002356#Line # sets drawPoints options ##
Cary Clark8032b982017-07-28 11:04:54 -04002357
2358#Code
Cary Clark61313f32018-10-08 14:57:48 -04002359#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002360##
2361
2362Selects if an array of points are drawn as discrete points, as lines, or as
2363an open polygon.
2364
2365#Const kPoints_PointMode 0
Cary Clark682c58d2018-05-16 07:07:07 -04002366#Line # draw each point separately ##
Cary Clark8032b982017-07-28 11:04:54 -04002367##
2368
2369#Const kLines_PointMode 1
Cary Clark682c58d2018-05-16 07:07:07 -04002370#Line # draw each pair of points as a line segment ##
Cary Clark8032b982017-07-28 11:04:54 -04002371##
2372
2373#Const kPolygon_PointMode 2
Cary Clark682c58d2018-05-16 07:07:07 -04002374#Line # draw the array of points as a open polygon ##
Cary Clark8032b982017-07-28 11:04:54 -04002375##
2376
2377#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002378 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002379 The upper left corner shows three squares when drawn as points.
2380 The upper right corner shows one line; when drawn as lines, two points are required per line.
2381 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
2382 The lower left corner shows two lines with a miter when path contains polygon.
2383 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002384void draw(SkCanvas* canvas) {
2385 SkPaint paint;
2386 paint.setStyle(SkPaint::kStroke_Style);
2387 paint.setStrokeWidth(10);
2388 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
2389 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
2390 canvas->translate(128, 0);
2391 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
2392 canvas->translate(0, 128);
2393 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
2394 SkPath path;
2395 path.addPoly(points, 3, false);
2396 canvas->translate(-128, 0);
2397 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002398}
2399##
2400
Cary Clark2ade9972017-11-02 17:49:34 -04002401#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002402
2403##
2404
2405# ------------------------------------------------------------------------------
2406
2407#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002408#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002409#Line # draws array as points, lines, polygon ##
Cary Clark09d80c02018-10-31 12:14:03 -04002410#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002411
2412#Example
2413#Height 200
Herb Derbyefe39bc2018-05-01 17:06:20 -04002414 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002415 #List
2416 # The first column draws points. ##
2417 # The second column draws points as lines. ##
2418 # The third column draws points as a polygon. ##
2419 # The fourth column draws points as a polygonal path. ##
2420 # The first row uses a round cap and round join. ##
2421 # The second row uses a square cap and a miter join. ##
2422 # The third row uses a butt cap and a bevel join. ##
2423 ##
2424 The transparent color makes multiple line draws visible;
2425 the path is drawn all at once.
2426 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002427void draw(SkCanvas* canvas) {
2428 SkPaint paint;
2429 paint.setAntiAlias(true);
2430 paint.setStyle(SkPaint::kStroke_Style);
2431 paint.setStrokeWidth(10);
2432 paint.setColor(0x80349a45);
2433 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
Herb Derbyefe39bc2018-05-01 17:06:20 -04002434 const SkPaint::Join join[] = { SkPaint::kRound_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002435 SkPaint::kMiter_Join,
2436 SkPaint::kBevel_Join };
2437 int joinIndex = 0;
2438 SkPath path;
2439 path.addPoly(points, 3, false);
2440 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
2441 paint.setStrokeCap(cap);
2442 paint.setStrokeJoin(join[joinIndex++]);
2443 for (const auto mode : { SkCanvas::kPoints_PointMode,
2444 SkCanvas::kLines_PointMode,
2445 SkCanvas::kPolygon_PointMode } ) {
2446 canvas->drawPoints(mode, 3, points, paint);
2447 canvas->translate(64, 0);
2448 }
2449 canvas->drawPath(path, paint);
2450 canvas->translate(-192, 64);
2451 }
Cary Clark8032b982017-07-28 11:04:54 -04002452}
2453##
2454
Cary Clark2ade9972017-11-02 17:49:34 -04002455#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002456
2457##
2458
2459# ------------------------------------------------------------------------------
2460
2461#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002462#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002463#Line # draws point at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04002464#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002465
2466#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002467void draw(SkCanvas* canvas) {
2468 SkPaint paint;
2469 paint.setAntiAlias(true);
2470 paint.setColor(0x80349a45);
2471 paint.setStyle(SkPaint::kStroke_Style);
2472 paint.setStrokeWidth(100);
2473 paint.setStrokeCap(SkPaint::kRound_Cap);
2474 canvas->scale(1, 1.2f);
2475 canvas->drawPoint(64, 96, paint);
2476 canvas->scale(.6f, .8f);
2477 paint.setColor(SK_ColorWHITE);
2478 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002479}
2480##
2481
Cary Clark2ade9972017-11-02 17:49:34 -04002482#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002483
2484##
2485
Cary Clarkbad5ad72017-08-03 17:14:08 -04002486#Method void drawPoint(SkPoint p, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002487#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002488
2489#Example
2490void draw(SkCanvas* canvas) {
2491 SkPaint paint;
2492 paint.setAntiAlias(true);
2493 paint.setColor(0x80349a45);
2494 paint.setStyle(SkPaint::kStroke_Style);
2495 paint.setStrokeWidth(100);
2496 paint.setStrokeCap(SkPaint::kSquare_Cap);
2497 canvas->scale(1, 1.2f);
2498 canvas->drawPoint({64, 96}, paint);
2499 canvas->scale(.6f, .8f);
2500 paint.setColor(SK_ColorWHITE);
2501 canvas->drawPoint(106, 120, paint);
2502}
2503##
2504
Cary Clark2ade9972017-11-02 17:49:34 -04002505#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002506
2507##
2508
Cary Clark8032b982017-07-28 11:04:54 -04002509# ------------------------------------------------------------------------------
2510
2511#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002512#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002513#Line # draws line segment between two points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002514#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002515
2516#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002517 SkPaint paint;
2518 paint.setAntiAlias(true);
2519 paint.setColor(0xFF9a67be);
2520 paint.setStrokeWidth(20);
2521 canvas->skew(1, 0);
2522 canvas->drawLine(32, 96, 32, 160, paint);
2523 canvas->skew(-2, 0);
2524 canvas->drawLine(288, 96, 288, 160, paint);
2525##
2526
Cary Clark2ade9972017-11-02 17:49:34 -04002527#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002528
2529##
2530
2531#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002532#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002533
2534#Example
2535 SkPaint paint;
2536 paint.setAntiAlias(true);
2537 paint.setColor(0xFF9a67be);
2538 paint.setStrokeWidth(20);
2539 canvas->skew(1, 0);
2540 canvas->drawLine({32, 96}, {32, 160}, paint);
2541 canvas->skew(-2, 0);
2542 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002543##
2544
Cary Clark2ade9972017-11-02 17:49:34 -04002545#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002546
2547##
2548
2549# ------------------------------------------------------------------------------
2550
2551#Method void drawRect(const SkRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002552#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002553#Line # draws Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002554#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002555
2556#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002557void draw(SkCanvas* canvas) {
2558 SkPoint rectPts[] = { {64, 48}, {192, 160} };
2559 SkPaint paint;
2560 paint.setAntiAlias(true);
2561 paint.setStyle(SkPaint::kStroke_Style);
2562 paint.setStrokeWidth(20);
2563 paint.setStrokeJoin(SkPaint::kRound_Join);
2564 SkMatrix rotator;
2565 rotator.setRotate(30, 128, 128);
2566 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2567 paint.setColor(color);
2568 SkRect rect;
2569 rect.set(rectPts[0], rectPts[1]);
2570 canvas->drawRect(rect, paint);
2571 rotator.mapPoints(rectPts, 2);
2572 }
Cary Clark8032b982017-07-28 11:04:54 -04002573}
2574##
2575
Herb Derbyefe39bc2018-05-01 17:06:20 -04002576#SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002577
2578##
2579
2580# ------------------------------------------------------------------------------
2581
Herb Derbyefe39bc2018-05-01 17:06:20 -04002582#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002583#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002584#Line # draws IRect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002585#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002586
2587#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002588 SkIRect rect = { 64, 48, 192, 160 };
2589 SkPaint paint;
2590 paint.setAntiAlias(true);
2591 paint.setStyle(SkPaint::kStroke_Style);
2592 paint.setStrokeWidth(20);
2593 paint.setStrokeJoin(SkPaint::kRound_Join);
2594 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2595 paint.setColor(color);
2596 canvas->drawIRect(rect, paint);
2597 canvas->rotate(30, 128, 128);
2598 }
Cary Clark8032b982017-07-28 11:04:54 -04002599##
2600
Cary Clark2ade9972017-11-02 17:49:34 -04002601#SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002602
2603##
2604
2605# ------------------------------------------------------------------------------
2606
2607#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002608#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002609#Line # draws Region using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002610#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002611
2612#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002613void draw(SkCanvas* canvas) {
2614 SkRegion region;
2615 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
2616 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
2617 SkPaint paint;
2618 paint.setAntiAlias(true);
2619 paint.setStyle(SkPaint::kStroke_Style);
2620 paint.setStrokeWidth(20);
2621 paint.setStrokeJoin(SkPaint::kRound_Join);
2622 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002623}
2624##
2625
Cary Clark2ade9972017-11-02 17:49:34 -04002626#SeeAlso drawRect drawIRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002627
2628##
2629
2630# ------------------------------------------------------------------------------
2631
2632#Method void drawOval(const SkRect& oval, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002633#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002634#Line # draws Oval using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002635#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002636
2637#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002638void draw(SkCanvas* canvas) {
2639 canvas->clear(0xFF3f5f9f);
2640 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
2641 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
2642 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
2643 SkScalar pos[] = { 0.2f, 1.0f };
2644 SkRect bounds = SkRect::MakeWH(80, 70);
2645 SkPaint paint;
2646 paint.setAntiAlias(true);
2647 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
2648 SkShader::kClamp_TileMode));
2649 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04002650}
2651##
2652
Cary Clark2ade9972017-11-02 17:49:34 -04002653#SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect
Cary Clark8032b982017-07-28 11:04:54 -04002654
2655##
2656
2657# ------------------------------------------------------------------------------
2658
2659#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002660#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002661#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002662#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002663
2664#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002665void draw(SkCanvas* canvas) {
2666 SkPaint paint;
2667 paint.setAntiAlias(true);
2668 SkRect outer = {30, 40, 210, 220};
2669 SkRect radii = {30, 50, 70, 90 };
2670 SkRRect rRect;
2671 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
2672 canvas->drawRRect(rRect, paint);
2673 paint.setColor(SK_ColorWHITE);
2674 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
2675 outer.fLeft + radii.fLeft, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002676 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002677 outer.fRight - radii.fRight, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002678 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002679 outer.fRight, outer.fTop + radii.fTop, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002680 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002681 outer.fRight, outer.fBottom - radii.fBottom, paint);
2682}
Cary Clark8032b982017-07-28 11:04:54 -04002683##
2684
Cary Clark2ade9972017-11-02 17:49:34 -04002685#SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002686
2687##
2688
2689# ------------------------------------------------------------------------------
2690
2691#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002692#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002693#Line # draws double Round_Rect stroked or filled ##
Cary Clark09d80c02018-10-31 12:14:03 -04002694#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002695
2696#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002697void draw(SkCanvas* canvas) {
2698 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2699 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
2700 SkPaint paint;
2701 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002702}
2703##
2704
2705#Example
2706#Description
2707 Outer Rect has no corner radii, but stroke join is rounded.
2708 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
2709 Stroke join does not affect inner Round_Rect since it has no sharp corners.
2710##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002711void draw(SkCanvas* canvas) {
2712 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2713 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
2714 SkPaint paint;
2715 paint.setAntiAlias(true);
2716 paint.setStyle(SkPaint::kStroke_Style);
2717 paint.setStrokeWidth(20);
2718 paint.setStrokeJoin(SkPaint::kRound_Join);
2719 canvas->drawDRRect(outer, inner, paint);
2720 paint.setStrokeWidth(1);
2721 paint.setColor(SK_ColorWHITE);
2722 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002723}
2724##
2725
Cary Clark2ade9972017-11-02 17:49:34 -04002726#SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002727
2728##
2729
2730# ------------------------------------------------------------------------------
2731
2732#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002733#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002734#Line # draws Circle using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002735#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002736
2737#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002738 void draw(SkCanvas* canvas) {
2739 SkPaint paint;
2740 paint.setAntiAlias(true);
2741 canvas->drawCircle(128, 128, 90, paint);
2742 paint.setColor(SK_ColorWHITE);
2743 canvas->drawCircle(86, 86, 20, paint);
2744 canvas->drawCircle(160, 76, 20, paint);
2745 canvas->drawCircle(140, 150, 35, paint);
2746 }
2747##
2748
Cary Clark2ade9972017-11-02 17:49:34 -04002749#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clarkbad5ad72017-08-03 17:14:08 -04002750
2751##
2752
2753#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002754#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002755
2756#Example
2757 void draw(SkCanvas* canvas) {
2758 SkPaint paint;
2759 paint.setAntiAlias(true);
2760 canvas->drawCircle(128, 128, 90, paint);
2761 paint.setColor(SK_ColorWHITE);
2762 canvas->drawCircle({86, 86}, 20, paint);
2763 canvas->drawCircle({160, 76}, 20, paint);
2764 canvas->drawCircle({140, 150}, 35, paint);
2765 }
Cary Clark8032b982017-07-28 11:04:54 -04002766##
2767
Cary Clark2ade9972017-11-02 17:49:34 -04002768#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002769
2770##
2771
2772# ------------------------------------------------------------------------------
2773
2774#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
2775 bool useCenter, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002776#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002777#Line # draws Arc using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002778#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002779
2780#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002781 void draw(SkCanvas* canvas) {
2782 SkPaint paint;
2783 paint.setAntiAlias(true);
2784 SkRect oval = { 4, 4, 60, 60};
2785 for (auto useCenter : { false, true } ) {
2786 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
2787 paint.setStyle(style);
2788 for (auto degrees : { 45, 90, 180, 360} ) {
2789 canvas->drawArc(oval, 0, degrees , useCenter, paint);
2790 canvas->translate(64, 0);
2791 }
2792 canvas->translate(-256, 64);
2793 }
2794 }
Cary Clark8032b982017-07-28 11:04:54 -04002795 }
2796##
2797
2798#Example
2799#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04002800 void draw(SkCanvas* canvas) {
2801 SkPaint paint;
2802 paint.setAntiAlias(true);
2803 paint.setStyle(SkPaint::kStroke_Style);
2804 paint.setStrokeWidth(4);
2805 SkRect oval = { 4, 4, 60, 60};
2806 float intervals[] = { 5, 5 };
2807 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
2808 for (auto degrees : { 270, 360, 540, 720 } ) {
2809 canvas->drawArc(oval, 0, degrees, false, paint);
2810 canvas->translate(64, 0);
2811 }
Cary Clark8032b982017-07-28 11:04:54 -04002812 }
2813##
2814
Cary Clark2ade9972017-11-02 17:49:34 -04002815#SeeAlso SkPath::arcTo drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002816
2817##
2818
2819# ------------------------------------------------------------------------------
2820
2821#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002822#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002823#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002824#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002825
2826#Example
2827#Description
2828 Top row has a zero radius a generates a rectangle.
2829 Second row radii sum to less than sides.
2830 Third row radii sum equals sides.
2831 Fourth row radii sum exceeds sides; radii are scaled to fit.
2832##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002833 void draw(SkCanvas* canvas) {
2834 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
2835 SkPaint paint;
2836 paint.setStrokeWidth(15);
2837 paint.setStrokeJoin(SkPaint::kRound_Join);
2838 paint.setAntiAlias(true);
2839 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
2840 paint.setStyle(style );
2841 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
2842 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
2843 canvas->translate(0, 60);
2844 }
2845 canvas->translate(80, -240);
2846 }
Cary Clark8032b982017-07-28 11:04:54 -04002847 }
2848##
2849
Cary Clark77b3f3a2018-11-07 14:59:03 -05002850#SeeAlso drawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint
Cary Clark8032b982017-07-28 11:04:54 -04002851
2852##
2853
2854# ------------------------------------------------------------------------------
2855
2856#Method void drawPath(const SkPath& path, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002857#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002858#Line # draws Path using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002859#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002860
2861#Example
2862#Description
2863 Top rows draw stroked path with combinations of joins and caps. The open contour
2864 is affected by caps; the closed contour is affected by joins.
Herb Derbyefe39bc2018-05-01 17:06:20 -04002865 Bottom row draws fill the same for open and closed contour.
Cary Clark8032b982017-07-28 11:04:54 -04002866 First bottom column shows winding fills overlap.
2867 Second bottom column shows even odd fills exclude overlap.
2868 Third bottom column shows inverse winding fills area outside both contours.
2869##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002870void draw(SkCanvas* canvas) {
2871 SkPath path;
2872 path.moveTo(20, 20);
2873 path.quadTo(60, 20, 60, 60);
2874 path.close();
2875 path.moveTo(60, 20);
2876 path.quadTo(60, 60, 20, 60);
2877 SkPaint paint;
2878 paint.setStrokeWidth(10);
2879 paint.setAntiAlias(true);
2880 paint.setStyle(SkPaint::kStroke_Style);
2881 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
2882 paint.setStrokeJoin(join);
2883 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
2884 paint.setStrokeCap(cap);
2885 canvas->drawPath(path, paint);
2886 canvas->translate(80, 0);
2887 }
2888 canvas->translate(-240, 60);
2889 }
2890 paint.setStyle(SkPaint::kFill_Style);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002891 for (auto fill : { SkPath::kWinding_FillType,
2892 SkPath::kEvenOdd_FillType,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002893 SkPath::kInverseWinding_FillType } ) {
2894 path.setFillType(fill);
2895 canvas->save();
2896 canvas->clipRect({0, 10, 80, 70});
2897 canvas->drawPath(path, paint);
2898 canvas->restore();
2899 canvas->translate(80, 0);
2900 }
Cary Clark8032b982017-07-28 11:04:54 -04002901}
2902##
2903
Cary Clark2ade9972017-11-02 17:49:34 -04002904#SeeAlso SkPath drawLine drawArc drawRect drawPoints
Cary Clark8032b982017-07-28 11:04:54 -04002905
2906##
2907
2908# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002909#Subtopic Draw_Image
2910#Line # draws Image to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04002911
Cary Clarkbad5ad72017-08-03 17:14:08 -04002912drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
2913a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04002914
Cary Clark73fa9722017-08-29 17:36:51 -04002915#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05002916#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05002917#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002918#Line # draws Image at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04002919#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002920
2921#Example
2922#Height 64
2923#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04002924void draw(SkCanvas* canvas) {
2925 // sk_sp<SkImage> image;
2926 SkImage* imagePtr = image.get();
2927 canvas->drawImage(imagePtr, 0, 0);
2928 SkPaint paint;
2929 canvas->drawImage(imagePtr, 80, 0, &paint);
2930 paint.setAlpha(0x80);
2931 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04002932}
2933##
2934
Cary Clark2ade9972017-11-02 17:49:34 -04002935#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04002936
2937##
2938
2939# ------------------------------------------------------------------------------
2940
2941#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Herb Derbyefe39bc2018-05-01 17:06:20 -04002942 const SkPaint* paint = nullptr)
Cary Clark09d80c02018-10-31 12:14:03 -04002943#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002944
2945#Example
2946#Height 64
2947#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04002948void draw(SkCanvas* canvas) {
2949 // sk_sp<SkImage> image;
2950 canvas->drawImage(image, 0, 0);
2951 SkPaint paint;
2952 canvas->drawImage(image, 80, 0, &paint);
2953 paint.setAlpha(0x80);
2954 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04002955}
2956##
2957
Cary Clark2ade9972017-11-02 17:49:34 -04002958#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04002959
2960##
2961
2962# ------------------------------------------------------------------------------
2963
2964#Enum SrcRectConstraint
Cary Clark08895c42018-02-01 09:37:32 -05002965#Line # sets drawImageRect options ##
Cary Clark8032b982017-07-28 11:04:54 -04002966
2967#Code
Cary Clark61313f32018-10-08 14:57:48 -04002968#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002969##
2970
Cary Clarkce101242017-09-01 15:51:02 -04002971SrcRectConstraint controls the behavior at the edge of source Rect,
2972provided to drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04002973
Cary Clarkce101242017-09-01 15:51:02 -04002974Image_Filter in Paint may sample multiple pixels in the image. Source Rect
Cary Clarkbad5ad72017-08-03 17:14:08 -04002975restricts the bounds of pixels that may be read. Image_Filter may slow down if
Herb Derbyefe39bc2018-05-01 17:06:20 -04002976it cannot read outside the bounds, when sampling near the edge of source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04002977SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
Cary Clarkce101242017-09-01 15:51:02 -04002978outside source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04002979
Cary Clark682c58d2018-05-16 07:07:07 -04002980#Const kStrict_SrcRectConstraint 0
2981#Line # sample only inside bounds; slower ##
Cary Clarkce101242017-09-01 15:51:02 -04002982 Requires Image_Filter to respect source Rect,
Cary Clark8032b982017-07-28 11:04:54 -04002983 sampling only inside of its bounds, possibly with a performance penalty.
2984##
2985
Cary Clark682c58d2018-05-16 07:07:07 -04002986#Const kFast_SrcRectConstraint 1
2987#Line # sample outside bounds; faster ##
Cary Clarkce101242017-09-01 15:51:02 -04002988 Permits Image_Filter to sample outside of source Rect
Cary Clark8032b982017-07-28 11:04:54 -04002989 by half the width of Image_Filter, permitting it to run faster but with
2990 error at the image edges.
2991##
2992
2993#Example
2994#Height 64
2995#Description
2996 redBorder contains a black and white checkerboard bordered by red.
2997 redBorder is drawn scaled by 16 on the left.
Cary Clarkce101242017-09-01 15:51:02 -04002998 The middle and right bitmaps are filtered checkerboards.
Cary Clark8032b982017-07-28 11:04:54 -04002999 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3000 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3001##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003002void draw(SkCanvas* canvas) {
3003 SkBitmap redBorder;
3004 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3005 SkCanvas checkRed(redBorder);
3006 checkRed.clear(SK_ColorRED);
3007 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3008 { SK_ColorWHITE, SK_ColorBLACK } };
3009 checkRed.writePixels(
3010 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3011 canvas->scale(16, 16);
3012 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3013 canvas->resetMatrix();
3014 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3015 SkPaint lowPaint;
3016 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3017 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3018 SkCanvas::kFast_SrcRectConstraint } ) {
3019 canvas->translate(80, 0);
3020 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3021 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3022 }
Cary Clark8032b982017-07-28 11:04:54 -04003023}
3024##
3025
Cary Clark2ade9972017-11-02 17:49:34 -04003026#SeeAlso drawImageRect drawImage SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003027
3028##
3029
3030# ------------------------------------------------------------------------------
3031
3032#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3033 const SkPaint* paint,
3034 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003035#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003036#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003037#Line # draws Image, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003038#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003039
3040#Example
3041#Height 64
3042#Description
3043 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
Cary Clarkbc5697d2017-10-04 14:31:33 -04003044 its bounds; there is no bleeding with kFast_SrcRectConstraint.
Cary Clark8032b982017-07-28 11:04:54 -04003045 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3046 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3047 with kFast_SrcRectConstraint red bleeds on the edges.
3048##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003049void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003050 uint32_t pixels[][4] = {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003051 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
3052 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
3053 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
3054 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
3055 SkBitmap redBorder;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003056 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003057 (void*) pixels, sizeof(pixels[0]));
3058 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3059 SkPaint lowPaint;
3060 for (auto constraint : {
3061 SkCanvas::kFast_SrcRectConstraint,
3062 SkCanvas::kStrict_SrcRectConstraint,
3063 SkCanvas::kFast_SrcRectConstraint } ) {
3064 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3065 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3066 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3067 canvas->translate(80, 0);
3068 }
3069}
Cary Clark8032b982017-07-28 11:04:54 -04003070##
3071
Cary Clark2ade9972017-11-02 17:49:34 -04003072#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003073
3074##
3075
3076# ------------------------------------------------------------------------------
3077
3078#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
3079 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003080#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003081#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003082#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003083
3084#Example
3085#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003086void draw(SkCanvas* canvas) {
3087 // sk_sp<SkImage> image;
3088 for (auto i : { 1, 2, 4, 8 } ) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003089 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003090 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
3091 }
Cary Clark8032b982017-07-28 11:04:54 -04003092}
3093##
3094
Cary Clark2ade9972017-11-02 17:49:34 -04003095#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003096
3097##
3098
3099# ------------------------------------------------------------------------------
3100
Cary Clark0ac0edd2018-10-29 11:28:43 -04003101#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003102#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003103#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003104#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003105
3106#Example
3107#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003108void draw(SkCanvas* canvas) {
3109 // sk_sp<SkImage> image;
3110 for (auto i : { 20, 40, 80, 160 } ) {
3111 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
3112 }
Cary Clark8032b982017-07-28 11:04:54 -04003113}
3114##
3115
Cary Clark2ade9972017-11-02 17:49:34 -04003116#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003117
3118##
3119
3120# ------------------------------------------------------------------------------
3121
3122#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
3123 const SkPaint* paint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003124 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003125#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003126#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003127#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003128
3129#Example
3130#Height 64
3131#Description
3132 Canvas scales and translates; transformation from src to dst also scales.
3133 The two matrices are concatenated to create the final transformation.
3134##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003135void draw(SkCanvas* canvas) {
3136 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3137 { SK_ColorWHITE, SK_ColorBLACK } };
3138 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003139 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003140 (void*) pixels, sizeof(pixels[0]));
3141 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3142 SkPaint paint;
3143 canvas->scale(4, 4);
3144 for (auto alpha : { 50, 100, 150, 255 } ) {
3145 paint.setAlpha(alpha);
3146 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3147 canvas->translate(8, 0);
3148 }
3149}
Cary Clark8032b982017-07-28 11:04:54 -04003150##
3151
Cary Clark2ade9972017-11-02 17:49:34 -04003152#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003153
3154##
3155
3156# ------------------------------------------------------------------------------
3157
3158#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003159 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003160#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003161#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003162#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003163
3164#Example
3165#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003166void draw(SkCanvas* canvas) {
3167 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
3168 { 0xAAAAAAAA, 0xFFFFFFFF} };
3169 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003170 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003171 (void*) pixels, sizeof(pixels[0]));
3172 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3173 SkPaint paint;
3174 canvas->scale(4, 4);
3175 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3176 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3177 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3178 canvas->translate(8, 0);
3179 }
Cary Clark8032b982017-07-28 11:04:54 -04003180}
3181##
3182
Cary Clark2ade9972017-11-02 17:49:34 -04003183#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
3184
Cary Clark8032b982017-07-28 11:04:54 -04003185##
3186
3187# ------------------------------------------------------------------------------
3188
Cary Clark0ac0edd2018-10-29 11:28:43 -04003189#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003190#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003191#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003192#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003193
3194#Example
3195#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003196void draw(SkCanvas* canvas) {
3197 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3198 { 0xAAAA0000, 0xFFFF0000} };
3199 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003200 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003201 (void*) pixels, sizeof(pixels[0]));
3202 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3203 SkPaint paint;
3204 canvas->scale(4, 4);
3205 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3206 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3207 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
3208 canvas->translate(8, 0);
3209 }
Cary Clark8032b982017-07-28 11:04:54 -04003210}
3211##
3212
Cary Clark2ade9972017-11-02 17:49:34 -04003213#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003214
3215##
3216
3217# ------------------------------------------------------------------------------
3218
3219#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
3220 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003221#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003222#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003223#Line # draws Nine_Patch Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003224
Cary Clark80247e52018-07-11 16:18:41 -04003225Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003226IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003227the center. Corners are unmodified or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003228are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003229
Cary Clarkbad5ad72017-08-03 17:14:08 -04003230Additionally transform draw using Clip, Matrix, and optional Paint paint.
3231
Cary Clark682c58d2018-05-16 07:07:07 -04003232#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003233
3234If generated mask extends beyond image bounds, replicate image edge colors, just
3235as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003236replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003237
3238#Param image Image containing pixels, dimensions, and format ##
3239#Param center IRect edge of image corners and sides ##
3240#Param dst destination Rect of image to draw to ##
3241#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3242 and so on; or nullptr
3243##
Cary Clark8032b982017-07-28 11:04:54 -04003244
3245#Example
3246#Height 128
3247#Description
3248 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003249 The second image equals the size of center; only corners are drawn without scaling.
3250 The remaining images are larger than center. All corners draw without scaling.
3251 The sides and center are scaled if needed to take up the remaining space.
Cary Clark8032b982017-07-28 11:04:54 -04003252##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003253void draw(SkCanvas* canvas) {
3254 SkIRect center = { 20, 10, 50, 40 };
3255 SkBitmap bitmap;
3256 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3257 SkCanvas bitCanvas(bitmap);
3258 SkPaint paint;
3259 SkColor gray = 0xFF000000;
3260 int left = 0;
3261 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3262 int top = 0;
3263 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3264 paint.setColor(gray);
3265 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3266 gray += 0x001f1f1f;
3267 top = bottom;
3268 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003269 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003270 }
3271 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3272 SkImage* imagePtr = image.get();
3273 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3274 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3275 canvas->translate(dest + 4, 0);
3276 }
Cary Clark8032b982017-07-28 11:04:54 -04003277}
3278##
3279
Cary Clark2ade9972017-11-02 17:49:34 -04003280#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003281
3282##
3283
3284# ------------------------------------------------------------------------------
3285
3286#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003287 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003288#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003289#In Draw
Cary Clark80247e52018-07-11 16:18:41 -04003290Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003291IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003292the center. Corners are not scaled, or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003293are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003294
Cary Clarkbad5ad72017-08-03 17:14:08 -04003295Additionally transform draw using Clip, Matrix, and optional Paint paint.
3296
Cary Clark137b8742018-05-30 09:21:49 -04003297#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003298
3299If generated mask extends beyond image bounds, replicate image edge colors, just
3300as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003301replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003302
3303#Param image Image containing pixels, dimensions, and format ##
3304#Param center IRect edge of image corners and sides ##
3305#Param dst destination Rect of image to draw to ##
3306#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3307 and so on; or nullptr
3308##
Cary Clark8032b982017-07-28 11:04:54 -04003309
3310#Example
3311#Height 128
3312#Description
3313 The two leftmost images has four corners and sides to the left and right of center.
3314 The leftmost image scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003315 The third and fourth image corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003316 fill the remaining space.
3317 The rightmost image has four corners scaled vertically to fit, and uses sides above
3318 and below center to fill the remaining space.
3319##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003320void draw(SkCanvas* canvas) {
3321 SkIRect center = { 20, 10, 50, 40 };
3322 SkBitmap bitmap;
3323 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3324 SkCanvas bitCanvas(bitmap);
3325 SkPaint paint;
3326 SkColor gray = 0xFF000000;
3327 int left = 0;
3328 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3329 int top = 0;
3330 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3331 paint.setColor(gray);
3332 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3333 gray += 0x001f1f1f;
3334 top = bottom;
3335 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003336 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003337 }
3338 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3339 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3340 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3341 canvas->translate(dest + 4, 0);
3342 }
Cary Clark8032b982017-07-28 11:04:54 -04003343}
3344##
3345
Cary Clark2ade9972017-11-02 17:49:34 -04003346#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003347
3348##
3349
3350# ------------------------------------------------------------------------------
3351
3352#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003353 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003354#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003355#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003356#Line # draws Bitmap at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04003357#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003358
3359#Example
3360#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003361void draw(SkCanvas* canvas) {
3362 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3363 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3364 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3365 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3366 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3367 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3368 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
3369 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
3370 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003371 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003372 (void*) pixels, sizeof(pixels[0]));
3373 SkPaint paint;
3374 canvas->scale(4, 4);
3375 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3376 paint.setColor(color);
3377 canvas->drawBitmap(bitmap, 0, 0, &paint);
3378 canvas->translate(12, 0);
3379 }
Cary Clark8032b982017-07-28 11:04:54 -04003380}
3381##
3382
Cary Clark2ade9972017-11-02 17:49:34 -04003383#SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -04003384
3385##
3386
3387# ------------------------------------------------------------------------------
3388
3389#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
3390 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003391#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003392#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003393#Line # draws Bitmap, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003394#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003395
3396#Example
3397#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003398void draw(SkCanvas* canvas) {
3399 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3400 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3401 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3402 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3403 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3404 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3405 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3406 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
3407 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003408 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003409 (void*) pixels, sizeof(pixels[0]));
3410 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003411 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6));
Cary Clarkbad5ad72017-08-03 17:14:08 -04003412 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3413 paint.setColor(color);
3414 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3415 canvas->translate(48, 0);
3416 }
Cary Clark8032b982017-07-28 11:04:54 -04003417}
3418##
3419
Cary Clark2ade9972017-11-02 17:49:34 -04003420#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003421
3422##
3423
3424# ------------------------------------------------------------------------------
3425
3426#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
3427 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003428#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003429#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003430#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003431
3432#Example
3433#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003434void draw(SkCanvas* canvas) {
3435 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3436 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3437 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3438 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3439 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
3440 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
3441 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3442 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
3443 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003444 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003445 (void*) pixels, sizeof(pixels[0]));
3446 SkPaint paint;
3447 paint.setFilterQuality(kHigh_SkFilterQuality);
3448 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
3449 paint.setColor(color);
3450 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3451 canvas->translate(48.25f, 0);
3452 }
Cary Clark8032b982017-07-28 11:04:54 -04003453}
3454##
3455
Cary Clark2ade9972017-11-02 17:49:34 -04003456#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003457
3458##
3459
3460# ------------------------------------------------------------------------------
3461
3462#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
3463 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003464#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003465#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003466#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003467
3468#Example
3469#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003470void draw(SkCanvas* canvas) {
3471 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3472 { 0xAAAA0000, 0xFFFF0000} };
3473 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003474 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003475 (void*) pixels, sizeof(pixels[0]));
3476 SkPaint paint;
3477 canvas->scale(4, 4);
3478 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3479 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3480 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
3481 canvas->translate(8, 0);
3482 }
Cary Clark8032b982017-07-28 11:04:54 -04003483}
3484##
3485
Cary Clark2ade9972017-11-02 17:49:34 -04003486#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003487
3488##
3489
3490# ------------------------------------------------------------------------------
3491
Cary Clark682c58d2018-05-16 07:07:07 -04003492#PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image)
3493If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3494Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader.
3495If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint
3496Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all
3497other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels.
Cary Clark137b8742018-05-30 09:21:49 -04003498Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state.
Cary Clark682c58d2018-05-16 07:07:07 -04003499##
3500
Cary Clark8032b982017-07-28 11:04:54 -04003501#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04003502 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003503#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003504#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003505#Line # draws Nine_Patch Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003506
Cary Clark80247e52018-07-11 16:18:41 -04003507Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003508IRect center divides the bitmap into nine sections: four sides, four corners,
Cary Clarkce101242017-09-01 15:51:02 -04003509and the center. Corners are not scaled, or scaled down proportionately if their
Cary Clarkbad5ad72017-08-03 17:14:08 -04003510sides are larger than dst; center and four sides are scaled to fit remaining
3511space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003512
Cary Clarkbad5ad72017-08-03 17:14:08 -04003513Additionally transform draw using Clip, Matrix, and optional Paint paint.
3514
Cary Clark682c58d2018-05-16 07:07:07 -04003515#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003516
3517If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3518just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003519SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003520outside of its bounds.
3521
3522#Param bitmap Bitmap containing pixels, dimensions, and format ##
3523#Param center IRect edge of image corners and sides ##
3524#Param dst destination Rect of image to draw to ##
3525#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3526 and so on; or nullptr
3527##
Cary Clark8032b982017-07-28 11:04:54 -04003528
3529#Example
3530#Height 128
3531#Description
3532 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3533 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003534 The third and fourth draw corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003535 fill the remaining space.
3536 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3537 and below center to fill the remaining space.
3538##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003539void draw(SkCanvas* canvas) {
3540 SkIRect center = { 20, 10, 50, 40 };
3541 SkBitmap bitmap;
3542 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3543 SkCanvas bitCanvas(bitmap);
3544 SkPaint paint;
3545 SkColor gray = 0xFF000000;
3546 int left = 0;
3547 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3548 int top = 0;
3549 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3550 paint.setColor(gray);
3551 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3552 gray += 0x001f1f1f;
3553 top = bottom;
3554 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003555 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003556 }
3557 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3558 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3559 canvas->translate(dest + 4, 0);
3560 }
Cary Clark8032b982017-07-28 11:04:54 -04003561}
3562##
3563
Cary Clark2ade9972017-11-02 17:49:34 -04003564#SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect
Cary Clark8032b982017-07-28 11:04:54 -04003565
3566##
3567
3568# ------------------------------------------------------------------------------
Cary Clark682c58d2018-05-16 07:07:07 -04003569#Subtopic Lattice
3570#Line # divides Bitmap or Image into a rectangular grid ##
3571
Cary Clark8032b982017-07-28 11:04:54 -04003572#Struct Lattice
Cary Clark08895c42018-02-01 09:37:32 -05003573#Line # divides Bitmap or Image into a rectangular grid ##
Cary Clark682c58d2018-05-16 07:07:07 -04003574
Cary Clark8032b982017-07-28 11:04:54 -04003575#Code
Cary Clark61313f32018-10-08 14:57:48 -04003576#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003577##
3578
Cary Clark137b8742018-05-30 09:21:49 -04003579Lattice divides Bitmap or Image into a rectangular grid.
3580Grid entries on even columns and even rows are fixed; these entries are
3581always drawn at their original size if the destination is large enough.
3582If the destination side is too small to hold the fixed entries, all fixed
3583entries are proportionately scaled down to fit.
3584The grid entries not on even columns and rows are scaled to fit the
3585remaining space, if any.
3586
Cary Clark2f466242017-12-11 16:03:17 -05003587 #Enum RectType
Cary Clark682c58d2018-05-16 07:07:07 -04003588 #Line # optional setting per rectangular grid entry ##
Cary Clark8032b982017-07-28 11:04:54 -04003589 #Code
Cary Clark61313f32018-10-08 14:57:48 -04003590 #Populate
Cary Clark8032b982017-07-28 11:04:54 -04003591 ##
3592
Cary Clark2f466242017-12-11 16:03:17 -05003593 Optional setting per rectangular grid entry to make it transparent,
3594 or to fill the grid entry with a color.
Cary Clark8032b982017-07-28 11:04:54 -04003595
Cary Clark2f466242017-12-11 16:03:17 -05003596 #Const kDefault 0
Cary Clark682c58d2018-05-16 07:07:07 -04003597 #Line # draws Bitmap into lattice rectangle ##
Cary Clark2f466242017-12-11 16:03:17 -05003598 ##
3599
3600 #Const kTransparent 1
Cary Clark682c58d2018-05-16 07:07:07 -04003601 #Line # skips lattice rectangle by making it transparent ##
Cary Clark2f466242017-12-11 16:03:17 -05003602 ##
3603
3604 #Const kFixedColor 2
Cary Clark682c58d2018-05-16 07:07:07 -04003605 #Line # draws one of fColors into lattice rectangle ##
Cary Clark8032b982017-07-28 11:04:54 -04003606 ##
3607 ##
3608
Cary Clark61313f32018-10-08 14:57:48 -04003609#Subtopic Members
Cary Clark682c58d2018-05-16 07:07:07 -04003610##
3611
Cary Clark8032b982017-07-28 11:04:54 -04003612 #Member const int* fXDivs
Cary Clark5538c132018-06-14 12:28:14 -04003613 #Line # x-axis values dividing bitmap ##
3614 Array of x-axis values that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003615 Array entries must be unique, increasing, greater than or equal to
3616 fBounds left edge, and less than fBounds right edge.
3617 Set the first element to fBounds left to collapse the left column of
3618 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003619 ##
3620
3621 #Member const int* fYDivs
Cary Clark5538c132018-06-14 12:28:14 -04003622 #Line # y-axis values dividing bitmap ##
3623 Array of y-axis values that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003624 Array entries must be unique, increasing, greater than or equal to
3625 fBounds top edge, and less than fBounds bottom edge.
3626 Set the first element to fBounds top to collapse the top row of fixed
3627 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003628 ##
3629
Cary Clark2f466242017-12-11 16:03:17 -05003630 #Member const RectType* fRectTypes
Cary Clark682c58d2018-05-16 07:07:07 -04003631 #Line # array of fill types ##
Cary Clark2f466242017-12-11 16:03:17 -05003632 Optional array of fill types, one per rectangular grid entry:
Cary Clark2be81cf2018-09-13 12:04:30 -04003633 array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark6fc50412017-09-21 12:31:06 -04003634
Cary Clark2f466242017-12-11 16:03:17 -05003635 Each RectType is one of: kDefault, kTransparent, kFixedColor.
3636
Cary Clark8032b982017-07-28 11:04:54 -04003637 Array entries correspond to the rectangular grid entries, ascending
3638 left to right and then top to bottom.
3639 ##
3640
3641 #Member int fXCount
Cary Clark682c58d2018-05-16 07:07:07 -04003642 #Line # number of x-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003643 Number of entries in fXDivs array; one less than the number of
3644 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003645 ##
3646
3647 #Member int fYCount
Cary Clark682c58d2018-05-16 07:07:07 -04003648 #Line # number of y-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003649 Number of entries in fYDivs array; one less than the number of vertical
3650 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003651 ##
3652
3653 #Member const SkIRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04003654 #Line # source bounds to draw from ##
Cary Clark8032b982017-07-28 11:04:54 -04003655 Optional subset IRect source to draw from.
3656 If nullptr, source bounds is dimensions of Bitmap or Image.
3657 ##
3658
Cary Clark2f466242017-12-11 16:03:17 -05003659 #Member const SkColor* fColors
Cary Clark682c58d2018-05-16 07:07:07 -04003660 #Line # array of colors ##
Cary Clark2f466242017-12-11 16:03:17 -05003661 Optional array of colors, one per rectangular grid entry.
Cary Clark2be81cf2018-09-13 12:04:30 -04003662 Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark2f466242017-12-11 16:03:17 -05003663
3664 Array entries correspond to the rectangular grid entries, ascending
3665 left to right, then top to bottom.
3666 ##
3667
Cary Clark8032b982017-07-28 11:04:54 -04003668#Struct Lattice ##
3669
3670#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
3671 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003672#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003673#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003674#Line # draws proportionally stretched Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003675
Cary Clark80247e52018-07-11 16:18:41 -04003676Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003677
3678Lattice lattice divides bitmap into a rectangular grid.
3679Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003680of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003681size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003682dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003683
3684Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003685
Cary Clark682c58d2018-05-16 07:07:07 -04003686#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003687
3688If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3689just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003690SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003691outside of its bounds.
3692
3693#Param bitmap Bitmap containing pixels, dimensions, and format ##
3694#Param lattice division of bitmap into fixed and variable rectangles ##
3695#Param dst destination Rect of image to draw to ##
3696#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3697 and so on; or nullptr
3698##
Cary Clark8032b982017-07-28 11:04:54 -04003699
3700#Example
3701#Height 128
3702#Description
3703 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3704 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003705 The third and fourth draw corners are not scaled; the sides are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003706 fill the remaining space; the center is transparent.
3707 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3708 and below center to fill the remaining space.
3709##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003710void draw(SkCanvas* canvas) {
3711 SkIRect center = { 20, 10, 50, 40 };
3712 SkBitmap bitmap;
3713 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3714 SkCanvas bitCanvas(bitmap);
3715 SkPaint paint;
3716 SkColor gray = 0xFF000000;
3717 int left = 0;
3718 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3719 int top = 0;
3720 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3721 paint.setColor(gray);
3722 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3723 gray += 0x001f1f1f;
3724 top = bottom;
3725 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003726 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003727 }
3728 const int xDivs[] = { center.fLeft, center.fRight };
3729 const int yDivs[] = { center.fTop, center.fBottom };
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003730 SkCanvas::Lattice::RectType fillTypes[3][3];
3731 memset(fillTypes, 0, sizeof(fillTypes));
3732 fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
3733 SkColor dummy[9]; // temporary pending bug fix
3734 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs),
3735 SK_ARRAY_COUNT(yDivs), nullptr, dummy };
Cary Clarkbad5ad72017-08-03 17:14:08 -04003736 for (auto dest: { 20, 30, 40, 60, 90 } ) {
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003737 canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003738 canvas->translate(dest + 4, 0);
3739 }
Cary Clark8032b982017-07-28 11:04:54 -04003740}
3741##
3742
Cary Clark2ade9972017-11-02 17:49:34 -04003743#SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003744
3745##
3746
3747# ------------------------------------------------------------------------------
3748
3749#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
3750 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003751#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003752#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003753#Line # draws proportionally stretched Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003754
Cary Clark80247e52018-07-11 16:18:41 -04003755Draws Image image stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003756
3757Lattice lattice divides image into a rectangular grid.
3758Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003759of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003760size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003761dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003762
3763Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003764
Cary Clark682c58d2018-05-16 07:07:07 -04003765#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003766
3767If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3768just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003769SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003770outside of its bounds.
3771
3772#Param image Image containing pixels, dimensions, and format ##
3773#Param lattice division of bitmap into fixed and variable rectangles ##
3774#Param dst destination Rect of image to draw to ##
3775#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3776 and so on; or nullptr
3777##
Cary Clark8032b982017-07-28 11:04:54 -04003778
3779#Example
3780#Height 128
3781#Description
3782 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003783 The second image equals the size of center; only corners are drawn without scaling.
3784 The remaining images are larger than center. All corners draw without scaling. The sides
Cary Clark8032b982017-07-28 11:04:54 -04003785 are scaled if needed to take up the remaining space; the center is transparent.
3786##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003787void draw(SkCanvas* canvas) {
3788 SkIRect center = { 20, 10, 50, 40 };
3789 SkBitmap bitmap;
3790 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3791 SkCanvas bitCanvas(bitmap);
3792 SkPaint paint;
3793 SkColor gray = 0xFF000000;
3794 int left = 0;
3795 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3796 int top = 0;
3797 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3798 paint.setColor(gray);
3799 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3800 gray += 0x001f1f1f;
3801 top = bottom;
3802 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003803 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003804 }
Cary Clarkbad5ad72017-08-03 17:14:08 -04003805 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3806 SkImage* imagePtr = image.get();
3807 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3808 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3809 canvas->translate(dest + 4, 0);
3810 }
Cary Clark8032b982017-07-28 11:04:54 -04003811}
3812##
3813
Cary Clark2ade9972017-11-02 17:49:34 -04003814#SeeAlso drawBitmapLattice drawImage drawImageNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003815
3816##
3817
Cary Clark682c58d2018-05-16 07:07:07 -04003818#Subtopic Lattice ##
3819
Cary Clark08895c42018-02-01 09:37:32 -05003820#Subtopic Draw_Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003821
3822# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05003823#Subtopic Draw_Text
Cary Clark78de7512018-02-07 07:27:09 -05003824#Line # draws text into Canvas ##
3825##
Cary Clark8032b982017-07-28 11:04:54 -04003826
Mike Reedcb268f62019-01-07 12:51:32 -05003827#Method void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
3828 SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003829#In Draw_Text
3830#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003831#Line # draws text at (x, y), using font advance ##
Cary Clark09d80c02018-10-31 12:14:03 -04003832#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003833
3834#Example
3835#Height 200
3836#Description
Mike Reedcb268f62019-01-07 12:51:32 -05003837The same text is drawn varying Paint_Text_Size and varying
3838Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04003839##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003840void draw(SkCanvas* canvas) {
3841 SkPaint paint;
Mike Reedcb268f62019-01-07 12:51:32 -05003842 SkFont font;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003843 float textSizes[] = { 12, 18, 24, 36 };
3844 for (auto size: textSizes ) {
Mike Reedcb268f62019-01-07 12:51:32 -05003845 font.setSize(size);
Hal Canary35d14702019-01-15 11:57:41 -05003846 canvas->drawSimpleText("Aa", 2, kUTF8_SkTextEncoding, 10, 20, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003847 canvas->translate(0, size * 2);
3848 }
Mike Reedcb268f62019-01-07 12:51:32 -05003849 font.setSize(12);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003850 float yPos = 20;
3851 for (auto size: textSizes ) {
3852 float scale = size / 12.f;
3853 canvas->resetMatrix();
3854 canvas->translate(100, 0);
3855 canvas->scale(scale, scale);
Hal Canary35d14702019-01-15 11:57:41 -05003856 canvas->drawSimpleText("Aa", 2, kUTF8_SkTextEncoding,
3857 10 / scale, yPos / scale, font, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04003858 yPos += size * 2;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003859 }
3860}
Cary Clark8032b982017-07-28 11:04:54 -04003861##
3862
Mike Reed53a11f52019-01-03 12:18:06 -05003863#SeeAlso drawString drawTextBlob
Cary Clark8032b982017-07-28 11:04:54 -04003864
3865##
3866
Cary Clark8032b982017-07-28 11:04:54 -04003867# ------------------------------------------------------------------------------
3868
3869#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003870#In Draw_Text
3871#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003872#Line # draws text with arrays of positions and Paint ##
Cary Clark80247e52018-07-11 16:18:41 -04003873Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003874
Cary Clarkce101242017-09-01 15:51:02 -04003875blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clark3e73dcf2018-12-06 08:41:14 -05003876#font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04003877
Mike Reed0f9d33e2018-12-05 10:54:05 -05003878Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
Cary Clark3cd22cc2017-12-01 11:49:58 -05003879
Cary Clarkd2ca79c2018-08-10 13:09:13 -04003880Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha,
3881Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and
Cary Clark61313f32018-10-08 14:57:48 -04003882Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style:
Cary Clarkd2ca79c2018-08-10 13:09:13 -04003883Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width;
3884apply to Path created from blob.
Cary Clark8032b982017-07-28 11:04:54 -04003885
Cary Clarkce101242017-09-01 15:51:02 -04003886#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003887#Param x horizontal offset applied to blob ##
3888#Param y vertical offset applied to blob ##
3889#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003890
3891#Example
3892#Height 120
Cary Clarke80cd442018-07-17 13:19:56 -04003893void draw(SkCanvas* canvas) {
Mike Reed0f9d33e2018-12-05 10:54:05 -05003894 SkTextBlobBuilder textBlobBuilder;
3895 const char bunny[] = "/(^x^)\\";
3896 const int len = sizeof(bunny) - 1;
3897 uint16_t glyphs[len];
Mike Reed0f9d33e2018-12-05 10:54:05 -05003898 SkFont font;
Cary Clark26d173f2019-01-07 15:16:56 -05003899 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, len);
Mike Reed0f9d33e2018-12-05 10:54:05 -05003900 int runs[] = { 3, 1, 3 };
3901 SkPoint textPos = { 20, 100 };
3902 int glyphIndex = 0;
3903 for (auto runLen : runs) {
3904 font.setSize(1 == runLen ? 20 : 50);
3905 const SkTextBlobBuilder::RunBuffer& run =
3906 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY);
3907 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
Cary Clark26d173f2019-01-07 15:16:56 -05003908 font.setSize(1 == runLen ? 20 : 50);
3909 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen,
3910 SkTextEncoding::kGlyphID);
Mike Reed0f9d33e2018-12-05 10:54:05 -05003911 glyphIndex += runLen;
3912 }
3913 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clark26d173f2019-01-07 15:16:56 -05003914 canvas->drawTextBlob(blob.get(), 0, 0, SkPaint());
Cary Clarke80cd442018-07-17 13:19:56 -04003915}
Cary Clark8032b982017-07-28 11:04:54 -04003916##
3917
Mike Reed53a11f52019-01-03 12:18:06 -05003918#SeeAlso drawText
Cary Clark8032b982017-07-28 11:04:54 -04003919
3920##
3921
3922# ------------------------------------------------------------------------------
3923
Herb Derbyefe39bc2018-05-01 17:06:20 -04003924#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark8032b982017-07-28 11:04:54 -04003925
Cary Clark80247e52018-07-11 16:18:41 -04003926Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003927
Cary Clarkce101242017-09-01 15:51:02 -04003928blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clark3e73dcf2018-12-06 08:41:14 -05003929#font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04003930
Mike Reed0f9d33e2018-12-05 10:54:05 -05003931Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
Cary Clark3cd22cc2017-12-01 11:49:58 -05003932
Herb Derbyefe39bc2018-05-01 17:06:20 -04003933Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -04003934Image_Filter, and Draw_Looper; apply to blob.
3935
Cary Clarkce101242017-09-01 15:51:02 -04003936#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003937#Param x horizontal offset applied to blob ##
3938#Param y vertical offset applied to blob ##
3939#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003940
3941#Example
3942#Height 120
3943#Description
Cary Clark8032b982017-07-28 11:04:54 -04003944Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
3945##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003946 void draw(SkCanvas* canvas) {
3947 SkTextBlobBuilder textBlobBuilder;
Cary Clarkfc93eb02018-11-24 22:32:31 -05003948 SkFont font;
3949 font.setSize(50);
Herb Derbyefe39bc2018-05-01 17:06:20 -04003950 const SkTextBlobBuilder::RunBuffer& run =
Cary Clarkfc93eb02018-11-24 22:32:31 -05003951 textBlobBuilder.allocRun(font, 1, 20, 100);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003952 run.glyphs[0] = 20;
3953 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clarkfc93eb02018-11-24 22:32:31 -05003954 SkPaint paint;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003955 paint.setColor(SK_ColorBLUE);
3956 canvas->drawTextBlob(blob.get(), 0, 0, paint);
3957 }
Cary Clark8032b982017-07-28 11:04:54 -04003958##
3959
Mike Reed53a11f52019-01-03 12:18:06 -05003960#SeeAlso drawText
Cary Clark8032b982017-07-28 11:04:54 -04003961
3962##
3963
3964# ------------------------------------------------------------------------------
3965
Herb Derbyefe39bc2018-05-01 17:06:20 -04003966#Method void drawPicture(const SkPicture* picture)
Cary Clark78de7512018-02-07 07:27:09 -05003967#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003968#Line # draws Picture using Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04003969#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003970
3971#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04003972void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003973 SkPictureRecorder recorder;
3974 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
3975 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
3976 SkPaint paint;
3977 paint.setColor(color);
3978 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
3979 recordingCanvas->translate(10, 10);
3980 recordingCanvas->scale(1.2f, 1.4f);
3981 }
3982 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
Cary Clarkbad5ad72017-08-03 17:14:08 -04003983 canvas->drawPicture(playback);
3984 canvas->scale(2, 2);
3985 canvas->translate(50, 0);
3986 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04003987}
3988##
3989
Cary Clark2ade9972017-11-02 17:49:34 -04003990#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04003991
3992##
3993
3994# ------------------------------------------------------------------------------
3995
Herb Derbyefe39bc2018-05-01 17:06:20 -04003996#Method void drawPicture(const sk_sp<SkPicture>& picture)
Cary Clark09d80c02018-10-31 12:14:03 -04003997#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003998
3999#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004000void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004001 SkPictureRecorder recorder;
4002 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4003 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4004 SkPaint paint;
4005 paint.setColor(color);
4006 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4007 recordingCanvas->translate(10, 10);
4008 recordingCanvas->scale(1.2f, 1.4f);
4009 }
4010 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4011 canvas->drawPicture(playback);
4012 canvas->scale(2, 2);
4013 canvas->translate(50, 0);
4014 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004015}
4016##
4017
Cary Clark2ade9972017-11-02 17:49:34 -04004018#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004019
4020##
4021
4022# ------------------------------------------------------------------------------
4023
4024#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004025#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004026
4027#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004028void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004029 SkPaint paint;
4030 SkPictureRecorder recorder;
4031 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4032 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4033 paint.setColor(color);
4034 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4035 recordingCanvas->translate(10, 10);
4036 recordingCanvas->scale(1.2f, 1.4f);
4037 }
4038 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4039 const SkPicture* playbackPtr = playback.get();
4040 SkMatrix matrix;
4041 matrix.reset();
4042 for (auto alpha : { 70, 140, 210 } ) {
4043 paint.setAlpha(alpha);
4044 canvas->drawPicture(playbackPtr, &matrix, &paint);
4045 matrix.preTranslate(70, 70);
4046 }
Cary Clark8032b982017-07-28 11:04:54 -04004047}
4048##
4049
Cary Clark2ade9972017-11-02 17:49:34 -04004050#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004051
4052##
4053
4054# ------------------------------------------------------------------------------
4055
Herb Derbyefe39bc2018-05-01 17:06:20 -04004056#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004057#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004058
4059#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004060void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004061 SkPaint paint;
4062 SkPictureRecorder recorder;
4063 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4064 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4065 paint.setColor(color);
4066 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4067 recordingCanvas->translate(10, 10);
4068 recordingCanvas->scale(1.2f, 1.4f);
4069 }
4070 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4071 SkMatrix matrix;
4072 matrix.reset();
4073 for (auto alpha : { 70, 140, 210 } ) {
4074 paint.setAlpha(alpha);
4075 canvas->drawPicture(playback, &matrix, &paint);
4076 matrix.preTranslate(70, 70);
4077 }
Cary Clark8032b982017-07-28 11:04:54 -04004078}
4079##
4080
Cary Clark2ade9972017-11-02 17:49:34 -04004081#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004082
4083##
4084
4085# ------------------------------------------------------------------------------
4086
4087#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004088#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004089#Line # draws Vertices, a triangle mesh ##
Cary Clark09d80c02018-10-31 12:14:03 -04004090#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004091
4092#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004093void draw(SkCanvas* canvas) {
4094 SkPaint paint;
4095 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4096 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4097 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4098 SK_ARRAY_COUNT(points), points, nullptr, colors);
4099 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
4100}
Cary Clark8032b982017-07-28 11:04:54 -04004101##
4102
Cary Clark2ade9972017-11-02 17:49:34 -04004103#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004104
4105##
4106
4107# ------------------------------------------------------------------------------
4108
4109#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004110#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004111
4112#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004113void draw(SkCanvas* canvas) {
4114 SkPaint paint;
4115 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4116 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4117 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4118 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4119 SkShader::kClamp_TileMode));
4120 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4121 SK_ARRAY_COUNT(points), points, texs, colors);
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004122 canvas->drawVertices(vertices, SkBlendMode::kDarken, paint);
4123}
4124##
4125
4126#SeeAlso drawPatch drawPicture
4127
4128##
4129
4130# ------------------------------------------------------------------------------
4131
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004132#Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
4133 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004134#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004135
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004136#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004137void draw(SkCanvas* canvas) {
4138 SkPaint paint;
4139 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4140 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4141 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4142 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4143 { 1, 0, 0, 0 },
4144 { 2, 0, 0, 0 },
4145 { 3, 0, 0, 0 } };
4146 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4147 { 1.0f, 0.0f, 0.0f, 0.0f },
4148 { 1.0f, 0.0f, 0.0f, 0.0f },
4149 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004150 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4151 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4152 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4153 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004154 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4155 SkShader::kClamp_TileMode));
4156 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4157 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4158 canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
4159}
4160##
4161
4162#SeeAlso drawPatch drawPicture
4163
4164##
4165
4166# ------------------------------------------------------------------------------
4167
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004168#Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
4169 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004170#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004171
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004172#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004173void draw(SkCanvas* canvas) {
4174 SkPaint paint;
4175 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4176 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4177 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4178 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4179 { 1, 0, 0, 0 },
4180 { 2, 0, 0, 0 },
4181 { 3, 0, 0, 0 } };
4182 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4183 { 1.0f, 0.0f, 0.0f, 0.0f },
4184 { 1.0f, 0.0f, 0.0f, 0.0f },
4185 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004186 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4187 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4188 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4189 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004190 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4191 SkShader::kClamp_TileMode));
4192 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4193 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4194 canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004195}
4196##
4197
Cary Clark2ade9972017-11-02 17:49:34 -04004198#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004199
4200##
4201
4202# ------------------------------------------------------------------------------
4203
4204#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
4205 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004206#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004207#Line # draws Coons_Patch ##
Cary Clark09d80c02018-10-31 12:14:03 -04004208#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004209
4210#Example
4211#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04004212void draw(SkCanvas* canvas) {
4213 // SkBitmap source = cmbkygk;
4214 SkPaint paint;
4215 paint.setFilterQuality(kLow_SkFilterQuality);
4216 paint.setAntiAlias(true);
4217 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4218 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4219 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4220 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4221 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
4222 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
4223 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4224 SkShader::kClamp_TileMode, nullptr));
4225 canvas->scale(15, 15);
4226 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
4227 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
4228 canvas->translate(4, 4);
4229 }
Cary Clark8032b982017-07-28 11:04:54 -04004230}
4231##
4232
Cary Clark2ade9972017-11-02 17:49:34 -04004233#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004234#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004235
4236##
4237
4238# ------------------------------------------------------------------------------
4239
4240#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004241 const SkPoint texCoords[4], const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004242#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004243
4244#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004245void draw(SkCanvas* canvas) {
4246 SkPaint paint;
4247 paint.setAntiAlias(true);
4248 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4249 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4250 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4251 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4252 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4253 canvas->scale(30, 30);
4254 canvas->drawPatch(cubics, colors, nullptr, paint);
4255 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
4256 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
4257 {0.5f,3.2f} };
Mike Reed33535cb2019-01-09 11:25:18 -05004258
4259 SkFont font(nullptr, 18.f / 30);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004260 for (int i = 0; i< 10; ++i) {
4261 char digit = '0' + i;
Mike Reed33535cb2019-01-09 11:25:18 -05004262 canvas->drawSimpleText(&digit, kUTF8_SkTextEncoding, 1, text[i].fX, text[i].fY, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004263 }
Mike Reed33535cb2019-01-09 11:25:18 -05004264 canvas->drawString("10", text[10].fX, text[10].fY, font, paint);
4265 canvas->drawString("11", text[11].fX, text[11].fY, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004266 paint.setStyle(SkPaint::kStroke_Style);
4267 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
4268 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004269}
4270##
4271
4272#Example
4273#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04004274void draw(SkCanvas* canvas) {
4275 // SkBitmap source = checkerboard;
4276 SkPaint paint;
4277 paint.setFilterQuality(kLow_SkFilterQuality);
4278 paint.setAntiAlias(true);
4279 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4280 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4281 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4282 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4283 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
4284 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4285 SkShader::kClamp_TileMode, nullptr));
4286 canvas->scale(30, 30);
4287 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004288}
4289##
4290
Cary Clark2ade9972017-11-02 17:49:34 -04004291#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004292#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004293
4294##
4295
4296# ------------------------------------------------------------------------------
4297
4298#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
4299 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
4300 const SkPaint* paint)
Cary Clark78de7512018-02-07 07:27:09 -05004301#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004302#Line # draws sprites using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04004303#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004304
4305#Example
4306#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004307void draw(SkCanvas* canvas) {
4308 // SkBitmap source = mandrill;
4309 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4310 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4311 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4312 const SkImage* imagePtr = image.get();
4313 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004314}
4315##
4316
Cary Clark2ade9972017-11-02 17:49:34 -04004317#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004318
4319##
4320
4321# ------------------------------------------------------------------------------
4322
4323#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
4324 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004325 const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004326#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004327
4328#Example
4329#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004330void draw(SkCanvas* canvas) {
4331 // SkBitmap source = mandrill;
4332 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4333 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4334 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4335 SkPaint paint;
4336 paint.setAlpha(127);
4337 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04004338}
4339##
4340
4341#ToDo bug in example on cpu side, gpu looks ok ##
4342
Cary Clark2ade9972017-11-02 17:49:34 -04004343#SeeAlso drawBitmap drawImage
4344
Cary Clark8032b982017-07-28 11:04:54 -04004345##
4346
4347# ------------------------------------------------------------------------------
4348
4349#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004350 const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004351#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004352
4353#Example
4354#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004355void draw(SkCanvas* canvas) {
4356 // sk_sp<SkImage> image = mandrill;
4357 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4358 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4359 const SkImage* imagePtr = image.get();
4360 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004361}
4362##
4363
Cary Clark2ade9972017-11-02 17:49:34 -04004364#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004365
4366##
4367
4368# ------------------------------------------------------------------------------
4369
4370#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004371 int count, const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004372#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004373
4374#Example
4375#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004376void draw(SkCanvas* canvas) {
4377 // sk_sp<SkImage> image = mandrill;
4378 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
4379 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
4380 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004381}
4382##
4383
Cary Clark2ade9972017-11-02 17:49:34 -04004384#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004385
4386##
4387
4388# ------------------------------------------------------------------------------
4389
Cary Clark73fa9722017-08-29 17:36:51 -04004390#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -05004391#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004392#Line # draws Drawable, encapsulated drawing commands ##
Cary Clark09d80c02018-10-31 12:14:03 -04004393#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004394
4395#Example
4396#Height 100
4397#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004398struct MyDrawable : public SkDrawable {
4399 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4400
4401 void onDraw(SkCanvas* canvas) override {
4402 SkPath path;
4403 path.conicTo(10, 90, 50, 90, 0.9f);
4404 SkPaint paint;
4405 paint.setColor(SK_ColorBLUE);
4406 canvas->drawRect(path.getBounds(), paint);
4407 paint.setAntiAlias(true);
4408 paint.setColor(SK_ColorWHITE);
4409 canvas->drawPath(path, paint);
4410 }
4411};
4412
4413#Function ##
4414void draw(SkCanvas* canvas) {
4415 sk_sp<SkDrawable> drawable(new MyDrawable);
4416 SkMatrix matrix;
4417 matrix.setTranslate(10, 10);
4418 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04004419}
4420##
4421
Cary Clark2ade9972017-11-02 17:49:34 -04004422#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004423
4424##
4425
4426# ------------------------------------------------------------------------------
4427
4428#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
Cary Clark09d80c02018-10-31 12:14:03 -04004429#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004430
4431#Example
4432#Height 100
4433#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004434struct MyDrawable : public SkDrawable {
4435 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4436
4437 void onDraw(SkCanvas* canvas) override {
4438 SkPath path;
4439 path.conicTo(10, 90, 50, 90, 0.9f);
4440 SkPaint paint;
4441 paint.setColor(SK_ColorBLUE);
4442 canvas->drawRect(path.getBounds(), paint);
4443 paint.setAntiAlias(true);
4444 paint.setColor(SK_ColorWHITE);
4445 canvas->drawPath(path, paint);
4446 }
4447};
4448
4449#Function ##
4450void draw(SkCanvas* canvas) {
4451 sk_sp<SkDrawable> drawable(new MyDrawable);
4452 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04004453}
4454##
4455
Cary Clark2ade9972017-11-02 17:49:34 -04004456#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004457
4458##
4459
4460# ------------------------------------------------------------------------------
4461
4462#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
Cary Clark78de7512018-02-07 07:27:09 -05004463#In Draw
4464#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004465#Line # associates a Rect with a key-value pair ##
Cary Clark09d80c02018-10-31 12:14:03 -04004466#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004467
4468#Example
4469 #Height 1
4470 const char text[] = "Click this link!";
4471 SkRect bounds;
4472 SkPaint paint;
Cary Clark26d173f2019-01-07 15:16:56 -05004473 SkFont font(nullptr, 40);
4474 (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Cary Clark8032b982017-07-28 11:04:54 -04004475 const char url[] = "https://www.google.com/";
4476 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4477 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4478##
4479
Cary Clark2ade9972017-11-02 17:49:34 -04004480#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004481
4482##
4483
4484# ------------------------------------------------------------------------------
4485
Herb Derbyefe39bc2018-05-01 17:06:20 -04004486#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
Cary Clark09d80c02018-10-31 12:14:03 -04004487#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004488
4489#Example
4490#Height 1
4491 const char text[] = "Click this link!";
4492 SkRect bounds;
4493 SkPaint paint;
Cary Clark26d173f2019-01-07 15:16:56 -05004494 SkFont font(nullptr, 40);
4495 (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Cary Clark8032b982017-07-28 11:04:54 -04004496 const char url[] = "https://www.google.com/";
4497 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4498 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4499##
4500
Cary Clark2ade9972017-11-02 17:49:34 -04004501#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004502
4503##
4504
Cary Clark8032b982017-07-28 11:04:54 -04004505# ------------------------------------------------------------------------------
4506
4507#Method virtual bool isClipEmpty() const
Cary Clark78de7512018-02-07 07:27:09 -05004508#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004509#Line # returns if Clip is empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004510#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004511
4512#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004513 void draw(SkCanvas* canvas) {
4514 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
4515 SkPath path;
4516 canvas->clipPath(path);
4517 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004518 }
4519 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004520 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04004521 clip is empty
4522 ##
4523##
4524
Cary Clark2ade9972017-11-02 17:49:34 -04004525#SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004526
4527##
4528
4529# ------------------------------------------------------------------------------
4530
4531#Method virtual bool isClipRect() const
Cary Clark78de7512018-02-07 07:27:09 -05004532#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004533#Line # returns if Clip is Rect and not empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004534#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004535
4536#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004537 void draw(SkCanvas* canvas) {
4538 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
4539 canvas->clipRect({0, 0, 0, 0});
4540 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004541 }
4542 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004543 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04004544 clip is not rect
4545 ##
4546##
4547
Cary Clark2ade9972017-11-02 17:49:34 -04004548#SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004549
4550##
4551
4552#Class SkCanvas ##
Cary Clark884dd7d2017-10-11 10:37:52 -04004553
Cary Clark8032b982017-07-28 11:04:54 -04004554#Topic Canvas ##