blob: d3121ba899ccc0a7286198bd64168e541187d799 [file] [log] [blame]
Cary Clark8032b982017-07-28 11:04:54 -04001#Topic Canvas
Cary Clark12799e12017-07-28 15:18:29 -04002#Alias Canvas_Reference
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clarke4aa3712017-09-15 02:56:12 -04004#Class SkCanvas
5
Cary Clark8032b982017-07-28 11:04:54 -04006Canvas provides an interface for drawing, and how the drawing is clipped and transformed.
7Canvas contains a stack of Matrix and Clip values.
8
9Canvas and Paint together provide the state to draw into Surface or Device.
Cary Clarkbad5ad72017-08-03 17:14:08 -040010Each Canvas draw call transforms the geometry of the object by the concatenation of all
11Matrix values in the stack. The transformed geometry is clipped by the intersection
12of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing
13state such as Color, Typeface, text size, stroke width, Shader and so on.
Cary Clark8032b982017-07-28 11:04:54 -040014
15To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
16Request Canvas from Surface to obtain the interface to draw.
17Canvas generated by Raster_Surface draws to memory visible to the CPU.
18Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
19
Cary Clarkbad5ad72017-08-03 17:14:08 -040020To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
Cary Clarkce101242017-09-01 15:51:02 -040021Document based Canvas and other Canvas Subclasses reference Device describing the
Cary Clarkbad5ad72017-08-03 17:14:08 -040022destination.
23
Cary Clark8032b982017-07-28 11:04:54 -040024Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
25This approach may be deprecated in the future.
26
Cary Clark8032b982017-07-28 11:04:54 -040027#Topic Overview
28
29#Subtopic Subtopics
30#Table
31#Legend
32# topics # description ##
33#Legend ##
34#ToDo generate a TOC here ##
35#Table ##
36#Subtopic ##
37
38#Subtopic Constants
39#Table
40#Legend
41# constants # description ##
42#Legend ##
43# Lattice::Flags # Controls Lattice transparency. ##
44# PointMode # Sets drawPoints options. ##
45# SaveLayerFlags # Sets SaveLayerRec options. ##
46# SrcRectConstraint # Sets drawImageRect options. ##
47#Table ##
48#Subtopic ##
49
50#Subtopic Structs
51#Table
52#Legend
53# struct # description ##
54#Legend ##
55# Lattice # Divides Bitmap, Image into a rectangular grid. ##
Cary Clarkce101242017-09-01 15:51:02 -040056# SaveLayerRec # Contains state to create Layer. ##
Cary Clark8032b982017-07-28 11:04:54 -040057#Table ##
58#Subtopic ##
59
60#Subtopic Constructors
61
62Create the desired type of Surface to obtain its Canvas when possible. Constructors are useful
63when no Surface is required, and some helpers implicitly create Raster_Surface.
64
65#Table
66#Legend
67# # description ##
68#Legend ##
69# SkCanvas() # No Surface, no dimensions. ##
Cary Clark73fa9722017-08-29 17:36:51 -040070# SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr) # No Surface, set dimensions, Surface_Properties. ##
Cary Clark8032b982017-07-28 11:04:54 -040071# SkCanvas(SkBaseDevice* device) # Existing Device. (SkBaseDevice is private.) ##
72# SkCanvas(const SkBitmap& bitmap) # Uses existing Bitmap. ##
73# SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) # Uses existing Bitmap and Surface_Properties. ##
74# MakeRasterDirect # Creates from SkImageInfo and Pixel_Storage. ##
75# MakeRasterDirectN32 # Creates from image data and Pixel_Storage. ##
76#ToDo incomplete ##
77#Table ##
78#Subtopic ##
79
80#Subtopic Member_Functions
81#Table
82#Legend
83# function # description ##
84#Legend ##
85# accessTopLayerPixels # Returns writable pixel access if available. ##
86# accessTopRasterHandle # Returns context that tracks Clip and Matrix. ##
87# clear() # Fills Clip with Color. ##
88# clipPath # Combines Clip with Path. ##
89# clipRRect # Combines Clip with Round_Rect. ##
90# clipRect # Combines Clip with Rect. ##
91# clipRegion # Combines Clip with Region. ##
92# concat() # Multiplies Matrix by Matrix. ##
93# discard() # Makes Canvas contents undefined. ##
94# drawAnnotation # Associates a Rect with a key-value pair.##
95# drawArc # Draws Arc using Clip, Matrix, and Paint.##
96# drawAtlas # Draws sprites using Clip, Matrix, and Paint.##
97# drawBitmap # Draws Bitmap at (x, y) position. ##
Cary Clarkd0530ba2017-09-14 11:25:39 -040098# drawBitmapLattice # Draws proportionally stretched Bitmap. ##
Cary Clark8032b982017-07-28 11:04:54 -040099# drawBitmapNine # Draws Nine_Patch Bitmap. ##
100# drawBitmapRect # Draws Bitmap, source Rect to destination Rect. ##
101# drawCircle # Draws Circle using Clip, Matrix, and Paint. ##
102# drawColor # Fills Clip with Color and Blend_Mode. ##
103# drawDRRect # Draws double Round_Rect stroked or filled. ##
104# drawDrawable # Draws Drawable, encapsulated drawing commands. ##
105# drawIRect # Draws IRect using Clip, Matrix, and Paint. ##
106# drawImage # Draws Image at (x, y) position. ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400107# drawImageLattice # Draws proportionally stretched Image. ##
Cary Clark8032b982017-07-28 11:04:54 -0400108# drawImageNine # Draws Nine_Patch Image. ##
109# drawImageRect # Draws Image, source Rect to destination Rect. ##
110# drawLine # Draws line segment between two points.##
111# drawOval # Draws Oval using Clip, Matrix, and Paint. ##
112# drawPaint # Fills Clip with Paint. ##
Cary Clarkce101242017-09-01 15:51:02 -0400113# drawPatch # Draws Coons patch. ##
Cary Clark8032b982017-07-28 11:04:54 -0400114# drawPath # Draws Path using Clip, Matrix, and Paint. ##
115# drawPicture # Draws Picture using Clip and Matrix. ##
116# drawPoint # Draws point at (x, y) position. ##
117# drawPoints # Draws array as points, lines, polygon. ##
118# drawPosText # Draws text at array of (x, y) positions. ##
119# drawPosTextH # Draws text at x positions with common baseline. ##
120# drawRRect # Draws Round_Rect using Clip, Matrix, and Paint. ##
121# drawRect # Draws Rect using Clip, Matrix, and Paint. ##
122# drawRegion # Draws Region using Clip, Matrix, and Paint. ##
123# drawRoundRect # Draws Round_Rect using Clip, Matrix, and Paint. ##
124# drawText # Draws text at (x, y), using font advance. ##
125# drawTextBlob # Draws text with arrays of positions and Paint. ##
126# drawTextOnPath # Draws text following Path contour. ##
127# drawTextOnPathHV # Draws text following Path with offsets. ##
128# drawTextRSXform # Draws text with array of RSXform. ##
129# drawString # Draws null terminated string at (x, y) using font advance. ##
130# drawVertices # Draws Vertices, a triangle mesh. ##
131# flush() # Triggers execution of all pending draw operations. ##
Cary Clarkce101242017-09-01 15:51:02 -0400132# getBaseLayerSize # Gets size of base Layer in global coordinates. ##
Cary Clark8032b982017-07-28 11:04:54 -0400133# getDeviceClipBounds # Returns IRect bounds of Clip. ##
134# getDrawFilter # Legacy; to be deprecated. ##
135# getGrContext # Returns GPU_Context of the GPU_Surface. ##
136# getLocalClipBounds # Returns Clip bounds in source coordinates. ##
137# getMetaData # Associates additional data with the canvas. ##
138# getProps # Copies Surface_Properties if available. ##
139# getSaveCount # Returns depth of stack containing Clip and Matrix. ##
140# getTotalMatrix # Returns Matrix. ##
141# imageInfo # Returns Image_Info for Canvas. ##
142# isClipEmpty # Returns if Clip is empty. ##
143# isClipRect # Returns if Clip is Rect and not empty. ##
144# MakeRasterDirect # Creates Canvas from SkImageInfo and pixel data. ##
145# MakeRasterDirectN32 # Creates Canvas from image specifications and pixel data. ##
146# makeSurface # Creates Surface matching SkImageInfo and SkSurfaceProps. ##
147# peekPixels # Returns if Canvas has direct access to its pixels. ##
148# quickReject # Returns if Rect is outside Clip. ##
149# readPixels # Copies and converts rectangle of pixels from Canvas. ##
150# resetMatrix # Resets Matrix to identity. ##
151# restore() # Restores changes to Clip and Matrix, pops save stack. ##
152# restoreToCount # Restores changes to Clip and Matrix to given depth. ##
153# rotate() # Rotates Matrix. ##
154# save() # Saves Clip and Matrix on stack. ##
Cary Clarkce101242017-09-01 15:51:02 -0400155# saveLayer # Saves Clip and Matrix on stack; creates Layer. ##
156# saveLayerAlpha # Saves Clip and Matrix on stack; creates Layer; sets opacity. ##
157# saveLayerPreserveLCDTextRequests # Saves Clip and Matrix on stack; creates Layer for LCD text. ##
Cary Clark8032b982017-07-28 11:04:54 -0400158# scale() # Scales Matrix. ##
159# setAllowSimplifyClip # Experimental. ##
160# setDrawFilter # Legacy; to be deprecated. ##
161# setMatrix # Sets Matrix. ##
162# skew() # Skews Matrix. #
163# translate() # Translates Matrix. ##
164# writePixels # Copies and converts rectangle of pixels to Canvas. ##
165#Table ##
166#Subtopic ##
167
168#Topic Overview ##
169
170# ------------------------------------------------------------------------------
171
172#Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info,
173 void* pixels, size_t rowBytes)
174
Cary Clarkbad5ad72017-08-03 17:14:08 -0400175Allocates raster Canvas that will draw directly into pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400176To access pixels after drawing, call flush() or peekPixels.
177
Cary Clarkbad5ad72017-08-03 17:14:08 -0400178Canvas is returned if all parameters are valid.
179Valid parameters include:
180info dimensions are zero or positive;
181info contains Image_Color_Type and Image_Alpha_Type supported by Raster_Surface;
182pixels is not nullptr;
183rowBytes is zero or large enough to contain info width pixels of Image_Color_Type.
184
Cary Clarkf05bdda2017-08-24 12:59:48 -0400185Pass zero for rowBytes to compute rowBytes from info width and size of pixel.
186If rowBytes is greater than zero, it must be equal to or greater than
187info width times bytes required for Image_Color_Type.
188
189Pixel buffer size should be info height times computed rowBytes.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400190
191#Param info width, height, Image_Color_Type, Image_Alpha_Type, Color_Space, of Raster_Surface;
192 width, or height, or both, may be zero
Cary Clark8032b982017-07-28 11:04:54 -0400193##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400194#Param pixels pointer to destination pixels buffer
Cary Clark8032b982017-07-28 11:04:54 -0400195##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400196#Param rowBytes interval from one Surface row to the next, or zero
Cary Clark8032b982017-07-28 11:04:54 -0400197##
198
Cary Clarkbad5ad72017-08-03 17:14:08 -0400199#Return Canvas if all parameters are valid; otherwise, nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -0400200
201#Example
202 #Description
203 Allocates a three by three bitmap, clears it to white, and draws a black pixel
204 in the center.
205 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400206void draw(SkCanvas* ) {
Cary Clarkce101242017-09-01 15:51:02 -0400207 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied
Cary Clarkbad5ad72017-08-03 17:14:08 -0400208 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row
209 const size_t size = info.getSafeSize(minRowBytes); // bytes used by all rows
210 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels
211 SkPMColor* pixels = storage.get(); // get pointer to allocated storage
212 // create a SkCanvas backed by a raster device, and delete it when the
213 // function goes out of scope.
214 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
Cary Clarkce101242017-09-01 15:51:02 -0400215 canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clarkbad5ad72017-08-03 17:14:08 -0400216 canvas->flush(); // ensure that pixels are cleared
Cary Clarkce101242017-09-01 15:51:02 -0400217 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clarkbad5ad72017-08-03 17:14:08 -0400218 SkPaint paint; // by default, draws black
219 canvas->drawPoint(1, 1, paint); // draw in the center
220 canvas->flush(); // ensure that point was drawn
221 for (int y = 0; y < info.height(); ++y) {
222 for (int x = 0; x < info.width(); ++x) {
223 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
224 }
225 SkDebugf("\n");
226 }
Cary Clark8032b982017-07-28 11:04:54 -0400227}
228 #StdOut
229 ---
230 -x-
231 ---
232 ##
233##
234
235#ToDo incomplete ##
236
237#SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
238##
239
240# ------------------------------------------------------------------------------
241
242#Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
243 size_t rowBytes)
244
Cary Clarkbad5ad72017-08-03 17:14:08 -0400245Allocates raster Canvas specified by inline image specification. Subsequent Canvas
246calls draw into pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400247Image_Color_Type is set to kN32_SkColorType.
248Image_Alpha_Type is set to kPremul_SkAlphaType.
249To access pixels after drawing, call flush() or peekPixels.
250
Cary Clarkbad5ad72017-08-03 17:14:08 -0400251Canvas is returned if all parameters are valid.
252Valid parameters include:
Cary Clarkf05bdda2017-08-24 12:59:48 -0400253width and height are zero or positive;
Cary Clarkbad5ad72017-08-03 17:14:08 -0400254pixels is not nullptr;
Cary Clarkf05bdda2017-08-24 12:59:48 -0400255rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400256
Cary Clarkce101242017-09-01 15:51:02 -0400257Pass zero for rowBytes to compute rowBytes from width and size of pixel.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400258If rowBytes is greater than zero, it must be equal to or greater than
259width times bytes required for Image_Color_Type.
260
261Pixel buffer size should be height times rowBytes.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400262
263#Param width pixel column count on Raster_Surface created; must be zero or greater ##
264#Param height pixel row count on Raster_Surface created.; must be zero or greater ##
265#Param pixels pointer to destination pixels buffer; buffer size should be height
Cary Clarkf05bdda2017-08-24 12:59:48 -0400266 times rowBytes
Cary Clark8032b982017-07-28 11:04:54 -0400267##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400268#Param rowBytes interval from one Surface row to the next, or zero
Cary Clark8032b982017-07-28 11:04:54 -0400269##
270
Cary Clarkbad5ad72017-08-03 17:14:08 -0400271#Return Canvas if all parameters are valid; otherwise, nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -0400272
273#Example
274 #Description
275 Allocates a three by three bitmap, clears it to white, and draws a black pixel
276 in the center.
277 ##
278void draw(SkCanvas* ) {
279 const int width = 3;
280 const int height = 3;
Cary Clarkce101242017-09-01 15:51:02 -0400281 SkPMColor pixels[height][width]; // allocate a 3x3 Premultiplied bitmap on the stack
Cary Clark8032b982017-07-28 11:04:54 -0400282 // create a SkCanvas backed by a raster device, and delete it when the
283 // function goes out of scope.
284 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
285 width,
286 height,
287 pixels[0], // top left of the bitmap
288 sizeof(pixels[0])); // byte width of the each row
Cary Clarkce101242017-09-01 15:51:02 -0400289 // write a premultiplied value for white into all pixels in the bitmap
Cary Clark8032b982017-07-28 11:04:54 -0400290 canvas->clear(SK_ColorWHITE);
Cary Clarkce101242017-09-01 15:51:02 -0400291 SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400292 SkPaint paint; // by default, draws black
293 canvas->drawPoint(1, 1, paint); // draw in the center
294 canvas->flush(); // ensure that pixels is ready to be read
295 for (int y = 0; y < height; ++y) {
296 for (int x = 0; x < width; ++x) {
297 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
298 }
299 SkDebugf("\n");
300 }
301}
302 #StdOut
303 ---
304 -x-
305 ---
306 ##
307##
308
309#ToDo incomplete ##
310
311##
312
313# ------------------------------------------------------------------------------
314
315#Method SkCanvas()
316
Cary Clarkd0530ba2017-09-14 11:25:39 -0400317Creates an empty Canvas with no backing device or pixels, with
Cary Clarkf05bdda2017-08-24 12:59:48 -0400318a width and height of zero.
Cary Clark8032b982017-07-28 11:04:54 -0400319
Cary Clarkd0530ba2017-09-14 11:25:39 -0400320#Return empty Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400321
322#Example
323
324#Description
325Passes a placeholder to a function that requires one.
326##
327
328#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -0400329// Returns true if either the canvas rotates the text by 90 degrees, or the paint does.
330static void check_for_up_and_down_text(const SkCanvas* canvas, const SkPaint& paint) {
331 bool paintHasVertical = paint.isVerticalText();
332 const SkMatrix& matrix = canvas->getTotalMatrix();
333 bool matrixIsVertical = matrix.preservesRightAngles() && !matrix.isScaleTranslate();
334 SkDebugf("paint draws text %s\n", paintHasVertical != matrixIsVertical ?
335 "top to bottom" : "left to right");
336}
337
338static void check_for_up_and_down_text(const SkPaint& paint) {
339 SkCanvas canvas; // placeholder only, does not have an associated device
340 check_for_up_and_down_text(&canvas, paint);
341}
342
Cary Clark8032b982017-07-28 11:04:54 -0400343##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400344void draw(SkCanvas* canvas) {
345 SkPaint paint;
346 check_for_up_and_down_text(paint); // paint draws text left to right
347 paint.setVerticalText(true);
348 check_for_up_and_down_text(paint); // paint draws text top to bottom
349 paint.setVerticalText(false);
350 canvas->rotate(90);
351 check_for_up_and_down_text(canvas, paint); // paint draws text top to bottom
352}
Cary Clark8032b982017-07-28 11:04:54 -0400353
354 #StdOut
355 paint draws text left to right
356 paint draws text top to bottom
357 paint draws text top to bottom
358 ##
359##
360
361#ToDo incomplete ##
362
363##
364
365# ------------------------------------------------------------------------------
366
Cary Clark73fa9722017-08-29 17:36:51 -0400367#Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -0400368
369Creates Canvas of the specified dimensions without a Surface.
Cary Clarkce101242017-09-01 15:51:02 -0400370Used by Subclasses with custom implementations for draw methods.
Cary Clark8032b982017-07-28 11:04:54 -0400371
Cary Clarkd0530ba2017-09-14 11:25:39 -0400372If props equals nullptr, Surface_Properties are created with
373Surface_Properties_Legacy_Font_Host settings, which choose the pixel striping
374direction and order. Since a platform may dynamically change its direction when
375the device is rotated, and since a platform may have multiple monitors with
376different characteristics, it is best not to rely on this legacy behavior.
Cary Clark8032b982017-07-28 11:04:54 -0400377
Cary Clarkbad5ad72017-08-03 17:14:08 -0400378#Param width zero or greater ##
379#Param height zero or greater ##
380#Param props LCD striping orientation and setting for device independent fonts;
381 may be nullptr
382##
383
384#Return Canvas placeholder with dimensions ##
Cary Clark8032b982017-07-28 11:04:54 -0400385
386#Example
387 SkCanvas canvas(10, 20); // 10 units wide, 20 units high
388 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device
389 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
390
391 #StdOut
392 canvas is empty
393 ##
394##
395
Cary Clarkbad5ad72017-08-03 17:14:08 -0400396#SeeAlso SkSurfaceProps SkPixelGeometry
Cary Clark8032b982017-07-28 11:04:54 -0400397
398##
399
400# ------------------------------------------------------------------------------
401
402#Method explicit SkCanvas(SkBaseDevice* device)
403
404Construct a canvas that draws into device.
405Used by child classes of SkCanvas.
406
407#ToDo Since SkBaseDevice is private, shouldn't this be private also? ##
408
Cary Clarkbad5ad72017-08-03 17:14:08 -0400409#Param device specifies a device for the canvas to draw into ##
Cary Clark8032b982017-07-28 11:04:54 -0400410
Cary Clarkbad5ad72017-08-03 17:14:08 -0400411#Return Canvas that can be used to draw into device ##
Cary Clark8032b982017-07-28 11:04:54 -0400412
413#Example
414#Error "Unsure how to create a meaningful example."
415 SkPDFCanvas::SkPDFCanvas(const sk_sp<SkPDFDevice>& dev)
416 : SkCanvas(dev.get()) {}
417##
418
419#ToDo either remove doc of figure out a way to fiddle it ##
420
421##
422
423# ------------------------------------------------------------------------------
424
425#Method explicit SkCanvas(const SkBitmap& bitmap)
426
427Construct a canvas that draws into bitmap.
428Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed Surface.
429
Cary Clarkbad5ad72017-08-03 17:14:08 -0400430Bitmap is copied so that subsequently editing bitmap will not affect
431constructed Canvas.
432
433May be deprecated in the future.
434
Cary Clark8032b982017-07-28 11:04:54 -0400435#ToDo Should be deprecated? ##
436
Cary Clarkbad5ad72017-08-03 17:14:08 -0400437#Param bitmap width, height, Image_Color_Type, Image_Alpha_Type, and pixel
438 storage of Raster_Surface
Cary Clark8032b982017-07-28 11:04:54 -0400439##
440
Cary Clarkbad5ad72017-08-03 17:14:08 -0400441#Return Canvas that can be used to draw into bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -0400442
443#Example
444#Description
445The actual output depends on the installed fonts.
446##
447 SkBitmap bitmap;
448 // create a bitmap 5 wide and 11 high
449 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
450 SkCanvas canvas(bitmap);
Cary Clarkce101242017-09-01 15:51:02 -0400451 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400452 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
453 if (!canvas.peekPixels(&pixmap)) {
454 SkDebugf("peekPixels should never fail.\n");
455 }
456 const SkPMColor* pixels = pixmap.addr32(); // points to top left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400457 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400458 SkPaint paint; // by default, draws black, 12 point text
459 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
460 for (int y = 0; y < bitmap.height(); ++y) {
461 for (int x = 0; x < bitmap.width(); ++x) {
462 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
463 }
464 SkDebugf("\n");
465 }
466
467 #StdOut
Cary Clarkd0530ba2017-09-14 11:25:39 -0400468 -----
469 ---x-
470 ---x-
471 ---x-
472 ---x-
473 ---x-
474 ---x-
475 -----
476 ---x-
477 ---x-
Cary Clark8032b982017-07-28 11:04:54 -0400478 -----
479 #StdOut ##
480##
481
482#ToDo incomplete ##
483
484##
485
Cary Clarkbad5ad72017-08-03 17:14:08 -0400486#EnumClass ColorBehavior
Cary Clark8032b982017-07-28 11:04:54 -0400487
488#Private
489Android framework only.
490##
491
492#Code
493 enum class ColorBehavior {
494 kLegacy,
495 };
496##
497#Const kLegacy 0
Cary Clarkbad5ad72017-08-03 17:14:08 -0400498 Is a placeholder to allow specialized constructor; has no meaning.
Cary Clark8032b982017-07-28 11:04:54 -0400499##
500##
501
Cary Clarkbad5ad72017-08-03 17:14:08 -0400502#Method SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior)
503
504#Private
505Android framework only.
506##
507
508#Param bitmap specifies a bitmap for the canvas to draw into ##
509#Param behavior specializes this constructor; value is unused ##
510#Return Canvas that can be used to draw into bitmap ##
511
512#NoExample
513##
514##
Cary Clark8032b982017-07-28 11:04:54 -0400515
516# ------------------------------------------------------------------------------
517
518#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
519
520Construct a canvas that draws into bitmap.
521Use props to match the device characteristics, like LCD striping.
522
Cary Clarkbad5ad72017-08-03 17:14:08 -0400523bitmap is copied so that subsequently editing bitmap will not affect
524constructed Canvas.
525
526#Param bitmap width, height, Image_Color_Type, Image_Alpha_Type,
527 and pixel storage of Raster_Surface
Cary Clark8032b982017-07-28 11:04:54 -0400528##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400529#Param props order and orientation of RGB striping; and whether to use
530 device independent fonts
Cary Clark8032b982017-07-28 11:04:54 -0400531##
532
Cary Clarkbad5ad72017-08-03 17:14:08 -0400533#Return Canvas that can be used to draw into bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -0400534
535#Example
536#Description
537The actual output depends on the installed fonts.
538##
539 SkBitmap bitmap;
540 // create a bitmap 5 wide and 11 high
541 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
542 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
Cary Clarkce101242017-09-01 15:51:02 -0400543 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400544 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
545 if (!canvas.peekPixels(&pixmap)) {
546 SkDebugf("peekPixels should never fail.\n");
547 }
548 const SkPMColor* pixels = pixmap.addr32(); // points to top left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400549 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400550 SkPaint paint; // by default, draws black, 12 point text
551 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
552 for (int y = 0; y < bitmap.height(); ++y) {
553 for (int x = 0; x < bitmap.width(); ++x) {
554 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
555 }
556 SkDebugf("\n");
557 }
558
559 #StdOut
560 -----
561 ---x-
562 ---x-
563 ---x-
564 ---x-
565 ---x-
566 ---x-
567 -----
568 ---x-
569 ---x-
570 -----
571 #StdOut ##
572##
573
574#ToDo incomplete ##
575
576##
577
578# ------------------------------------------------------------------------------
579
580#Method virtual ~SkCanvas()
581
Cary Clarkce101242017-09-01 15:51:02 -0400582Draw saved Layers, if any.
Cary Clark8032b982017-07-28 11:04:54 -0400583Free up resources used by Canvas.
584
585#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -0400586#Description
Cary Clarkce101242017-09-01 15:51:02 -0400587Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
588drawing surface that blends with the bitmap. When Layer goes out of
589scope, Layer Destructor is called. The saved Layer is restored, drawing
Cary Clarkbad5ad72017-08-03 17:14:08 -0400590transparent letters.
591##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400592void draw(SkCanvas* canvas) {
593 SkBitmap bitmap;
594 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
595 {
596 SkCanvas offscreen(bitmap);
597 SkPaint paint;
598 paint.setTextSize(100);
599 offscreen.drawString("ABC", 20, 160, paint);
600 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
601 offscreen.saveLayerAlpha(&layerBounds, 128);
602 offscreen.clear(SK_ColorWHITE);
603 offscreen.drawString("DEF", 20, 160, paint);
604 }
605 canvas->drawBitmap(bitmap, 0, 0, nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400606}
Cary Clark8032b982017-07-28 11:04:54 -0400607##
608
Cary Clarkbad5ad72017-08-03 17:14:08 -0400609#SeeAlso State_Stack
Cary Clark8032b982017-07-28 11:04:54 -0400610
611##
612
613# ------------------------------------------------------------------------------
614
615#Method SkMetaData& getMetaData()
616
Cary Clarkf05bdda2017-08-24 12:59:48 -0400617Returns storage to associate additional data with the canvas.
Cary Clark8032b982017-07-28 11:04:54 -0400618The storage is freed when Canvas is deleted.
619
Cary Clarkbad5ad72017-08-03 17:14:08 -0400620#Return storage that can be read from and written to ##
Cary Clark8032b982017-07-28 11:04:54 -0400621
622#Example
623 const char* kHelloMetaData = "HelloMetaData";
624 SkCanvas canvas;
625 SkMetaData& metaData = canvas.getMetaData();
626 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
627 metaData.setString(kHelloMetaData, "Hello!");
628 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
629 metaData.removeString(kHelloMetaData);
630 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
631
632 #StdOut
633 before: (null)
634 during: Hello!
635 after: (null)
636 #StdOut ##
637##
638
639#ToDo incomplete ##
640
641##
642
643# ------------------------------------------------------------------------------
644
645#Method SkImageInfo imageInfo() const
646
647Returns Image_Info for Canvas. If Canvas is not associated with Raster_Surface or
Cary Clarkbad5ad72017-08-03 17:14:08 -0400648GPU_Surface, returned Image_Color_Type is set to kUnknown_SkColorType.
Cary Clark8032b982017-07-28 11:04:54 -0400649
Cary Clarkbad5ad72017-08-03 17:14:08 -0400650#Return dimensions and Image_Color_Type of Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400651
652#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400653 SkCanvas emptyCanvas;
654 SkImageInfo canvasInfo = emptyCanvas.imageInfo();
655 SkImageInfo emptyInfo;
656 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
657
658 #StdOut
659 emptyInfo == canvasInfo
660 ##
Cary Clark8032b982017-07-28 11:04:54 -0400661##
662
663#ToDo incomplete ##
664
665##
666
667# ------------------------------------------------------------------------------
668
669#Method bool getProps(SkSurfaceProps* props) const
670
671If Canvas is associated with Raster_Surface or
672GPU_Surface, copies Surface_Properties and returns true. Otherwise,
673return false and leave props unchanged.
674
Cary Clarkbad5ad72017-08-03 17:14:08 -0400675#Param props storage for writable SkSurfaceProps ##
Cary Clark8032b982017-07-28 11:04:54 -0400676
Cary Clarkbad5ad72017-08-03 17:14:08 -0400677#Return true if Surface_Properties was copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400678
679#ToDo This seems old style. Deprecate? ##
680
681#Example
682 SkBitmap bitmap;
683 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
684 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
685 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
686 if (!canvas.getProps(&surfaceProps)) {
687 SkDebugf("getProps failed unexpectedly.\n");
688 }
689 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
690
691 #StdOut
692 isRGB:0
693 isRGB:1
694 #StdOut ##
695##
696
697#ToDo incomplete ##
698
699##
700
701# ------------------------------------------------------------------------------
702
703#Method void flush()
704
705Triggers the immediate execution of all pending draw operations.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400706If Canvas is associated with GPU_Surface, resolves all pending GPU operations.
Cary Clark8032b982017-07-28 11:04:54 -0400707
708#Example
709#Error "haven't thought of a useful example to put here"
710##
711
712#ToDo incomplete ##
713
714##
715
716# ------------------------------------------------------------------------------
717
718#Method virtual SkISize getBaseLayerSize() const
719
Cary Clarkce101242017-09-01 15:51:02 -0400720Gets the size of the base or root Layer in global canvas coordinates. The
721origin of the base Layer is always (0,0). The area available for drawing may be
Cary Clark8032b982017-07-28 11:04:54 -0400722smaller (due to clipping or saveLayer).
723
Cary Clarkce101242017-09-01 15:51:02 -0400724#Return integral width and height of base Layer ##
Cary Clark8032b982017-07-28 11:04:54 -0400725
726#Example
727 SkBitmap bitmap;
728 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
729 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
730 canvas.clipRect(SkRect::MakeWH(10, 40));
731 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
732 if (clipDeviceBounds.isEmpty()) {
733 SkDebugf("Empty clip bounds is unexpected!\n");
734 }
735 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
736 SkISize baseLayerSize = canvas.getBaseLayerSize();
737 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
738
739 #StdOut
740 clip=10,30
741 size=20,30
742 ##
743##
744
745#ToDo is this the same as the width and height of surface? ##
746
747##
748
749# ------------------------------------------------------------------------------
750
751#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
752
753Creates Surface matching info and props, and associates it with Canvas.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400754Returns nullptr if no match found.
Cary Clark8032b982017-07-28 11:04:54 -0400755
Cary Clarkbad5ad72017-08-03 17:14:08 -0400756If props is nullptr, matches Surface_Properties in Canvas. If props is nullptr and Canvas
757does not have Surface_Properties, creates Surface with default Surface_Properties.
Cary Clark8032b982017-07-28 11:04:54 -0400758
Cary Clarkbad5ad72017-08-03 17:14:08 -0400759#Param info width, height, Image_Color_Type, Image_Alpha_Type, and Color_Space ##
760#Param props Surface_Properties to match; may be nullptr to match Canvas ##
761
762#Return Surface matching info and props, or nullptr if no match is available ##
Cary Clark8032b982017-07-28 11:04:54 -0400763
764#Example
765 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
766 SkCanvas* smallCanvas = surface->getCanvas();
767 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
768 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
769 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
770 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
771
772 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -0400773 compatible != nullptr
Cary Clark8032b982017-07-28 11:04:54 -0400774 size = 3, 4
775 ##
776##
777
778#ToDo incomplete ##
779
780##
781
782# ------------------------------------------------------------------------------
783
784#Method virtual GrContext* getGrContext()
785
786Returns GPU_Context of the GPU_Surface associated with Canvas.
787
Cary Clarkbad5ad72017-08-03 17:14:08 -0400788#Return GPU_Context, if available; nullptr otherwise ##
Cary Clark8032b982017-07-28 11:04:54 -0400789
790#Example
791void draw(SkCanvas* canvas) {
792 if (canvas->getGrContext()) {
793 canvas->clear(SK_ColorRED);
794 } else {
795 canvas->clear(SK_ColorBLUE);
796 }
797}
798##
799
800#ToDo fiddle should show both CPU and GPU out ##
801
802##
803
804# ------------------------------------------------------------------------------
805
Cary Clark73fa9722017-08-29 17:36:51 -0400806#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -0400807
808Returns the pixel base address, Image_Info, rowBytes, and origin if the pixels
Cary Clarkbad5ad72017-08-03 17:14:08 -0400809can be read directly. The returned address is only valid
Cary Clark8032b982017-07-28 11:04:54 -0400810while Canvas is in scope and unchanged. Any Canvas call or Surface call
811may invalidate the returned address and other returned values.
812
813If pixels are inaccessible, info, rowBytes, and origin are unchanged.
814
Cary Clarkbad5ad72017-08-03 17:14:08 -0400815#Param info storage for writable pixels' Image_Info; may be nullptr ##
816#Param rowBytes storage for writable pixels' row bytes; may be nullptr ##
Cary Clarkce101242017-09-01 15:51:02 -0400817#Param origin storage for Canvas top Layer origin, its top left corner;
Cary Clarkbad5ad72017-08-03 17:14:08 -0400818 may be nullptr
819##
Cary Clark8032b982017-07-28 11:04:54 -0400820
Cary Clarka523d2d2017-08-30 08:58:10 -0400821#Return address of pixels, or nullptr if inaccessible ##
Cary Clark8032b982017-07-28 11:04:54 -0400822
823#Example
824void draw(SkCanvas* canvas) {
825 if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
826 canvas->clear(SK_ColorRED);
827 } else {
828 canvas->clear(SK_ColorBLUE);
829 }
830}
831##
832
833#Example
834#Description
Cary Clarkce101242017-09-01 15:51:02 -0400835Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
836Layer to add a large dotted "DEF". Finally blends Layer with the
Cary Clark8032b982017-07-28 11:04:54 -0400837device.
838
Cary Clarkce101242017-09-01 15:51:02 -0400839The Layer and blended result appear on the CPU and GPU but the large dotted
Cary Clark8032b982017-07-28 11:04:54 -0400840"DEF" appear only on the CPU.
841##
842void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400843 SkPaint paint;
844 paint.setTextSize(100);
845 canvas->drawString("ABC", 20, 160, paint);
846 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
847 canvas->saveLayerAlpha(&layerBounds, 128);
848 canvas->clear(SK_ColorWHITE);
849 canvas->drawString("DEF", 20, 160, paint);
850 SkImageInfo imageInfo;
851 size_t rowBytes;
852 SkIPoint origin;
853 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
854 if (access) {
855 int h = imageInfo.height();
856 int v = imageInfo.width();
857 int rowWords = rowBytes / sizeof(uint32_t);
858 for (int y = 0; y < h; ++y) {
859 int newY = (y - h / 2) * 2 + h / 2;
860 if (newY < 0 || newY >= h) {
861 continue;
862 }
863 for (int x = 0; x < v; ++x) {
864 int newX = (x - v / 2) * 2 + v / 2;
865 if (newX < 0 || newX >= v) {
866 continue;
867 }
868 if (access[y * rowWords + x] == SK_ColorBLACK) {
869 access[newY * rowWords + newX] = SK_ColorGRAY;
870 }
871 }
872 }
873
874 }
Cary Clark8032b982017-07-28 11:04:54 -0400875 canvas->restore();
876}
877##
878
879#ToDo there are no callers of this that I can find. Deprecate? ##
880#ToDo fiddle should show both CPU and GPU out ##
881
882##
883
884# ------------------------------------------------------------------------------
885
886#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
887
888Returns custom context that tracks the Matrix and Clip.
889
890Use Raster_Handle_Allocator to blend Skia drawing with custom drawing, typically performed
Cary Clarkce101242017-09-01 15:51:02 -0400891by the host platform's user interface. The custom context returned is generated by
Cary Clarkbad5ad72017-08-03 17:14:08 -0400892SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
Cary Clark8032b982017-07-28 11:04:54 -0400893the drawing destination.
894
Cary Clarkce101242017-09-01 15:51:02 -0400895#Return context of custom allocation ##
Cary Clark8032b982017-07-28 11:04:54 -0400896
897#Example
898#Description
899#ToDo ##
900##
901#Function
902 static void DeleteCallback(void*, void* context) {
903 delete (char*) context;
904 }
905
906 class CustomAllocator : public SkRasterHandleAllocator {
907 public:
908 bool allocHandle(const SkImageInfo& info, Rec* rec) override {
909 char* context = new char[4]{'s', 'k', 'i', 'a'};
910 rec->fReleaseProc = DeleteCallback;
911 rec->fReleaseCtx = context;
912 rec->fHandle = context;
913 rec->fPixels = context;
914 rec->fRowBytes = 4;
915 return true;
916 }
917
918 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
919 // apply canvas matrix and clip to custom environment
920 }
921 };
922
923##
924 void draw(SkCanvas* canvas) {
925 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
926 std::unique_ptr<SkCanvas> c2 =
927 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
928 new CustomAllocator()), info);
929 char* context = (char*) c2->accessTopRasterHandle();
930 SkDebugf("context = %.4s\n", context);
931
932 }
933 #StdOut
934 context = skia
935 ##
936 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
937##
938
939#SeeAlso SkRasterHandleAllocator
940
941##
942
943# ------------------------------------------------------------------------------
944
945#Method bool peekPixels(SkPixmap* pixmap)
946
947Returns true if Canvas has direct access to its pixels.
948
Cary Clarkf05bdda2017-08-24 12:59:48 -0400949Pixels are readable when Device is raster. Pixels are not readable when Canvas
Cary Clarkbad5ad72017-08-03 17:14:08 -0400950is returned from GPU_Surface, returned by SkDocument::beginPage, returned by
Cary Clarkf05bdda2017-08-24 12:59:48 -0400951SkPictureRecorder::beginRecording, or Canvas is the base of a utility class
Cary Clarkbad5ad72017-08-03 17:14:08 -0400952like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400953
Cary Clarkf05bdda2017-08-24 12:59:48 -0400954pixmap is valid only while Canvas is in scope and unchanged. Any
Cary Clarkbad5ad72017-08-03 17:14:08 -0400955Canvas or Surface call may invalidate the pixmap values.
Cary Clark8032b982017-07-28 11:04:54 -0400956
Cary Clarkbad5ad72017-08-03 17:14:08 -0400957#Param pixmap storage for Canvas pixel state if Canvas pixels are readable;
958 otherwise, ignored
959##
Cary Clark8032b982017-07-28 11:04:54 -0400960
Cary Clarkbad5ad72017-08-03 17:14:08 -0400961#Return true if Canvas has direct access to pixels ##
Cary Clark8032b982017-07-28 11:04:54 -0400962
963#Example
964 SkPixmap pixmap;
965 if (canvas->peekPixels(&pixmap)) {
966 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
967 }
968 #StdOut
969 width=256 height=256
970 ##
971##
972
973##
974
975# ------------------------------------------------------------------------------
976
977#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
978 int srcX, int srcY)
979
Cary Clarkf05bdda2017-08-24 12:59:48 -0400980Copies rectangle of pixels from Canvas into dstPixels. Matrix and Clip are
981ignored. Source rectangle corners are (srcX, srcY) and
Cary Clarkce101242017-09-01 15:51:02 -0400982#Formula
983(this->imageInfo.width(), this->imageInfo.height())
984##
Cary Clark6fc50412017-09-21 12:31:06 -0400985.
986
987Destination rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
988Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400989converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400990
Cary Clarkf05bdda2017-08-24 12:59:48 -0400991Pixels are readable when Device is raster, or backed by a GPU.
992Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
993returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
994class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400995
Cary Clarkf05bdda2017-08-24 12:59:48 -0400996The destination pixel storage must be allocated by the caller.
Cary Clark8032b982017-07-28 11:04:54 -0400997
Cary Clarkf05bdda2017-08-24 12:59:48 -0400998Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
999do not match. Only pixels within both source and destination rectangles
1000are copied. dstPixels contents outside the rectangle intersection are unchanged.
1001
1002Pass negative values for srcX or srcY to offset pixels across or down destination.
Cary Clark8032b982017-07-28 11:04:54 -04001003
1004Does not copy, and returns false if:
1005
1006#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001007# Source and destination rectangles do not intersect. ##
1008# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
1009# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001010# dstRowBytes is too small to contain one row of pixels. ##
1011##
1012
Cary Clarkf05bdda2017-08-24 12:59:48 -04001013#Param dstInfo width, height, Image_Color_Type, and Image_Alpha_Type of dstPixels ##
1014#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
1015#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
1016#Param srcX offset into readable pixels in x; may be negative ##
1017#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001018
Cary Clarkbad5ad72017-08-03 17:14:08 -04001019#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001020
1021#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001022#Width 64
1023#Height 64
1024#Description
1025 A black circle drawn on a blue background provides an image to copy.
1026 readPixels copies one quarter of the canvas into each of the four corners.
Cary Clarkce101242017-09-01 15:51:02 -04001027 The Layer draws over the image.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001028##
1029 canvas->clear(SK_ColorBLUE);
1030 SkPaint paint;
1031 canvas->drawCircle(32, 32, 28, paint);
1032 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
1033 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
1034 sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
1035 for (int x : { 32, -32 } ) {
1036 for (int y : { 32, -32 } ) {
1037 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
1038 }
1039 }
1040 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
1041 canvas->drawImage(image, 0, 0);
1042##
1043
1044#Example
Cary Clark8032b982017-07-28 11:04:54 -04001045#Description
Cary Clarkce101242017-09-01 15:51:02 -04001046 Canvas returned by Raster_Surface has Premultiplied pixel values.
1047 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
1048 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha
1049 to generate Premultiplied value 0x802B5580. readPixels converts pixel back
1050 to Unpremultiplied value 0x8056A9FF, introducing error.
Cary Clark8032b982017-07-28 11:04:54 -04001051##
1052 canvas->clear(0x8055aaff);
1053 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
1054 uint32_t pixel = 0;
1055 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
1056 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
1057 SkDebugf("pixel = %08x\n", pixel);
1058 }
1059 }
1060
1061 #StdOut
1062 pixel = 802b5580
1063 pixel = 8056a9ff
1064 ##
1065##
1066
Cary Clarkf05bdda2017-08-24 12:59:48 -04001067#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001068
1069##
1070
1071# ------------------------------------------------------------------------------
1072
1073#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
1074
Cary Clarkf05bdda2017-08-24 12:59:48 -04001075Copies rectangle of pixels from Canvas into pixmap. Matrix and Clip are
1076ignored. Source rectangle corners are (srcX, srcY) and
Cary Clarkce101242017-09-01 15:51:02 -04001077#Formula
1078(this->imageInfo.width(), this->imageInfo.height())
1079##
Cary Clark6fc50412017-09-21 12:31:06 -04001080.
1081
1082Destination rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
1083Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -04001084converting to pixmap.colorType() and pixmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001085
Cary Clarkf05bdda2017-08-24 12:59:48 -04001086Pixels are readable when Device is raster, or backed by a GPU.
1087Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
1088returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1089class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001090
Cary Clark6fc50412017-09-21 12:31:06 -04001091Caller must allocate pixel storage in pixmap if needed.
Cary Clark8032b982017-07-28 11:04:54 -04001092
Cary Clarkf05bdda2017-08-24 12:59:48 -04001093Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1094do not match. Only pixels within both source and destination rectangles
1095are copied. pixmap pixels contents outside the rectangle intersection are unchanged.
1096
1097Pass negative values for srcX or srcY to offset pixels across or down pixmap.
Cary Clark8032b982017-07-28 11:04:54 -04001098
1099Does not copy, and returns false if:
1100
1101#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001102# Source and destination rectangles do not intersect. ##
1103# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
1104# Canvas pixels are not readable; for instance, Canvas is document-based. ##
1105# Pixmap pixels could not be allocated. ##
1106# pixmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -04001107##
1108
Cary Clarkbad5ad72017-08-03 17:14:08 -04001109#Param pixmap storage for pixels copied from Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001110#Param srcX offset into readable pixels in x; may be negative ##
1111#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001112
Cary Clarkbad5ad72017-08-03 17:14:08 -04001113#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001114
1115#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001116 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001117 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
1118 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha
1119 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001120 ##
1121 void draw(SkCanvas* canvas) {
1122 canvas->clear(0x8055aaff);
1123 uint32_t pixels[1] = { 0 };
1124 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
1125 canvas->readPixels(pixmap, 0, 0);
1126 SkDebugf("pixel = %08x\n", pixels[0]);
1127 }
Cary Clark8032b982017-07-28 11:04:54 -04001128 #StdOut
1129 pixel = 802b5580
1130 ##
1131##
1132
Cary Clarkf05bdda2017-08-24 12:59:48 -04001133#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001134
1135##
1136
1137# ------------------------------------------------------------------------------
1138
1139#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
1140
Cary Clarkf05bdda2017-08-24 12:59:48 -04001141Copies rectangle of pixels from Canvas into bitmap. Matrix and Clip are
1142ignored. Source rectangle corners are (srcX, srcY) and
Cary Clarkce101242017-09-01 15:51:02 -04001143#Formula
1144(this->imageInfo.width(), this->imageInfo.height())
1145##
Cary Clark6fc50412017-09-21 12:31:06 -04001146.
1147
1148Destination rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clarkf05bdda2017-08-24 12:59:48 -04001149Copies each readable pixel intersecting both rectangles, without scaling,
1150converting to bitmap.colorType() and bitmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001151
Cary Clarkf05bdda2017-08-24 12:59:48 -04001152Pixels are readable when Device is raster, or backed by a GPU.
1153Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
1154returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1155class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001156
Cary Clark6fc50412017-09-21 12:31:06 -04001157Caller must allocate pixel storage in bitmap if needed.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001158
1159Bitmap values are converted only if Image_Color_Type and Image_Alpha_Type
1160do not match. Only pixels within both source and destination rectangles
1161are copied. Bitmap pixels outside the rectangle intersection are unchanged.
1162
1163Pass negative values for srcX or srcY to offset pixels across or down bitmap.
Cary Clark8032b982017-07-28 11:04:54 -04001164
1165Does not copy, and returns false if:
1166
1167#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001168# Source and destination rectangles do not intersect. ##
1169# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
1170# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001171# bitmap pixels could not be allocated. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001172# bitmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -04001173##
1174
Cary Clarkbad5ad72017-08-03 17:14:08 -04001175#Param bitmap storage for pixels copied from Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001176#Param srcX offset into readable pixels in x; may be negative ##
1177#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001178
Cary Clarkbad5ad72017-08-03 17:14:08 -04001179#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001180
1181#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001182 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001183 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
1184 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha
1185 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001186 ##
Cary Clark8032b982017-07-28 11:04:54 -04001187void draw(SkCanvas* canvas) {
1188 canvas->clear(0x8055aaff);
1189 SkBitmap bitmap;
1190 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
1191 canvas->readPixels(bitmap, 0, 0);
1192 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
1193}
1194 #StdOut
1195 pixel = 802b5580
1196 ##
1197##
1198
Cary Clarkf05bdda2017-08-24 12:59:48 -04001199#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001200
1201##
1202
1203# ------------------------------------------------------------------------------
1204
1205#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
1206
Cary Clarkf05bdda2017-08-24 12:59:48 -04001207Copies rectangle from pixels to Canvas. Matrix and Clip are ignored.
1208Source rectangle corners are (0, 0) and (info.width(), info.height()).
1209Destination rectangle corners are (x, y) and
Cary Clarkce101242017-09-01 15:51:02 -04001210#Formula
1211(this->imageInfo.width(), this->imageInfo.height())
1212##
Cary Clark6fc50412017-09-21 12:31:06 -04001213.
1214
1215Copies each readable pixel intersecting both rectangles, without scaling,
1216converting to
Cary Clarkce101242017-09-01 15:51:02 -04001217#Formula
1218this->imageInfo.colorType()
1219##
1220and
1221#Formula
1222this->imageInfo.alphaType()
1223##
1224if required.
Cary Clark8032b982017-07-28 11:04:54 -04001225
Cary Clarkf05bdda2017-08-24 12:59:48 -04001226Pixels are writable when Device is raster, or backed by a GPU.
1227Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
1228returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1229class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001230
Cary Clarkf05bdda2017-08-24 12:59:48 -04001231Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1232do not match. Only pixels within both source and destination rectangles
1233are copied. Canvas pixels outside the rectangle intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -04001234
Cary Clarkf05bdda2017-08-24 12:59:48 -04001235Pass negative values for x or y to offset pixels to the left or
1236above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001237
1238Does not copy, and returns false if:
1239
1240#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001241# Source and destination rectangles do not intersect. ##
Cary Clark6fc50412017-09-21 12:31:06 -04001242# pixels could not be converted to this->imageInfo.colorType() or
1243this->imageInfo.alphaType(). ##
Cary Clark8032b982017-07-28 11:04:54 -04001244# Canvas pixels are not writable; for instance, Canvas is document-based. ##
1245# rowBytes is too small to contain one row of pixels. ##
1246##
1247
Cary Clarkf05bdda2017-08-24 12:59:48 -04001248#Param info width, height, Image_Color_Type, and Image_Alpha_Type of pixels ##
1249#Param pixels pixels to copy, of size info.height() times rowBytes, or larger ##
Cary Clarkd0530ba2017-09-14 11:25:39 -04001250#Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001251#Param x offset into Canvas writable pixels in x; may be negative ##
1252#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001253
Cary Clarkbad5ad72017-08-03 17:14:08 -04001254#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001255
1256#Example
1257 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
1258 for (int y = 0; y < 256; ++y) {
1259 uint32_t pixels[256];
1260 for (int x = 0; x < 256; ++x) {
1261 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
1262 }
1263 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
1264 }
1265##
1266
Cary Clarkf05bdda2017-08-24 12:59:48 -04001267#SeeAlso readPixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001268
1269##
1270
1271# ------------------------------------------------------------------------------
1272
1273#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
1274
Cary Clarkf05bdda2017-08-24 12:59:48 -04001275Copies rectangle from pixels to Canvas. Matrix and Clip are ignored.
Cary Clark6fc50412017-09-21 12:31:06 -04001276Source rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
1277
Cary Clarkf05bdda2017-08-24 12:59:48 -04001278Destination rectangle corners are (x, y) and
Cary Clarkce101242017-09-01 15:51:02 -04001279#Formula
1280(this->imageInfo.width(), this->imageInfo.height())
1281##
Cary Clark6fc50412017-09-21 12:31:06 -04001282.
1283
1284Copies each readable pixel intersecting both rectangles, without scaling,
1285converting to
Cary Clarkce101242017-09-01 15:51:02 -04001286#Formula
1287this->imageInfo.colorType()
1288##
1289and
1290#Formula
1291this->imageInfo.alphaType()
1292##
1293if required.
Cary Clark8032b982017-07-28 11:04:54 -04001294
Cary Clarkf05bdda2017-08-24 12:59:48 -04001295Pixels are writable when Device is raster, or backed by a GPU.
1296Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
1297returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1298class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001299
Cary Clarkf05bdda2017-08-24 12:59:48 -04001300Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1301do not match. Only pixels within both source and destination rectangles
1302are copied. Canvas pixels outside the rectangle intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -04001303
Cary Clarkf05bdda2017-08-24 12:59:48 -04001304Pass negative values for x or y to offset pixels to the left or
1305above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001306
1307Does not copy, and returns false if:
1308
1309#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001310# Source and destination rectangles do not intersect. ##
Cary Clark8032b982017-07-28 11:04:54 -04001311# bitmap does not have allocated pixels. ##
Cary Clark6fc50412017-09-21 12:31:06 -04001312# bitmap pixels could not be converted to this->imageInfo.colorType() or
1313this->imageInfo.alphaType(). ##
Cary Clarkce101242017-09-01 15:51:02 -04001314# Canvas pixels are not writable; for instance, Canvas is document based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001315# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
1316##
1317
Cary Clarkbad5ad72017-08-03 17:14:08 -04001318#Param bitmap contains pixels copied to Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001319#Param x offset into Canvas writable pixels in x; may be negative ##
1320#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001321
Cary Clarkbad5ad72017-08-03 17:14:08 -04001322#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001323
1324#Example
1325void draw(SkCanvas* canvas) {
1326 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
1327 SkBitmap bitmap;
1328 bitmap.setInfo(imageInfo);
1329 uint32_t pixels[4];
1330 bitmap.setPixels(pixels);
1331 for (int y = 0; y < 256; y += 2) {
1332 for (int x = 0; x < 256; x += 2) {
1333 pixels[0] = SkColorSetRGB(x, y, x | y);
1334 pixels[1] = SkColorSetRGB(x ^ y, y, x);
1335 pixels[2] = SkColorSetRGB(x, x & y, y);
1336 pixels[3] = SkColorSetRGB(~x, ~y, x);
1337 canvas->writePixels(bitmap, x, y);
1338 }
1339 }
1340}
1341##
1342
Cary Clarkf05bdda2017-08-24 12:59:48 -04001343#SeeAlso readPixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001344
1345##
1346
1347# ------------------------------------------------------------------------------
1348#Topic State_Stack
1349
1350Canvas maintains a stack of state that allows hierarchical drawing, commonly used
Cary Clarkbad5ad72017-08-03 17:14:08 -04001351to implement windows and views. The initial state has an identity matrix and and
1352an infinite clip. Even with a wide-open clip, drawing is constrained by the
1353bounds of the Canvas Surface or Device.
Cary Clark8032b982017-07-28 11:04:54 -04001354
1355Canvas savable state consists of Clip, Matrix, and Draw_Filter.
1356Clip describes the area that may be drawn to.
1357Matrix transforms the geometry.
1358Draw_Filter (deprecated on most platforms) modifies the paint before drawing.
1359
1360save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
1361save state and return the depth of the stack.
1362
Cary Clarkbad5ad72017-08-03 17:14:08 -04001363restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
Cary Clark8032b982017-07-28 11:04:54 -04001364
1365Each state on the stack intersects Clip with the previous Clip,
1366and concatenates Matrix with the previous Matrix.
1367The intersected Clip makes the drawing area the same or smaller;
1368the concatenated Matrix may move the origin and potentially scale or rotate
1369the coordinate space.
1370
1371Canvas does not require balancing the state stack but it is a good idea
1372to do so. Calling save() without restore() will eventually cause Skia to fail;
1373mismatched save() and restore() create hard to find bugs.
1374
1375It is not possible to use state to draw outside of the clip defined by the
1376previous state.
1377
1378#Example
1379#Description
1380Draw to ever smaller clips; then restore drawing to full canvas.
1381Note that the second clipRect is not permitted to enlarge Clip.
1382##
1383#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001384void draw(SkCanvas* canvas) {
1385 SkPaint paint;
1386 canvas->save(); // records stack depth to restore
1387 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
1388 canvas->clear(SK_ColorRED); // draws to limit of clip
1389 canvas->save(); // records stack depth to restore
1390 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
1391 canvas->clear(SK_ColorBLUE); // draws to smaller clip
1392 canvas->restore(); // enlarges clip
1393 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
1394 canvas->restore(); // enlarges clip
1395 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
Cary Clark8032b982017-07-28 11:04:54 -04001396}
1397##
1398
1399Each Clip uses the current Matrix for its coordinates.
1400
1401#Example
1402#Description
1403While clipRect is given the same rectangle twice, Matrix makes the second
1404clipRect draw at half the size of the first.
1405##
1406#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001407void draw(SkCanvas* canvas) {
1408 canvas->clipRect(SkRect::MakeWH(100, 100));
1409 canvas->clear(SK_ColorRED);
1410 canvas->scale(.5, .5);
1411 canvas->clipRect(SkRect::MakeWH(100, 100));
1412 canvas->clear(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001413}
1414##
1415
1416#SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
1417
1418#Method int save()
1419
1420Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms).
1421Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1422restoring the Matrix, Clip, and Draw_Filter to their state when save() was called.
1423
Cary Clarkbad5ad72017-08-03 17:14:08 -04001424Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix,
1425and resetMatrix. Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001426
Cary Clarkbad5ad72017-08-03 17:14:08 -04001427Saved Canvas state is put on a stack; multiple calls to save() should be balance
1428by an equal number of calls to restore().
Cary Clark8032b982017-07-28 11:04:54 -04001429
1430Call restoreToCount with result to restore this and subsequent saves.
1431
Cary Clarkbad5ad72017-08-03 17:14:08 -04001432#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001433
1434#Example
1435#Description
1436The black square is translated 50 pixels down and to the right.
1437Restoring Canvas state removes translate() from Canvas stack;
1438the red square is not translated, and is drawn at the origin.
1439##
1440#Height 100
1441void draw(SkCanvas* canvas) {
1442 SkPaint paint;
1443 SkRect rect = { 0, 0, 25, 25 };
1444 canvas->drawRect(rect, paint);
1445 canvas->save();
1446 canvas->translate(50, 50);
1447 canvas->drawRect(rect, paint);
1448 canvas->restore();
1449 paint.setColor(SK_ColorRED);
1450 canvas->drawRect(rect, paint);
1451}
1452##
1453
1454#ToDo incomplete ##
1455
1456##
1457
1458# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001459
1460#Method void restore()
1461
1462Removes changes to Matrix, Clip, and Draw_Filter since Canvas state was
1463last saved. The state is removed from the stack.
1464
1465Does nothing if the stack is empty.
1466
1467#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001468void draw(SkCanvas* canvas) {
1469 SkCanvas simple;
1470 SkDebugf("depth = %d\n", simple.getSaveCount());
1471 simple.restore();
1472 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001473}
1474##
1475
1476##
1477
1478# ------------------------------------------------------------------------------
1479
1480#Method int getSaveCount() const
1481
1482Returns the number of saved states, each containing: Matrix, Clip, and Draw_Filter.
1483Equals the number of save() calls less the number of restore() calls plus one.
1484The save count of a new canvas is one.
1485
Cary Clarkbad5ad72017-08-03 17:14:08 -04001486#Return depth of save state stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001487
1488#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001489void draw(SkCanvas* canvas) {
1490 SkCanvas simple;
1491 SkDebugf("depth = %d\n", simple.getSaveCount());
1492 simple.save();
1493 SkDebugf("depth = %d\n", simple.getSaveCount());
1494 simple.restore();
1495 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001496}
1497#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001498depth = 1
1499depth = 2
Cary Clark8032b982017-07-28 11:04:54 -04001500depth = 1
1501##
1502##
1503
1504##
1505
1506# ------------------------------------------------------------------------------
1507
1508#Method void restoreToCount(int saveCount)
1509
Cary Clarkbad5ad72017-08-03 17:14:08 -04001510Restores state to Matrix, Clip, and Draw_Filter values when save(), saveLayer,
1511saveLayerPreserveLCDTextRequests, or saveLayerAlpha returned saveCount.
Cary Clark8032b982017-07-28 11:04:54 -04001512
1513Does nothing if saveCount is greater than state stack count.
1514Restores state to initial values if saveCount is less than or equal to one.
1515
Cary Clarkbad5ad72017-08-03 17:14:08 -04001516#Param saveCount depth of state stack to restore ##
Cary Clark8032b982017-07-28 11:04:54 -04001517
1518#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001519void draw(SkCanvas* canvas) {
1520 SkDebugf("depth = %d\n", canvas->getSaveCount());
1521 canvas->save();
1522 canvas->save();
1523 SkDebugf("depth = %d\n", canvas->getSaveCount());
1524 canvas->restoreToCount(0);
1525 SkDebugf("depth = %d\n", canvas->getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001526}
1527#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001528depth = 1
1529depth = 3
Cary Clark8032b982017-07-28 11:04:54 -04001530depth = 1
1531##
1532##
1533
1534##
1535
1536#Topic State_Stack ##
1537
1538# ------------------------------------------------------------------------------
Cary Clarkce101242017-09-01 15:51:02 -04001539
1540#Topic Layer
Cary Clarkd0530ba2017-09-14 11:25:39 -04001541#Substitute layer
Cary Clarkce101242017-09-01 15:51:02 -04001542#Alias Layers
1543
1544Layer allocates a temporary Bitmap to draw into. When the drawing is
1545complete, the Bitmap is drawn into the Canvas.
1546
1547Layer is saved in a stack along with other saved state. When state with a Layer
1548is restored, the Bitmap is drawn into the previous Layer.
1549
1550Layer may be initialized with the contents of the previous Layer. When Layer is
1551restored, its Bitmap can be modified by Paint passed to Layer to apply
1552Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
1553
1554#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1555
1556Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1557and allocates a Bitmap for subsequent drawing.
1558Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1559and draws the Bitmap.
1560
1561Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1562setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1563clipPath, clipRegion.
1564
1565Rect bounds suggests but does not define the Bitmap size. To clip drawing to
1566a specific rectangle, use clipRect.
1567
1568Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1569Blend_Mode when restore() is called.
1570
1571Call restoreToCount with returned value to restore this and subsequent saves.
1572
1573#Param bounds hint to limit the size of the Layer; may be nullptr ##
1574#Param paint graphics state for Layer; may be nullptr ##
1575
1576#Return depth of saved stack ##
1577
1578#Example
1579#Description
1580Rectangles are blurred by Image_Filter when restore() draws Layer to main
1581Canvas.
1582##
1583#Height 128
1584void draw(SkCanvas* canvas) {
1585 SkPaint paint, blur;
1586 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1587 canvas->saveLayer(nullptr, &blur);
1588 SkRect rect = { 25, 25, 50, 50};
1589 canvas->drawRect(rect, paint);
1590 canvas->translate(50, 50);
1591 paint.setColor(SK_ColorRED);
1592 canvas->drawRect(rect, paint);
1593 canvas->restore();
1594}
1595##
1596
1597#ToDo incomplete ##
1598
1599##
1600
1601#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
1602
1603Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1604and allocates a Bitmap for subsequent drawing.
1605Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1606and draws the Bitmap.
1607
1608Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1609setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1610clipPath, clipRegion.
1611
1612Rect bounds suggests but does not define the Layer size. To clip drawing to
1613a specific rectangle, use clipRect.
1614
1615Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1616Blend_Mode when restore() is called.
1617
1618Call restoreToCount with returned value to restore this and subsequent saves.
1619
1620#Param bounds hint to limit the size of Layer; may be nullptr ##
1621#Param paint graphics state for Layer; may be nullptr ##
1622
1623#Return depth of saved stack ##
1624
1625#Example
1626#Description
1627Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
1628The red rectangle is clipped; it does not fully fit on Layer.
1629Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
1630##
1631#Height 128
1632void draw(SkCanvas* canvas) {
1633 SkPaint paint, blur;
1634 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1635 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1636 SkRect rect = { 25, 25, 50, 50};
1637 canvas->drawRect(rect, paint);
1638 canvas->translate(50, 50);
1639 paint.setColor(SK_ColorRED);
1640 canvas->drawRect(rect, paint);
1641 canvas->restore();
1642}
1643##
1644
1645#ToDo incomplete ##
1646
1647##
1648
1649#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
1650
1651Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1652and allocates a Bitmap for subsequent drawing.
1653LCD_Text is preserved when the Layer is drawn to the prior Layer.
1654
1655Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1656and draws Layer.
1657
1658Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1659setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1660clipPath, clipRegion.
1661
1662Rect bounds suggests but does not define the Layer size. To clip drawing to
1663a specific rectangle, use clipRect.
1664
1665Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1666Blend_Mode when restore() is called.
1667
1668Call restoreToCount with returned value to restore this and subsequent saves.
1669
1670Draw text on an opaque background so that LCD_Text blends correctly with the
1671prior Layer. LCD_Text drawn on a background with transparency may result in
Cary Clark6fc50412017-09-21 12:31:06 -04001672incorrect blending.
Cary Clarkce101242017-09-01 15:51:02 -04001673
1674#Param bounds hint to limit the size of Layer; may be nullptr ##
1675#Param paint graphics state for Layer; may be nullptr ##
1676
1677#Return depth of saved stack ##
1678
1679#Example
1680 SkPaint paint;
1681 paint.setAntiAlias(true);
1682 paint.setLCDRenderText(true);
1683 paint.setTextSize(20);
1684 for (auto preserve : { false, true } ) {
1685 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
1686 : canvas->saveLayer(nullptr, nullptr);
1687 SkPaint p;
1688 p.setColor(SK_ColorWHITE);
1689 // Comment out the next line to draw on a non-opaque background.
1690 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
1691 canvas->drawString("Hamburgefons", 30, 60, paint);
1692
1693 p.setColor(0xFFCCCCCC);
1694 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
1695 canvas->drawString("Hamburgefons", 30, 90, paint);
1696
1697 canvas->restore();
1698 canvas->translate(0, 80);
1699 }
1700 ##
1701
1702#ToDo incomplete ##
1703
1704##
1705
1706#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1707
1708Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1709and allocates Bitmap for subsequent drawing.
1710
1711Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1712and blends Layer with alpha opacity onto prior Layer.
1713
1714Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1715setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1716clipPath, clipRegion.
1717
1718Rect bounds suggests but does not define Layer size. To clip drawing to
1719a specific rectangle, use clipRect.
1720
1721alpha of zero is fully transparent, 255 is fully opaque.
1722
1723Call restoreToCount with returned value to restore this and subsequent saves.
1724
1725#Param bounds hint to limit the size of Layer; may be nullptr ##
1726#Param alpha opacity of Layer ##
1727
1728#Return depth of saved stack ##
1729
1730#Example
1731 SkPaint paint;
1732 paint.setColor(SK_ColorRED);
1733 canvas->drawCircle(50, 50, 50, paint);
1734 canvas->saveLayerAlpha(nullptr, 128);
1735 paint.setColor(SK_ColorBLUE);
1736 canvas->drawCircle(100, 50, 50, paint);
1737 paint.setColor(SK_ColorGREEN);
1738 paint.setAlpha(128);
1739 canvas->drawCircle(75, 90, 50, paint);
1740 canvas->restore();
1741##
1742
1743#ToDo incomplete ##
1744
1745##
1746
1747#Enum
1748
1749#Code
1750 enum {
1751 kIsOpaque_SaveLayerFlag = 1 << 0,
1752 kPreserveLCDText_SaveLayerFlag = 1 << 1,
1753 kInitWithPrevious_SaveLayerFlag = 1 << 2,
1754 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
1755 };
1756
1757 typedef uint32_t SaveLayerFlags;
1758##
1759
1760SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
1761defining how Layer allocated by saveLayer operates.
1762
1763#Const kIsOpaque_SaveLayerFlag 1
1764 Creates Layer without transparency. Flag is ignored if Layer Paint contains
1765 Image_Filter or Color_Filter.
1766##
1767
1768#Const kPreserveLCDText_SaveLayerFlag 2
1769 Creates Layer for LCD text. Flag is ignored if Layer Paint contains
1770 Image_Filter or Color_Filter.
1771##
1772
1773#Const kInitWithPrevious_SaveLayerFlag 4
1774 Initializes Layer with the contents of the previous Layer.
1775##
1776
1777#Const kDontClipToLayer_Legacy_SaveLayerFlag 0x80000000
1778#Private
1779 to be deprecated: bug.skia.org/2440
1780##
1781 Only present on Android.
1782 Skips setting a clip to the Layer bounds.
1783##
1784
1785#Example
1786#Height 160
1787#Description
1788Canvas Layer captures red and blue circles scaled up by four.
1789scalePaint blends Layer back with transparency.
1790##
1791void draw(SkCanvas* canvas) {
1792 SkPaint redPaint, bluePaint, scalePaint;
1793 redPaint.setColor(SK_ColorRED);
1794 canvas->drawCircle(21, 21, 8, redPaint);
1795 bluePaint.setColor(SK_ColorBLUE);
1796 canvas->drawCircle(31, 21, 8, bluePaint);
1797 SkMatrix matrix;
1798 matrix.setScale(4, 4);
1799 scalePaint.setAlpha(0x40);
1800 scalePaint.setImageFilter(
1801 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1802 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
1803 SkCanvas::kInitWithPrevious_SaveLayerFlag);
1804 canvas->saveLayer(saveLayerRec);
1805 canvas->restore();
1806}
1807##
1808
1809#ToDo incomplete ##
1810
1811#Enum ##
1812
1813#Struct SaveLayerRec
1814
1815#Code
1816 struct SaveLayerRec {
1817 SaveLayerRec*(...
1818
1819 const SkRect* fBounds;
1820 const SkPaint* fPaint;
1821 const SkImageFilter* fBackdrop;
1822 SaveLayerFlags fSaveLayerFlags;
1823 };
1824##
1825
1826SaveLayerRec contains the state used to create the Layer.
1827
1828#Member const SkRect* fBounds
1829 fBounds is used as a hint to limit the size of Layer; may be nullptr.
1830 fBounds suggests but does not define Layer size. To clip drawing to
1831 a specific rectangle, use clipRect.
1832##
1833
1834#Member const SkPaint* fPaint
1835 fPaint modifies how Layer overlays the prior Layer; may be nullptr.
1836 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1837 Mask_Filter affect Layer draw.
1838##
1839
1840#Member const SkImageFilter* fBackdrop
1841 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
1842 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1843 prior Layer without an Image_Filter.
1844##
1845
1846#Member const SkImage* fClipMask
1847 restore() clips Layer by the Color_Alpha channel of fClipMask when
1848 Layer is copied to Device. fClipMask may be nullptr. .
1849##
1850
1851#Member const SkMatrix* fClipMatrix
1852 fClipMatrix transforms fClipMask before it clips Layer. If
1853 fClipMask describes a translucent gradient, it may be scaled and rotated
1854 without introducing artifacts. fClipMatrix may be nullptr.
1855##
1856
1857#Member SaveLayerFlags fSaveLayerFlags
1858 fSaveLayerFlags are used to create Layer without transparency,
1859 create Layer for LCD text, and to create Layer with the
1860 contents of the previous Layer.
1861##
1862
1863#Example
1864#Height 160
1865#Description
1866Canvas Layer captures a red Anti-aliased circle and a blue Aliased circle scaled
1867up by four. After drawing another red circle without scaling on top, the Layer is
1868transferred to the main canvas.
1869##
1870void draw(SkCanvas* canvas) {
1871 SkPaint redPaint, bluePaint;
1872 redPaint.setAntiAlias(true);
1873 redPaint.setColor(SK_ColorRED);
1874 canvas->drawCircle(21, 21, 8, redPaint);
1875 bluePaint.setColor(SK_ColorBLUE);
1876 canvas->drawCircle(31, 21, 8, bluePaint);
1877 SkMatrix matrix;
1878 matrix.setScale(4, 4);
1879 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
1880 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
1881 canvas->saveLayer(saveLayerRec);
1882 canvas->drawCircle(125, 85, 8, redPaint);
1883 canvas->restore();
1884}
1885##
1886
1887#Method SaveLayerRec()
1888
1889Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
1890
1891#Return empty SaveLayerRec ##
1892
1893#Example
1894 SkCanvas::SaveLayerRec rec1;
1895 rec1.fSaveLayerFlags = SkCanvas::kIsOpaque_SaveLayerFlag;
1896 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kIsOpaque_SaveLayerFlag);
1897 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1898 && rec1.fPaint == rec2.fPaint
1899 && rec1.fBackdrop == rec2.fBackdrop
1900 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1901 #StdOut
1902 rec1 == rec2
1903 ##
1904##
1905
1906##
1907
1908#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
1909
1910Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
1911
1912#Param bounds Layer dimensions; may be nullptr ##
1913#Param paint applied to Layer when overlaying prior Layer; may be nullptr ##
1914#Param saveLayerFlags SaveLayerRec options to modify Layer ##
1915
1916#Return SaveLayerRec with empty backdrop ##
1917
1918#Example
1919 SkCanvas::SaveLayerRec rec1;
1920 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1921 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1922 && rec1.fPaint == rec2.fPaint
1923 && rec1.fBackdrop == rec2.fBackdrop
1924 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1925 #StdOut
1926 rec1 == rec2
1927 ##
1928##
1929
1930##
1931
1932#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1933 SaveLayerFlags saveLayerFlags)
1934
1935Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
1936
1937#Param bounds Layer dimensions; may be nullptr ##
1938#Param paint applied to Layer when overlaying prior Layer;
1939 may be nullptr
1940##
1941#Param backdrop prior Layer copied with Image_Filter; may be nullptr
1942##
1943#Param saveLayerFlags SaveLayerRec options to modify Layer ##
1944
1945#Return SaveLayerRec fully specified ##
1946
1947#Example
1948 SkCanvas::SaveLayerRec rec1;
1949 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1950 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1951 && rec1.fPaint == rec2.fPaint
1952 && rec1.fBackdrop == rec2.fBackdrop
1953 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1954 #StdOut
1955 rec1 == rec2
1956 ##
1957##
1958
1959##
1960
1961#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1962 const SkImage* clipMask, const SkMatrix* clipMatrix,
1963 SaveLayerFlags saveLayerFlags)
1964
1965#Experimental
1966Not ready for general use.
1967##
1968
1969Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
1970clipMatrix uses Color_Alpha channel of image, transformed by clipMatrix, to clip
1971Layer when drawn to Canvas.
1972
1973Implementation is incomplete; has no effect if Device is GPU-backed.
1974
1975#Param bounds Layer dimensions; may be nullptr ##
1976#Param paint graphics state applied to Layer when overlaying prior
1977 Layer; may be nullptr
1978##
1979#Param backdrop prior Layer copied with Image_Filter;
1980 may be nullptr
1981##
1982#Param clipMask clip applied to Layer; may be nullptr ##
1983#Param clipMatrix matrix applied to clipMask; may be nullptr to use
1984 identity matrix
1985##
1986#Param saveLayerFlags SaveLayerRec options to modify Layer ##
1987
1988#Return SaveLayerRec fully specified ##
1989
1990#ToDo incomplete ##
1991
1992##
1993
1994#Struct ##
1995
1996#Method int saveLayer(const SaveLayerRec& layerRec)
1997
1998Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1999and allocates Bitmap for subsequent drawing.
2000
2001Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
2002and blends Bitmap with Color_Alpha opacity onto the prior Layer.
2003
2004Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
2005setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
2006clipPath, clipRegion.
2007
2008SaveLayerRec contains the state used to create the Layer.
2009
2010Call restoreToCount with returned value to restore this and subsequent saves.
2011
2012#Param layerRec Layer state ##
2013
2014#Return depth of save state stack ##
2015
2016#Example
2017#Description
2018The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
2019Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
2020Where Layer was cleared, the original image will draw unchanged.
2021Outside of the circle the mandrill is brightened.
2022##
2023 #Image 3
2024 // sk_sp<SkImage> image = GetResourceAsImage("mandrill_256.png");
2025 canvas->drawImage(image, 0, 0, nullptr);
2026 SkCanvas::SaveLayerRec rec;
2027 SkPaint paint;
2028 paint.setBlendMode(SkBlendMode::kPlus);
2029 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
2030 rec.fPaint = &paint;
2031 canvas->saveLayer(rec);
2032 paint.setBlendMode(SkBlendMode::kClear);
2033 canvas->drawCircle(128, 128, 96, paint);
2034 canvas->restore();
2035##
2036
2037#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
2038
2039##
2040
2041#Topic Layer ##
2042
2043# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04002044#Topic Matrix
2045
2046#Method void translate(SkScalar dx, SkScalar dy)
2047
2048Translate Matrix by dx along the x-axis and dy along the y-axis.
2049
2050Mathematically, replace Matrix with a translation matrix
Cary Clarkce101242017-09-01 15:51:02 -04002051Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002052
2053This has the effect of moving the drawing by (dx, dy) before transforming
2054the result with Matrix.
2055
Cary Clarkbad5ad72017-08-03 17:14:08 -04002056#Param dx distance to translate in x ##
2057#Param dy distance to translate in y ##
Cary Clark8032b982017-07-28 11:04:54 -04002058
2059#Example
2060#Height 128
2061#Description
2062scale() followed by translate() produces different results from translate() followed
2063by scale().
2064
2065The blue stroke follows translate of (50, 50); a black
2066fill follows scale of (2, 1/2.f). After restoring the clip, which resets
2067Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
2068follows translate of (50, 50).
2069##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002070void draw(SkCanvas* canvas) {
2071 SkPaint filledPaint;
2072 SkPaint outlinePaint;
2073 outlinePaint.setStyle(SkPaint::kStroke_Style);
2074 outlinePaint.setColor(SK_ColorBLUE);
2075 canvas->save();
2076 canvas->translate(50, 50);
2077 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
2078 canvas->scale(2, 1/2.f);
2079 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
2080 canvas->restore();
2081 filledPaint.setColor(SK_ColorGRAY);
2082 outlinePaint.setColor(SK_ColorRED);
2083 canvas->scale(2, 1/2.f);
2084 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
2085 canvas->translate(50, 50);
2086 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04002087}
2088##
2089
2090#ToDo incomplete ##
2091
2092##
2093
2094# ------------------------------------------------------------------------------
2095
2096#Method void scale(SkScalar sx, SkScalar sy)
2097
2098Scale Matrix by sx on the x-axis and sy on the y-axis.
2099
2100Mathematically, replace Matrix with a scale matrix
Cary Clarkce101242017-09-01 15:51:02 -04002101Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002102
2103This has the effect of scaling the drawing by (sx, sy) before transforming
2104the result with Matrix.
2105
Cary Clarkbad5ad72017-08-03 17:14:08 -04002106#Param sx amount to scale in x ##
2107#Param sy amount to scale in y ##
Cary Clark8032b982017-07-28 11:04:54 -04002108
2109#Example
2110#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04002111void draw(SkCanvas* canvas) {
2112 SkPaint paint;
2113 SkRect rect = { 10, 20, 60, 120 };
2114 canvas->translate(20, 20);
2115 canvas->drawRect(rect, paint);
2116 canvas->scale(2, .5f);
2117 paint.setColor(SK_ColorGRAY);
2118 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002119}
2120##
2121
2122#ToDo incomplete ##
2123
2124##
2125
2126# ------------------------------------------------------------------------------
2127
2128#Method void rotate(SkScalar degrees)
2129
2130Rotate Matrix by degrees. Positive degrees rotates clockwise.
2131
2132Mathematically, replace Matrix with a rotation matrix
Cary Clarkce101242017-09-01 15:51:02 -04002133Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002134
2135This has the effect of rotating the drawing by degrees before transforming
2136the result with Matrix.
2137
Cary Clarkbad5ad72017-08-03 17:14:08 -04002138#Param degrees amount to rotate, in degrees ##
Cary Clark8032b982017-07-28 11:04:54 -04002139
2140#Example
2141#Description
2142Draw clock hands at time 5:10. The hour hand and minute hand point up and
2143are rotated clockwise.
2144##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002145void draw(SkCanvas* canvas) {
2146 SkPaint paint;
2147 paint.setStyle(SkPaint::kStroke_Style);
2148 canvas->translate(128, 128);
2149 canvas->drawCircle(0, 0, 60, paint);
2150 canvas->save();
2151 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
2152 canvas->drawLine(0, 0, 0, -50, paint);
2153 canvas->restore();
2154 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
2155 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002156}
2157##
2158
2159#ToDo incomplete ##
2160
2161##
2162
2163# ------------------------------------------------------------------------------
2164
2165#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
2166
Cary Clarkbad5ad72017-08-03 17:14:08 -04002167Rotate Matrix by degrees about a point at (px, py). Positive degrees rotates
2168clockwise.
Cary Clark8032b982017-07-28 11:04:54 -04002169
Cary Clarkce101242017-09-01 15:51:02 -04002170Mathematically, construct a rotation matrix. Premultiply the rotation matrix by
Cary Clark8032b982017-07-28 11:04:54 -04002171a translation matrix, then replace Matrix with the resulting matrix
Cary Clarkce101242017-09-01 15:51:02 -04002172Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002173
Cary Clarkbad5ad72017-08-03 17:14:08 -04002174This has the effect of rotating the drawing about a given point before
2175transforming the result with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002176
Cary Clarkbad5ad72017-08-03 17:14:08 -04002177#Param degrees amount to rotate, in degrees ##
2178#Param px x-coordinate of the point to rotate about ##
2179#Param py y-coordinate of the point to rotate about ##
Cary Clark8032b982017-07-28 11:04:54 -04002180
2181#Example
2182#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04002183void draw(SkCanvas* canvas) {
2184 SkPaint paint;
2185 paint.setTextSize(96);
2186 canvas->drawString("A1", 130, 100, paint);
2187 canvas->rotate(180, 130, 100);
2188 canvas->drawString("A1", 130, 100, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002189}
2190##
2191
2192#ToDo incomplete ##
2193
2194##
2195
2196# ------------------------------------------------------------------------------
2197
2198#Method void skew(SkScalar sx, SkScalar sy)
2199
Cary Clarkbad5ad72017-08-03 17:14:08 -04002200Skew Matrix by sx on the x-axis and sy on the y-axis. A positive value of sx
2201skews the drawing right as y increases; a positive value of sy skews the drawing
2202down as x increases.
Cary Clark8032b982017-07-28 11:04:54 -04002203
Cary Clarkce101242017-09-01 15:51:02 -04002204Mathematically, replace Matrix with a skew matrix Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002205
Cary Clarkbad5ad72017-08-03 17:14:08 -04002206This has the effect of skewing the drawing by (sx, sy) before transforming
Cary Clark8032b982017-07-28 11:04:54 -04002207the result with Matrix.
2208
Cary Clarkbad5ad72017-08-03 17:14:08 -04002209#Param sx amount to skew in x ##
2210#Param sy amount to skew in y ##
2211
Cary Clark8032b982017-07-28 11:04:54 -04002212#Example
2213 #Description
2214 Black text mimics an oblique text style by using a negative skew in x that
2215 shifts the geometry to the right as the y values decrease.
2216 Red text uses a positive skew in y to shift the geometry down as the x values
2217 increase.
2218 Blue text combines x and y skew to rotate and scale.
2219 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002220 SkPaint paint;
2221 paint.setTextSize(128);
2222 canvas->translate(30, 130);
2223 canvas->save();
2224 canvas->skew(-.5, 0);
2225 canvas->drawString("A1", 0, 0, paint);
2226 canvas->restore();
2227 canvas->save();
2228 canvas->skew(0, .5);
2229 paint.setColor(SK_ColorRED);
2230 canvas->drawString("A1", 0, 0, paint);
2231 canvas->restore();
2232 canvas->skew(-.5, .5);
2233 paint.setColor(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04002234 canvas->drawString("A1", 0, 0, paint);
2235##
2236
2237#ToDo incomplete ##
2238
2239##
2240
2241# ------------------------------------------------------------------------------
2242
2243#Method void concat(const SkMatrix& matrix)
2244
Cary Clarkce101242017-09-01 15:51:02 -04002245Replace Matrix with matrix Premultiplied with existing Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002246
Cary Clarkbad5ad72017-08-03 17:14:08 -04002247This has the effect of transforming the drawn geometry by matrix, before
2248transforming the result with existing Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002249
Cary Clarkce101242017-09-01 15:51:02 -04002250#Param matrix matrix to Premultiply with existing Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04002251
2252#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002253void draw(SkCanvas* canvas) {
2254 SkPaint paint;
2255 paint.setTextSize(80);
2256 paint.setTextScaleX(.3);
2257 SkMatrix matrix;
2258 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
2259 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
2260 canvas->drawRect(rect[0], paint);
2261 canvas->drawRect(rect[1], paint);
2262 paint.setColor(SK_ColorWHITE);
2263 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
2264 canvas->concat(matrix);
2265 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002266}
2267##
2268
2269#ToDo incomplete ##
2270
2271##
2272
2273# ------------------------------------------------------------------------------
2274
2275#Method void setMatrix(const SkMatrix& matrix)
2276
2277Replace Matrix with matrix.
2278Unlike concat(), any prior matrix state is overwritten.
2279
Cary Clarkbad5ad72017-08-03 17:14:08 -04002280#Param matrix matrix to copy, replacing existing Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04002281
2282#Example
2283#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002284void draw(SkCanvas* canvas) {
2285 SkPaint paint;
2286 canvas->scale(4, 6);
2287 canvas->drawString("truth", 2, 10, paint);
2288 SkMatrix matrix;
2289 matrix.setScale(2.8f, 6);
2290 canvas->setMatrix(matrix);
2291 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002292}
2293##
2294
2295#ToDo incomplete ##
2296
2297##
2298
2299# ------------------------------------------------------------------------------
2300
2301#Method void resetMatrix()
2302
2303Sets Matrix to the identity matrix.
2304Any prior matrix state is overwritten.
2305
2306#Example
2307#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002308void draw(SkCanvas* canvas) {
2309 SkPaint paint;
2310 canvas->scale(4, 6);
2311 canvas->drawString("truth", 2, 10, paint);
2312 canvas->resetMatrix();
2313 canvas->scale(2.8f, 6);
2314 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002315}
2316##
2317
2318#ToDo incomplete ##
2319
2320##
2321
2322# ------------------------------------------------------------------------------
2323
2324#Method const SkMatrix& getTotalMatrix() const
2325
2326Returns Matrix.
2327This does not account for translation by Device or Surface.
2328
Cary Clarkbad5ad72017-08-03 17:14:08 -04002329#Return Matrix in Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04002330
2331#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002332 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
2333 #StdOut
2334 isIdentity true
2335 ##
Cary Clark8032b982017-07-28 11:04:54 -04002336##
2337
2338#ToDo incomplete ##
2339
2340##
2341
2342#Topic Matrix ##
2343
2344# ------------------------------------------------------------------------------
2345#Topic Clip
2346
2347Clip is built from a stack of clipping paths. Each Path in the
2348stack can be constructed from one or more Path_Contour elements. The
2349Path_Contour may be composed of any number of Path_Verb segments. Each
2350Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
2351by Path_Contour.
2352
2353Clip stack of Path elements successfully restrict the Path area. Each
2354Path is transformed by Matrix, then intersected with or subtracted from the
2355prior Clip to form the replacement Clip. Use SkClipOp::kDifference
2356to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
2357with Clip.
2358
Cary Clarkce101242017-09-01 15:51:02 -04002359A clipping Path may be Anti-aliased; if Path, after transformation, is
Cary Clark8032b982017-07-28 11:04:54 -04002360composed of horizontal and vertical lines, clearing Anti-alias allows whole pixels
Cary Clarkce101242017-09-01 15:51:02 -04002361to either be inside or outside the clip. The fastest drawing has a Aliased,
2362rectangular clip.
Cary Clark8032b982017-07-28 11:04:54 -04002363
2364If clipping Path has Anti-alias set, clip may partially clip a pixel, requiring
2365that drawing blend partially with the destination along the edge. A rotated
Cary Clarkce101242017-09-01 15:51:02 -04002366rectangular Anti-aliased clip looks smoother but draws slower.
Cary Clark8032b982017-07-28 11:04:54 -04002367
2368Clip can combine with Rect and Round_Rect primitives; like
2369Path, these are transformed by Matrix before they are combined with Clip.
2370
2371Clip can combine with Region. Region is assumed to be in Device coordinates
2372and is unaffected by Matrix.
2373
2374#Example
2375#Height 90
2376 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002377 Draw a red circle with an Aliased clip and an Anti-aliased clip.
Cary Clark8032b982017-07-28 11:04:54 -04002378 Use an image filter to zoom into the pixels drawn.
Cary Clarkce101242017-09-01 15:51:02 -04002379 The edge of the Aliased clip fully draws pixels in the red circle.
2380 The edge of the Anti-aliased clip partially draws pixels in the red circle.
Cary Clark8032b982017-07-28 11:04:54 -04002381 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002382 SkPaint redPaint, scalePaint;
2383 redPaint.setAntiAlias(true);
2384 redPaint.setColor(SK_ColorRED);
2385 canvas->save();
2386 for (bool antialias : { false, true } ) {
2387 canvas->save();
2388 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
2389 canvas->drawCircle(17, 11, 8, redPaint);
2390 canvas->restore();
2391 canvas->translate(16, 0);
2392 }
2393 canvas->restore();
2394 SkMatrix matrix;
2395 matrix.setScale(6, 6);
2396 scalePaint.setImageFilter(
2397 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
2398 SkCanvas::SaveLayerRec saveLayerRec(
2399 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
2400 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04002401 canvas->restore();
2402##
2403
2404#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
2405
2406Replace Clip with the intersection or difference of Clip and rect,
Cary Clarkce101242017-09-01 15:51:02 -04002407with an Aliased or Anti-aliased clip edge. rect is transformed by Matrix
Cary Clark8032b982017-07-28 11:04:54 -04002408before it is combined with Clip.
2409
Cary Clarka523d2d2017-08-30 08:58:10 -04002410#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002411#Param op Clip_Op to apply to Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002412#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002413
2414#Example
2415#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002416void draw(SkCanvas* canvas) {
2417 canvas->rotate(10);
2418 SkPaint paint;
2419 paint.setAntiAlias(true);
2420 for (auto alias: { false, true } ) {
2421 canvas->save();
2422 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
2423 canvas->drawCircle(100, 60, 60, paint);
2424 canvas->restore();
2425 canvas->translate(80, 0);
2426 }
Cary Clark8032b982017-07-28 11:04:54 -04002427}
2428##
2429
2430#ToDo incomplete ##
2431
2432##
2433
2434#Method void clipRect(const SkRect& rect, SkClipOp op)
2435
2436Replace Clip with the intersection or difference of Clip and rect.
Cary Clarkce101242017-09-01 15:51:02 -04002437Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002438rect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002439
Cary Clarka523d2d2017-08-30 08:58:10 -04002440#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002441#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002442
2443#Example
2444#Height 192
2445#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04002446void draw(SkCanvas* canvas) {
2447 SkPaint paint;
2448 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
2449 canvas->save();
2450 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
2451 canvas->drawCircle(100, 100, 60, paint);
2452 canvas->restore();
2453 canvas->translate(80, 0);
2454 }
Cary Clark8032b982017-07-28 11:04:54 -04002455}
2456##
2457
2458#ToDo incomplete ##
2459
2460##
2461
2462#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
2463
2464Replace Clip with the intersection of Clip and rect.
Cary Clarkce101242017-09-01 15:51:02 -04002465Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002466rect is transformed by Matrix
2467before it is combined with Clip.
2468
Cary Clarka523d2d2017-08-30 08:58:10 -04002469#Param rect Rect to combine with Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002470#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002471
2472#Example
2473#Height 133
2474 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002475 A circle drawn in pieces looks uniform when drawn Aliased.
2476 The same circle pieces blend with pixels more than once when Anti-aliased,
Cary Clark8032b982017-07-28 11:04:54 -04002477 visible as a thin pair of lines through the right circle.
2478 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002479void draw(SkCanvas* canvas) {
2480 canvas->clear(SK_ColorWHITE);
2481 SkPaint paint;
2482 paint.setAntiAlias(true);
2483 paint.setColor(0x8055aaff);
2484 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
2485 for (auto alias: { false, true } ) {
2486 canvas->save();
2487 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
2488 canvas->drawCircle(67, 67, 60, paint);
2489 canvas->restore();
2490 canvas->save();
2491 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
2492 canvas->drawCircle(67, 67, 60, paint);
2493 canvas->restore();
2494 canvas->translate(120, 0);
2495 }
Cary Clark8032b982017-07-28 11:04:54 -04002496}
2497##
2498
2499#ToDo incomplete ##
2500
2501##
2502
2503#Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect)
2504
Cary Clarkce101242017-09-01 15:51:02 -04002505Sets the maximum clip rectangle, which can be set by clipRect, clipRRect and
Cary Clark8032b982017-07-28 11:04:54 -04002506clipPath and intersect the current clip with the specified rect.
Cary Clarkce101242017-09-01 15:51:02 -04002507The maximum clip affects only future clipping operations; it is not retroactive.
Cary Clark8032b982017-07-28 11:04:54 -04002508The clip restriction is not recorded in pictures.
2509
Cary Clarkce101242017-09-01 15:51:02 -04002510Pass an empty rect to disable maximum clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002511
Cary Clark8032b982017-07-28 11:04:54 -04002512#Private
2513This is private API to be used only by Android framework.
2514##
2515
Cary Clarkbad5ad72017-08-03 17:14:08 -04002516#Param rect maximum allowed clip in device coordinates
Cary Clark579985c2017-07-31 11:48:27 -04002517#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04002518
2519##
2520
2521#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
2522
2523Replace Clip with the intersection or difference of Clip and rrect,
Cary Clarkce101242017-09-01 15:51:02 -04002524with an Aliased or Anti-aliased clip edge.
Cary Clark8032b982017-07-28 11:04:54 -04002525rrect is transformed by Matrix
2526before it is combined with Clip.
2527
Cary Clarkbad5ad72017-08-03 17:14:08 -04002528#Param rrect Round_Rect to combine with Clip ##
2529#Param op Clip_Op to apply to Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002530#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002531
2532#Example
2533#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002534void draw(SkCanvas* canvas) {
2535 canvas->clear(SK_ColorWHITE);
2536 SkPaint paint;
2537 paint.setAntiAlias(true);
2538 paint.setColor(0x8055aaff);
2539 SkRRect oval;
2540 oval.setOval({10, 20, 90, 100});
2541 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
2542 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002543}
2544##
2545
2546#ToDo incomplete ##
2547
2548##
2549
2550#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
2551
2552Replace Clip with the intersection or difference of Clip and rrect.
Cary Clarkce101242017-09-01 15:51:02 -04002553Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002554rrect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002555
Cary Clarkbad5ad72017-08-03 17:14:08 -04002556#Param rrect Round_Rect to combine with Clip ##
2557#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002558
2559#Example
2560#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002561void draw(SkCanvas* canvas) {
2562 SkPaint paint;
2563 paint.setColor(0x8055aaff);
2564 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
2565 canvas->clipRRect(oval, SkClipOp::kIntersect);
2566 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002567}
2568##
2569
2570#ToDo incomplete ##
2571
2572##
2573
2574#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
2575
2576Replace Clip with the intersection of Clip and rrect,
Cary Clarkce101242017-09-01 15:51:02 -04002577with an Aliased or Anti-aliased clip edge.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002578rrect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002579
Cary Clarkbad5ad72017-08-03 17:14:08 -04002580#Param rrect Round_Rect to combine with Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002581#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002582
2583#Example
2584#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002585void draw(SkCanvas* canvas) {
2586 SkPaint paint;
2587 paint.setAntiAlias(true);
2588 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
2589 canvas->clipRRect(oval, true);
2590 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002591}
2592##
2593
2594#ToDo incomplete ##
2595
2596##
2597
2598#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
2599
2600Replace Clip with the intersection or difference of Clip and path,
Cary Clarkce101242017-09-01 15:51:02 -04002601with an Aliased or Anti-aliased clip edge. Path_Fill_Type determines if path
Cary Clark8032b982017-07-28 11:04:54 -04002602describes the area inside or outside its contours; and if Path_Contour overlaps
2603itself or another Path_Contour, whether the overlaps form part of the area.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002604path is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002605
Cary Clarkbad5ad72017-08-03 17:14:08 -04002606#Param path Path to combine with Clip ##
2607#Param op Clip_Op to apply to Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002608#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002609
2610#Example
2611#Description
2612Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
2613area outside clip is subtracted from circle.
2614
2615Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
2616area inside clip is intersected with circle.
2617##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002618void draw(SkCanvas* canvas) {
2619 SkPaint paint;
2620 paint.setAntiAlias(true);
2621 SkPath path;
2622 path.addRect({20, 30, 100, 110});
2623 path.setFillType(SkPath::kInverseWinding_FillType);
2624 canvas->save();
2625 canvas->clipPath(path, SkClipOp::kDifference, false);
2626 canvas->drawCircle(70, 100, 60, paint);
2627 canvas->restore();
2628 canvas->translate(100, 100);
2629 path.setFillType(SkPath::kWinding_FillType);
2630 canvas->clipPath(path, SkClipOp::kIntersect, false);
2631 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002632}
2633##
2634
2635#ToDo incomplete ##
2636
2637##
2638
2639#Method void clipPath(const SkPath& path, SkClipOp op)
2640
2641Replace Clip with the intersection or difference of Clip and path.
Cary Clarkce101242017-09-01 15:51:02 -04002642Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002643Path_Fill_Type determines if path
2644describes the area inside or outside its contours; and if Path_Contour overlaps
2645itself or another Path_Contour, whether the overlaps form part of the area.
2646path is transformed by Matrix
2647before it is combined with Clip.
2648
Cary Clarkbad5ad72017-08-03 17:14:08 -04002649#Param path Path to combine with Clip ##
2650#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002651
2652#Example
2653#Description
2654Overlapping Rects form a clip. When clip's Path_Fill_Type is set to
2655SkPath::kWinding_FillType, the overlap is included. Set to
2656SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2657##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002658void draw(SkCanvas* canvas) {
2659 SkPaint paint;
2660 paint.setAntiAlias(true);
2661 SkPath path;
2662 path.addRect({20, 15, 100, 95});
2663 path.addRect({50, 65, 130, 135});
2664 path.setFillType(SkPath::kWinding_FillType);
2665 canvas->save();
2666 canvas->clipPath(path, SkClipOp::kIntersect);
2667 canvas->drawCircle(70, 85, 60, paint);
2668 canvas->restore();
2669 canvas->translate(100, 100);
2670 path.setFillType(SkPath::kEvenOdd_FillType);
2671 canvas->clipPath(path, SkClipOp::kIntersect);
2672 canvas->drawCircle(70, 85, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002673}
2674##
2675
2676#ToDo incomplete ##
2677
2678##
2679
2680#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
2681
2682Replace Clip with the intersection of Clip and path.
Cary Clarkce101242017-09-01 15:51:02 -04002683Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002684Path_Fill_Type determines if path
2685describes the area inside or outside its contours; and if Path_Contour overlaps
2686itself or another Path_Contour, whether the overlaps form part of the area.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002687path is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002688
Cary Clarkbad5ad72017-08-03 17:14:08 -04002689#Param path Path to combine with Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002690#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002691
2692#Example
2693#Height 212
2694#Description
2695Clip loops over itself covering its center twice. When clip's Path_Fill_Type
2696is set to SkPath::kWinding_FillType, the overlap is included. Set to
2697SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2698##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002699void draw(SkCanvas* canvas) {
2700 SkPaint paint;
2701 paint.setAntiAlias(true);
2702 SkPath path;
2703 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2704 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2705 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2706 path.setFillType(SkPath::kWinding_FillType);
2707 canvas->save();
2708 canvas->clipPath(path, SkClipOp::kIntersect);
2709 canvas->drawCircle(50, 50, 45, paint);
2710 canvas->restore();
2711 canvas->translate(100, 100);
2712 path.setFillType(SkPath::kEvenOdd_FillType);
2713 canvas->clipPath(path, SkClipOp::kIntersect);
2714 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002715}
2716##
2717
2718#ToDo incomplete ##
2719
2720##
2721
2722# ------------------------------------------------------------------------------
2723
2724#Method void setAllowSimplifyClip(bool allow)
2725
2726#Experimental
2727Only used for testing.
2728##
2729
Cary Clarkce101242017-09-01 15:51:02 -04002730Set to simplify clip stack using PathOps.
Cary Clark8032b982017-07-28 11:04:54 -04002731
2732##
2733
2734# ------------------------------------------------------------------------------
2735
2736#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2737
2738Replace Clip with the intersection or difference of Clip and Region deviceRgn.
Cary Clarkce101242017-09-01 15:51:02 -04002739Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002740deviceRgn is unaffected by Matrix.
2741
Cary Clarkbad5ad72017-08-03 17:14:08 -04002742#Param deviceRgn Region to combine with Clip ##
2743#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002744
2745#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002746#Description
Cary Clarkce101242017-09-01 15:51:02 -04002747 region is unaffected by canvas rotation; iRect is affected by canvas rotation.
2748 Both clips are Aliased; this is not noticeable on Region clip because it
Cary Clarkbad5ad72017-08-03 17:14:08 -04002749 aligns to pixel boundaries.
2750##
2751void draw(SkCanvas* canvas) {
2752 SkPaint paint;
2753 paint.setAntiAlias(true);
2754 SkIRect iRect = {30, 40, 120, 130 };
2755 SkRegion region(iRect);
2756 canvas->rotate(10);
2757 canvas->save();
2758 canvas->clipRegion(region, SkClipOp::kIntersect);
2759 canvas->drawCircle(50, 50, 45, paint);
2760 canvas->restore();
2761 canvas->translate(100, 100);
2762 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2763 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002764}
2765##
2766
2767#ToDo incomplete ##
2768
2769##
2770
2771#Method bool quickReject(const SkRect& rect) const
2772
2773Return true if Rect rect, transformed by Matrix, can be quickly determined to be
2774outside of Clip. May return false even though rect is outside of Clip.
2775
2776Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2777
Cary Clarkbad5ad72017-08-03 17:14:08 -04002778#Param rect Rect to compare with Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002779
Cary Clarkbad5ad72017-08-03 17:14:08 -04002780#Return true if rect, transformed by Matrix, does not intersect Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002781
2782#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002783void draw(SkCanvas* canvas) {
2784 SkRect testRect = {30, 30, 120, 129 };
2785 SkRect clipRect = {30, 130, 120, 230 };
2786 canvas->save();
2787 canvas->clipRect(clipRect);
2788 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2789 canvas->restore();
2790 canvas->rotate(10);
2791 canvas->clipRect(clipRect);
2792 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002793}
2794 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002795 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002796 quickReject false
2797 ##
2798##
2799
2800#ToDo incomplete ##
2801
2802##
2803
2804#Method bool quickReject(const SkPath& path) const
2805
2806Return true if path, transformed by Matrix, can be quickly determined to be
2807outside of Clip. May return false even though path is outside of Clip.
2808
2809Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2810
Cary Clarkbad5ad72017-08-03 17:14:08 -04002811#Param path Path to compare with Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002812
Cary Clarkbad5ad72017-08-03 17:14:08 -04002813#Return true if path, transformed by Matrix, does not intersect Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002814
2815#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002816void draw(SkCanvas* canvas) {
2817 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2818 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2819 SkPath testPath, clipPath;
2820 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2821 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2822 canvas->save();
2823 canvas->clipPath(clipPath);
2824 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2825 canvas->restore();
2826 canvas->rotate(10);
2827 canvas->clipPath(clipPath);
2828 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002829 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002830 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002831 quickReject false
2832 ##
2833}
2834##
2835
2836#ToDo incomplete ##
2837
2838##
2839
2840#Method SkRect getLocalClipBounds() const
2841
2842Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2843return SkRect::MakeEmpty, where all Rect sides equal zero.
2844
2845Rect returned is outset by one to account for partial pixel coverage if Clip
Cary Clarkce101242017-09-01 15:51:02 -04002846is Anti-aliased.
Cary Clark8032b982017-07-28 11:04:54 -04002847
Cary Clarkbad5ad72017-08-03 17:14:08 -04002848#Return bounds of Clip in local coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002849
2850#Example
2851 #Description
2852 Initial bounds is device bounds outset by 1 on all sides.
2853 Clipped bounds is clipPath bounds outset by 1 on all sides.
2854 Scaling the canvas by two in x and y scales the local bounds by 1/2 in x and y.
2855 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002856 SkCanvas local(256, 256);
2857 canvas = &local;
2858 SkRect bounds = canvas->getLocalClipBounds();
2859 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2860 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2861 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2862 SkPath clipPath;
2863 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2864 canvas->clipPath(clipPath);
2865 bounds = canvas->getLocalClipBounds();
2866 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2867 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2868 canvas->scale(2, 2);
2869 bounds = canvas->getLocalClipBounds();
2870 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2871 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2872 #StdOut
2873 left:-1 top:-1 right:257 bottom:257
2874 left:29 top:129 right:121 bottom:231
2875 left:14.5 top:64.5 right:60.5 bottom:115.5
2876 ##
Cary Clark8032b982017-07-28 11:04:54 -04002877##
2878
2879# local canvas in example works around bug in fiddle ##
2880#Bug 6524 ##
2881
2882##
2883
2884#Method bool getLocalClipBounds(SkRect* bounds) const
2885
2886Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2887return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2888
2889bounds is outset by one to account for partial pixel coverage if Clip
Cary Clarkce101242017-09-01 15:51:02 -04002890is Anti-aliased.
Cary Clark8032b982017-07-28 11:04:54 -04002891
Cary Clarkbad5ad72017-08-03 17:14:08 -04002892#Param bounds Rect of Clip in local coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002893
Cary Clarkbad5ad72017-08-03 17:14:08 -04002894#Return true if Clip bounds is not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04002895
2896#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002897 void draw(SkCanvas* canvas) {
2898 SkCanvas local(256, 256);
2899 canvas = &local;
2900 SkRect bounds;
2901 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2902 ? "false" : "true");
2903 SkPath path;
2904 canvas->clipPath(path);
2905 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2906 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002907 }
2908 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002909 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002910 local bounds empty = true
2911 ##
2912##
2913
2914# local canvas in example works around bug in fiddle ##
2915#Bug 6524 ##
2916
2917##
2918
2919#Method SkIRect getDeviceClipBounds() const
2920
2921Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2922return SkRect::MakeEmpty, where all Rect sides equal zero.
2923
2924Unlike getLocalClipBounds, returned IRect is not outset.
2925
Cary Clarkbad5ad72017-08-03 17:14:08 -04002926#Return bounds of Clip in Device coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002927
2928#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002929void draw(SkCanvas* canvas) {
2930 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002931 Initial bounds is device bounds, not outset.
2932 Clipped bounds is clipPath bounds, not outset.
2933 Scaling the canvas by 1/2 in x and y scales the device bounds by 1/2 in x and y.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002934 ##
2935 SkCanvas device(256, 256);
2936 canvas = &device;
2937 SkIRect bounds = canvas->getDeviceClipBounds();
2938 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2939 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2940 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2941 SkPath clipPath;
2942 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2943 canvas->save();
2944 canvas->clipPath(clipPath);
2945 bounds = canvas->getDeviceClipBounds();
2946 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2947 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2948 canvas->restore();
2949 canvas->scale(1.f/2, 1.f/2);
2950 canvas->clipPath(clipPath);
2951 bounds = canvas->getDeviceClipBounds();
2952 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2953 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002954 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002955 left:0 top:0 right:256 bottom:256
2956 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002957 left:15 top:65 right:60 bottom:115
2958 ##
2959}
2960##
2961
2962#ToDo some confusion on why with an identity Matrix local and device are different ##
2963
2964# device canvas in example works around bug in fiddle ##
2965#Bug 6524 ##
2966
2967##
2968
2969#Method bool getDeviceClipBounds(SkIRect* bounds) const
2970
2971Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2972return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2973
2974Unlike getLocalClipBounds, bounds is not outset.
2975
Cary Clarkbad5ad72017-08-03 17:14:08 -04002976#Param bounds Rect of Clip in device coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002977
Cary Clarkbad5ad72017-08-03 17:14:08 -04002978#Return true if Clip bounds is not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04002979
2980#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002981 void draw(SkCanvas* canvas) {
2982 SkIRect bounds;
2983 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2984 ? "false" : "true");
2985 SkPath path;
2986 canvas->clipPath(path);
2987 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2988 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002989 }
2990 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002991 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002992 device bounds empty = true
2993 ##
2994##
2995
2996#ToDo incomplete ##
2997
2998##
2999
3000#Topic Clip ##
3001
3002# ------------------------------------------------------------------------------
3003
3004#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
3005
3006Fill Clip with Color color.
3007mode determines how Color_ARGB is combined with destination.
3008
Cary Clarkbad5ad72017-08-03 17:14:08 -04003009#Param color Unpremultiplied Color_ARGB ##
3010#Param mode SkBlendMode used to combine source color and destination ##
Cary Clark8032b982017-07-28 11:04:54 -04003011
3012#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003013 canvas->drawColor(SK_ColorRED);
3014 canvas->clipRect(SkRect::MakeWH(150, 150));
3015 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
3016 canvas->clipRect(SkRect::MakeWH(75, 75));
3017 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04003018##
3019
3020#ToDo incomplete ##
3021
3022##
3023
3024# ------------------------------------------------------------------------------
3025
3026#Method void clear(SkColor color)
3027
3028Fill Clip with Color color using SkBlendMode::kSrc.
3029This has the effect of replacing all pixels contained by Clip with color.
3030
Cary Clarkbad5ad72017-08-03 17:14:08 -04003031#Param color Unpremultiplied Color_ARGB ##
Cary Clark8032b982017-07-28 11:04:54 -04003032
3033#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003034void draw(SkCanvas* canvas) {
3035 canvas->save();
3036 canvas->clipRect(SkRect::MakeWH(256, 128));
3037 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
3038 canvas->restore();
3039 canvas->save();
3040 canvas->clipRect(SkRect::MakeWH(150, 192));
3041 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
3042 canvas->restore();
3043 canvas->clipRect(SkRect::MakeWH(75, 256));
3044 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04003045}
3046##
3047
3048#ToDo incomplete ##
3049
3050##
3051
3052# ------------------------------------------------------------------------------
3053
3054#Method void discard()
3055
3056Make Canvas contents undefined. Subsequent calls that read Canvas pixels,
3057such as drawing with SkBlendMode, return undefined results. discard() does
3058not change Clip or Matrix.
3059
3060discard() may do nothing, depending on the implementation of Surface or Device
3061that created Canvas.
3062
3063discard() allows optimized performance on subsequent draws by removing
3064cached data associated with Surface or Device.
3065It is not necessary to call discard() once done with Canvas;
3066any cached data is deleted when owning Surface or Device is deleted.
3067
3068#ToDo example? not sure how to make this meaningful w/o more implementation detail ##
3069
3070#NoExample
3071##
3072
3073##
3074
3075# ------------------------------------------------------------------------------
3076
3077#Method void drawPaint(const SkPaint& paint)
3078
Cary Clarkbad5ad72017-08-03 17:14:08 -04003079Fill Clip with Paint paint. Paint components Rasterizer, Mask_Filter, Shader,
3080Color_Filter, Image_Filter, and Blend_Mode affect drawing;
3081Path_Effect in paint is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04003082
3083# can Path_Effect in paint ever alter drawPaint?
3084
Cary Clarkbad5ad72017-08-03 17:14:08 -04003085#Param paint graphics state used to fill Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04003086
3087#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003088void draw(SkCanvas* canvas) {
3089 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
3090 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
3091 SkPaint paint;
3092 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
3093 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04003094}
3095##
3096
3097#ToDo incomplete ##
3098
3099##
3100
3101# ------------------------------------------------------------------------------
3102
3103#Enum PointMode
3104
3105#Code
3106 enum PointMode {
3107 kPoints_PointMode,
3108 kLines_PointMode,
Cary Clarkd0530ba2017-09-14 11:25:39 -04003109 kPolygon_PointMode,
Cary Clark8032b982017-07-28 11:04:54 -04003110 };
3111##
3112
3113Selects if an array of points are drawn as discrete points, as lines, or as
3114an open polygon.
3115
3116#Const kPoints_PointMode 0
3117 Draw each point separately.
3118##
3119
3120#Const kLines_PointMode 1
3121 Draw each pair of points as a line segment.
3122##
3123
3124#Const kPolygon_PointMode 2
3125 Draw the array of points as a open polygon.
3126##
3127
3128#Example
3129 #Description
3130 The upper left corner shows three squares when drawn as points.
3131 The upper right corner shows one line; when drawn as lines, two points are required per line.
3132 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
3133 The lower left corner shows two lines with a miter when path contains polygon.
3134 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003135void draw(SkCanvas* canvas) {
3136 SkPaint paint;
3137 paint.setStyle(SkPaint::kStroke_Style);
3138 paint.setStrokeWidth(10);
3139 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
3140 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
3141 canvas->translate(128, 0);
3142 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
3143 canvas->translate(0, 128);
3144 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
3145 SkPath path;
3146 path.addPoly(points, 3, false);
3147 canvas->translate(-128, 0);
3148 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003149}
3150##
3151
3152#ToDo incomplete ##
3153
3154##
3155
3156# ------------------------------------------------------------------------------
3157
3158#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
3159
3160Draw pts using Clip, Matrix and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003161count is the number of points; if count is less than one, has no effect.
Cary Clark8032b982017-07-28 11:04:54 -04003162mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
3163
Cary Clarkbad5ad72017-08-03 17:14:08 -04003164If mode is kPoints_PointMode, the shape of point drawn depends on paint
3165Paint_Stroke_Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
3166circle of diameter Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap
3167or SkPaint::kButt_Cap, each point draws a square of width and height
3168Paint_Stroke_Width.
Cary Clark8032b982017-07-28 11:04:54 -04003169
3170If mode is kLines_PointMode, each pair of points draws a line segment.
3171One line is drawn for every two points; each point is used once. If count is odd,
3172the final point is ignored.
3173
3174If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
3175count minus one lines are drawn; the first and last point are used once.
3176
3177Each line segment respects paint Paint_Stroke_Cap and Paint_Stroke_Width.
3178Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3179
Cary Clarkbad5ad72017-08-03 17:14:08 -04003180Always draws each element one at a time; is not affected by
3181Paint_Stroke_Join, and unlike drawPath, does not create a mask from all points
3182and lines before drawing.
Cary Clark8032b982017-07-28 11:04:54 -04003183
Cary Clarka523d2d2017-08-30 08:58:10 -04003184#Param mode whether pts draws points or lines ##
3185#Param count number of points in the array ##
3186#Param pts array of points to draw ##
3187#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003188
3189#Example
3190#Height 200
3191 #Description
3192 #List
3193 # The first column draws points. ##
3194 # The second column draws points as lines. ##
3195 # The third column draws points as a polygon. ##
3196 # The fourth column draws points as a polygonal path. ##
3197 # The first row uses a round cap and round join. ##
3198 # The second row uses a square cap and a miter join. ##
3199 # The third row uses a butt cap and a bevel join. ##
3200 ##
3201 The transparent color makes multiple line draws visible;
3202 the path is drawn all at once.
3203 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003204void draw(SkCanvas* canvas) {
3205 SkPaint paint;
3206 paint.setAntiAlias(true);
3207 paint.setStyle(SkPaint::kStroke_Style);
3208 paint.setStrokeWidth(10);
3209 paint.setColor(0x80349a45);
3210 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
3211 const SkPaint::Join join[] = { SkPaint::kRound_Join,
3212 SkPaint::kMiter_Join,
3213 SkPaint::kBevel_Join };
3214 int joinIndex = 0;
3215 SkPath path;
3216 path.addPoly(points, 3, false);
3217 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
3218 paint.setStrokeCap(cap);
3219 paint.setStrokeJoin(join[joinIndex++]);
3220 for (const auto mode : { SkCanvas::kPoints_PointMode,
3221 SkCanvas::kLines_PointMode,
3222 SkCanvas::kPolygon_PointMode } ) {
3223 canvas->drawPoints(mode, 3, points, paint);
3224 canvas->translate(64, 0);
3225 }
3226 canvas->drawPath(path, paint);
3227 canvas->translate(-192, 64);
3228 }
Cary Clark8032b982017-07-28 11:04:54 -04003229}
3230##
3231
3232#ToDo incomplete ##
3233
3234##
3235
3236# ------------------------------------------------------------------------------
3237
3238#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
3239
3240Draw point at (x, y) using Clip, Matrix and Paint paint.
3241
3242The shape of point drawn depends on paint Paint_Stroke_Cap.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003243If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
3244Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04003245draw a square of width and height Paint_Stroke_Width.
3246Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3247
Cary Clarkbad5ad72017-08-03 17:14:08 -04003248#Param x left edge of circle or square ##
3249#Param y top edge of circle or square ##
3250#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003251
3252#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003253void draw(SkCanvas* canvas) {
3254 SkPaint paint;
3255 paint.setAntiAlias(true);
3256 paint.setColor(0x80349a45);
3257 paint.setStyle(SkPaint::kStroke_Style);
3258 paint.setStrokeWidth(100);
3259 paint.setStrokeCap(SkPaint::kRound_Cap);
3260 canvas->scale(1, 1.2f);
3261 canvas->drawPoint(64, 96, paint);
3262 canvas->scale(.6f, .8f);
3263 paint.setColor(SK_ColorWHITE);
3264 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003265}
3266##
3267
3268#ToDo incomplete ##
3269
3270##
3271
Cary Clarkbad5ad72017-08-03 17:14:08 -04003272#Method void drawPoint(SkPoint p, const SkPaint& paint)
3273
3274Draw point p using Clip, Matrix and Paint paint.
3275
3276The shape of point drawn depends on paint Paint_Stroke_Cap.
3277If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
3278Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
3279draw a square of width and height Paint_Stroke_Width.
3280Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3281
3282#Param p top-left edge of circle or square ##
3283#Param paint stroke, blend, color, and so on, used to draw ##
3284
3285#Example
3286void draw(SkCanvas* canvas) {
3287 SkPaint paint;
3288 paint.setAntiAlias(true);
3289 paint.setColor(0x80349a45);
3290 paint.setStyle(SkPaint::kStroke_Style);
3291 paint.setStrokeWidth(100);
3292 paint.setStrokeCap(SkPaint::kSquare_Cap);
3293 canvas->scale(1, 1.2f);
3294 canvas->drawPoint({64, 96}, paint);
3295 canvas->scale(.6f, .8f);
3296 paint.setColor(SK_ColorWHITE);
3297 canvas->drawPoint(106, 120, paint);
3298}
3299##
3300
3301#SeeAlso drawPoints drawCircle drawRect
3302
3303##
3304
Cary Clark8032b982017-07-28 11:04:54 -04003305# ------------------------------------------------------------------------------
3306
3307#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
3308
Cary Clarkbad5ad72017-08-03 17:14:08 -04003309Draws line segment from (x0, y0) to (x1, y1) using Clip, Matrix, and Paint paint.
3310In paint: Paint_Stroke_Width describes the line thickness;
3311Paint_Stroke_Cap draws the end rounded or square;
Cary Clark8032b982017-07-28 11:04:54 -04003312Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3313
Cary Clarkbad5ad72017-08-03 17:14:08 -04003314#Param x0 start of line segment on x-axis ##
3315#Param y0 start of line segment on y-axis ##
3316#Param x1 end of line segment on x-axis ##
3317#Param y1 end of line segment on y-axis ##
3318#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003319
3320#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003321 SkPaint paint;
3322 paint.setAntiAlias(true);
3323 paint.setColor(0xFF9a67be);
3324 paint.setStrokeWidth(20);
3325 canvas->skew(1, 0);
3326 canvas->drawLine(32, 96, 32, 160, paint);
3327 canvas->skew(-2, 0);
3328 canvas->drawLine(288, 96, 288, 160, paint);
3329##
3330
3331#ToDo incomplete ##
3332
3333##
3334
3335#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
3336
3337Draws line segment from p0 to p1 using Clip, Matrix, and Paint paint.
3338In paint: Paint_Stroke_Width describes the line thickness;
3339Paint_Stroke_Cap draws the end rounded or square;
3340Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3341
3342#Param p0 start of line segment ##
3343#Param p1 end of line segment ##
3344#Param paint stroke, blend, color, and so on, used to draw ##
3345
3346#Example
3347 SkPaint paint;
3348 paint.setAntiAlias(true);
3349 paint.setColor(0xFF9a67be);
3350 paint.setStrokeWidth(20);
3351 canvas->skew(1, 0);
3352 canvas->drawLine({32, 96}, {32, 160}, paint);
3353 canvas->skew(-2, 0);
3354 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003355##
3356
3357#ToDo incomplete ##
3358
3359##
3360
3361# ------------------------------------------------------------------------------
3362
3363#Method void drawRect(const SkRect& rect, const SkPaint& paint)
3364
3365Draw Rect rect using Clip, Matrix, and Paint paint.
3366In paint: Paint_Style determines if rectangle is stroked or filled;
3367if stroked, Paint_Stroke_Width describes the line thickness, and
3368Paint_Stroke_Join draws the corners rounded or square.
3369
Cary Clarkbad5ad72017-08-03 17:14:08 -04003370#Param rect rectangle to be drawn ##
3371#Param paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003372
3373#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003374void draw(SkCanvas* canvas) {
3375 SkPoint rectPts[] = { {64, 48}, {192, 160} };
3376 SkPaint paint;
3377 paint.setAntiAlias(true);
3378 paint.setStyle(SkPaint::kStroke_Style);
3379 paint.setStrokeWidth(20);
3380 paint.setStrokeJoin(SkPaint::kRound_Join);
3381 SkMatrix rotator;
3382 rotator.setRotate(30, 128, 128);
3383 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3384 paint.setColor(color);
3385 SkRect rect;
3386 rect.set(rectPts[0], rectPts[1]);
3387 canvas->drawRect(rect, paint);
3388 rotator.mapPoints(rectPts, 2);
3389 }
Cary Clark8032b982017-07-28 11:04:54 -04003390}
3391##
3392
3393#ToDo incomplete ##
3394
3395##
3396
3397# ------------------------------------------------------------------------------
3398
3399#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
3400
3401Draw IRect rect using Clip, Matrix, and Paint paint.
3402In paint: Paint_Style determines if rectangle is stroked or filled;
3403if stroked, Paint_Stroke_Width describes the line thickness, and
3404Paint_Stroke_Join draws the corners rounded or square.
3405
Cary Clarkbad5ad72017-08-03 17:14:08 -04003406#Param rect rectangle to be drawn ##
3407#Param paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003408
3409#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003410 SkIRect rect = { 64, 48, 192, 160 };
3411 SkPaint paint;
3412 paint.setAntiAlias(true);
3413 paint.setStyle(SkPaint::kStroke_Style);
3414 paint.setStrokeWidth(20);
3415 paint.setStrokeJoin(SkPaint::kRound_Join);
3416 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3417 paint.setColor(color);
3418 canvas->drawIRect(rect, paint);
3419 canvas->rotate(30, 128, 128);
3420 }
Cary Clark8032b982017-07-28 11:04:54 -04003421##
3422
3423#ToDo incomplete ##
3424
3425##
3426
3427# ------------------------------------------------------------------------------
3428
3429#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
3430
3431Draw Region region using Clip, Matrix, and Paint paint.
3432In paint: Paint_Style determines if rectangle is stroked or filled;
3433if stroked, Paint_Stroke_Width describes the line thickness, and
3434Paint_Stroke_Join draws the corners rounded or square.
3435
Cary Clarkbad5ad72017-08-03 17:14:08 -04003436#Param region region to be drawn ##
3437#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003438
3439#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003440void draw(SkCanvas* canvas) {
3441 SkRegion region;
3442 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3443 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3444 SkPaint paint;
3445 paint.setAntiAlias(true);
3446 paint.setStyle(SkPaint::kStroke_Style);
3447 paint.setStrokeWidth(20);
3448 paint.setStrokeJoin(SkPaint::kRound_Join);
3449 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003450}
3451##
3452
3453#ToDo incomplete ##
3454
3455##
3456
3457# ------------------------------------------------------------------------------
3458
3459#Method void drawOval(const SkRect& oval, const SkPaint& paint)
3460
3461Draw Oval oval using Clip, Matrix, and Paint.
3462In paint: Paint_Style determines if Oval is stroked or filled;
3463if stroked, Paint_Stroke_Width describes the line thickness.
3464
Cary Clarkbad5ad72017-08-03 17:14:08 -04003465#Param oval Rect bounds of Oval ##
3466#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003467
3468#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003469void draw(SkCanvas* canvas) {
3470 canvas->clear(0xFF3f5f9f);
3471 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
3472 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
3473 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
3474 SkScalar pos[] = { 0.2f, 1.0f };
3475 SkRect bounds = SkRect::MakeWH(80, 70);
3476 SkPaint paint;
3477 paint.setAntiAlias(true);
3478 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
3479 SkShader::kClamp_TileMode));
3480 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04003481}
3482##
3483
3484#ToDo incomplete ##
3485
3486##
3487
3488# ------------------------------------------------------------------------------
3489
3490#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
3491
3492Draw Round_Rect rrect using Clip, Matrix, and Paint paint.
3493In paint: Paint_Style determines if rrect is stroked or filled;
3494if stroked, Paint_Stroke_Width describes the line thickness.
3495
Cary Clarkbad5ad72017-08-03 17:14:08 -04003496rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
3497may have any combination of positive non-square radii for the four corners.
Cary Clark8032b982017-07-28 11:04:54 -04003498
Cary Clarkbad5ad72017-08-03 17:14:08 -04003499#Param rrect Round_Rect with up to eight corner radii to draw ##
3500#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003501
3502#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003503void draw(SkCanvas* canvas) {
3504 SkPaint paint;
3505 paint.setAntiAlias(true);
3506 SkRect outer = {30, 40, 210, 220};
3507 SkRect radii = {30, 50, 70, 90 };
3508 SkRRect rRect;
3509 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
3510 canvas->drawRRect(rRect, paint);
3511 paint.setColor(SK_ColorWHITE);
3512 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
3513 outer.fLeft + radii.fLeft, outer.fBottom, paint);
3514 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
3515 outer.fRight - radii.fRight, outer.fBottom, paint);
3516 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
3517 outer.fRight, outer.fTop + radii.fTop, paint);
3518 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
3519 outer.fRight, outer.fBottom - radii.fBottom, paint);
3520}
Cary Clark8032b982017-07-28 11:04:54 -04003521##
3522
3523#ToDo incomplete ##
3524
3525##
3526
3527# ------------------------------------------------------------------------------
3528
3529#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
3530
3531Draw Round_Rect outer and inner
3532using Clip, Matrix, and Paint paint.
3533outer must contain inner or the drawing is undefined.
Cary Clarkce101242017-09-01 15:51:02 -04003534In paint: Paint_Style determines if Round_Rect is stroked or filled;
Cary Clark8032b982017-07-28 11:04:54 -04003535if stroked, Paint_Stroke_Width describes the line thickness.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003536If stroked and Round_Rect corner has zero length radii, Paint_Stroke_Join can
3537draw corners rounded or square.
Cary Clark8032b982017-07-28 11:04:54 -04003538
Cary Clarkbad5ad72017-08-03 17:14:08 -04003539GPU-backed platforms optimize drawing when both outer and inner are
Cary Clark8032b982017-07-28 11:04:54 -04003540concave and outer contains inner. These platforms may not be able to draw
3541Path built with identical data as fast.
3542
Cary Clarkbad5ad72017-08-03 17:14:08 -04003543#Param outer Round_Rect outer bounds to draw ##
3544#Param inner Round_Rect inner bounds to draw ##
3545#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003546
3547#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003548void draw(SkCanvas* canvas) {
3549 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3550 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
3551 SkPaint paint;
3552 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003553}
3554##
3555
3556#Example
3557#Description
3558 Outer Rect has no corner radii, but stroke join is rounded.
3559 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
3560 Stroke join does not affect inner Round_Rect since it has no sharp corners.
3561##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003562void draw(SkCanvas* canvas) {
3563 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3564 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
3565 SkPaint paint;
3566 paint.setAntiAlias(true);
3567 paint.setStyle(SkPaint::kStroke_Style);
3568 paint.setStrokeWidth(20);
3569 paint.setStrokeJoin(SkPaint::kRound_Join);
3570 canvas->drawDRRect(outer, inner, paint);
3571 paint.setStrokeWidth(1);
3572 paint.setColor(SK_ColorWHITE);
3573 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003574}
3575##
3576
3577#ToDo incomplete ##
3578
3579##
3580
3581# ------------------------------------------------------------------------------
3582
3583#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
3584
3585Draw Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint.
3586If radius is zero or less, nothing is drawn.
3587In paint: Paint_Style determines if Circle is stroked or filled;
3588if stroked, Paint_Stroke_Width describes the line thickness.
3589
Cary Clarkbad5ad72017-08-03 17:14:08 -04003590#Param cx Circle center on the x-axis ##
3591#Param cy Circle center on the y-axis ##
3592#Param radius half the diameter of Circle ##
3593#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003594
3595#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003596 void draw(SkCanvas* canvas) {
3597 SkPaint paint;
3598 paint.setAntiAlias(true);
3599 canvas->drawCircle(128, 128, 90, paint);
3600 paint.setColor(SK_ColorWHITE);
3601 canvas->drawCircle(86, 86, 20, paint);
3602 canvas->drawCircle(160, 76, 20, paint);
3603 canvas->drawCircle(140, 150, 35, paint);
3604 }
3605##
3606
3607#ToDo incomplete ##
3608
3609##
3610
3611#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
3612
Cary Clarkce101242017-09-01 15:51:02 -04003613Draw Circle at center with radius using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003614If radius is zero or less, nothing is drawn.
3615In paint: Paint_Style determines if Circle is stroked or filled;
3616if stroked, Paint_Stroke_Width describes the line thickness.
3617
3618#Param center Circle center ##
3619#Param radius half the diameter of Circle ##
3620#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
3621
3622#Example
3623 void draw(SkCanvas* canvas) {
3624 SkPaint paint;
3625 paint.setAntiAlias(true);
3626 canvas->drawCircle(128, 128, 90, paint);
3627 paint.setColor(SK_ColorWHITE);
3628 canvas->drawCircle({86, 86}, 20, paint);
3629 canvas->drawCircle({160, 76}, 20, paint);
3630 canvas->drawCircle({140, 150}, 35, paint);
3631 }
Cary Clark8032b982017-07-28 11:04:54 -04003632##
3633
3634#ToDo incomplete ##
3635
3636##
3637
3638# ------------------------------------------------------------------------------
3639
3640#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
3641 bool useCenter, const SkPaint& paint)
3642
3643Draw Arc using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003644
Cary Clark8032b982017-07-28 11:04:54 -04003645Arc is part of Oval bounded by oval, sweeping from startAngle to startAngle plus
3646sweepAngle. startAngle and sweepAngle are in degrees.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003647
Cary Clark8032b982017-07-28 11:04:54 -04003648startAngle of zero places start point at the right middle edge of oval.
3649A positive sweepAngle places Arc end point clockwise from start point;
3650a negative sweepAngle places Arc end point counterclockwise from start point.
3651sweepAngle may exceed 360 degrees, a full circle.
3652If useCenter is true, draw a wedge that includes lines from oval
3653center to Arc end points. If useCenter is false, draw Arc between end points.
3654
3655If Rect oval is empty or sweepAngle is zero, nothing is drawn.
3656
Cary Clarkbad5ad72017-08-03 17:14:08 -04003657#Param oval Rect bounds of Oval containing Arc to draw ##
3658#Param startAngle angle in degrees where Arc begins ##
3659#Param sweepAngle sweep angle in degrees; positive is clockwise ##
3660#Param useCenter if true, include the center of the oval ##
3661#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003662
3663#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003664 void draw(SkCanvas* canvas) {
3665 SkPaint paint;
3666 paint.setAntiAlias(true);
3667 SkRect oval = { 4, 4, 60, 60};
3668 for (auto useCenter : { false, true } ) {
3669 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
3670 paint.setStyle(style);
3671 for (auto degrees : { 45, 90, 180, 360} ) {
3672 canvas->drawArc(oval, 0, degrees , useCenter, paint);
3673 canvas->translate(64, 0);
3674 }
3675 canvas->translate(-256, 64);
3676 }
3677 }
Cary Clark8032b982017-07-28 11:04:54 -04003678 }
3679##
3680
3681#Example
3682#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003683 void draw(SkCanvas* canvas) {
3684 SkPaint paint;
3685 paint.setAntiAlias(true);
3686 paint.setStyle(SkPaint::kStroke_Style);
3687 paint.setStrokeWidth(4);
3688 SkRect oval = { 4, 4, 60, 60};
3689 float intervals[] = { 5, 5 };
3690 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
3691 for (auto degrees : { 270, 360, 540, 720 } ) {
3692 canvas->drawArc(oval, 0, degrees, false, paint);
3693 canvas->translate(64, 0);
3694 }
Cary Clark8032b982017-07-28 11:04:54 -04003695 }
3696##
3697
3698#ToDo incomplete ##
3699
3700##
3701
3702# ------------------------------------------------------------------------------
3703
3704#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
3705
Cary Clarkbad5ad72017-08-03 17:14:08 -04003706Draw Round_Rect bounded by Rect rect, with corner radii (rx, ry) using Clip,
3707Matrix, and Paint paint.
3708
Cary Clark8032b982017-07-28 11:04:54 -04003709In paint: Paint_Style determines if Round_Rect is stroked or filled;
3710if stroked, Paint_Stroke_Width describes the line thickness.
3711If rx or ry are less than zero, they are treated as if they are zero.
3712If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003713If rx and ry are zero, Round_Rect is drawn as Rect and if stroked is affected by
3714Paint_Stroke_Join.
Cary Clark8032b982017-07-28 11:04:54 -04003715
Cary Clarkbad5ad72017-08-03 17:14:08 -04003716#Param rect Rect bounds of Round_Rect to draw ##
Cary Clarkce101242017-09-01 15:51:02 -04003717#Param rx axis length in x of oval describing rounded corners ##
3718#Param ry axis length in y of oval describing rounded corners ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003719#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003720
3721#Example
3722#Description
3723 Top row has a zero radius a generates a rectangle.
3724 Second row radii sum to less than sides.
3725 Third row radii sum equals sides.
3726 Fourth row radii sum exceeds sides; radii are scaled to fit.
3727##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003728 void draw(SkCanvas* canvas) {
3729 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
3730 SkPaint paint;
3731 paint.setStrokeWidth(15);
3732 paint.setStrokeJoin(SkPaint::kRound_Join);
3733 paint.setAntiAlias(true);
3734 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
3735 paint.setStyle(style );
3736 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
3737 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
3738 canvas->translate(0, 60);
3739 }
3740 canvas->translate(80, -240);
3741 }
Cary Clark8032b982017-07-28 11:04:54 -04003742 }
3743##
3744
3745#ToDo incomplete ##
3746
3747##
3748
3749# ------------------------------------------------------------------------------
3750
3751#Method void drawPath(const SkPath& path, const SkPaint& paint)
3752
3753Draw Path path using Clip, Matrix, and Paint paint.
3754Path contains an array of Path_Contour, each of which may be open or closed.
3755
3756In paint: Paint_Style determines if Round_Rect is stroked or filled:
Cary Clarkbad5ad72017-08-03 17:14:08 -04003757if filled, Path_Fill_Type determines whether Path_Contour describes inside or
3758outside of fill; if stroked, Paint_Stroke_Width describes the line thickness,
3759Paint_Stroke_Cap describes line ends, and Paint_Stroke_Join describes how
3760corners are drawn.
Cary Clark8032b982017-07-28 11:04:54 -04003761
Cary Clarkbad5ad72017-08-03 17:14:08 -04003762#Param path Path to draw ##
3763#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003764
3765#Example
3766#Description
3767 Top rows draw stroked path with combinations of joins and caps. The open contour
3768 is affected by caps; the closed contour is affected by joins.
3769 Bottom row draws fill the same for open and closed contour.
3770 First bottom column shows winding fills overlap.
3771 Second bottom column shows even odd fills exclude overlap.
3772 Third bottom column shows inverse winding fills area outside both contours.
3773##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003774void draw(SkCanvas* canvas) {
3775 SkPath path;
3776 path.moveTo(20, 20);
3777 path.quadTo(60, 20, 60, 60);
3778 path.close();
3779 path.moveTo(60, 20);
3780 path.quadTo(60, 60, 20, 60);
3781 SkPaint paint;
3782 paint.setStrokeWidth(10);
3783 paint.setAntiAlias(true);
3784 paint.setStyle(SkPaint::kStroke_Style);
3785 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
3786 paint.setStrokeJoin(join);
3787 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
3788 paint.setStrokeCap(cap);
3789 canvas->drawPath(path, paint);
3790 canvas->translate(80, 0);
3791 }
3792 canvas->translate(-240, 60);
3793 }
3794 paint.setStyle(SkPaint::kFill_Style);
3795 for (auto fill : { SkPath::kWinding_FillType,
3796 SkPath::kEvenOdd_FillType,
3797 SkPath::kInverseWinding_FillType } ) {
3798 path.setFillType(fill);
3799 canvas->save();
3800 canvas->clipRect({0, 10, 80, 70});
3801 canvas->drawPath(path, paint);
3802 canvas->restore();
3803 canvas->translate(80, 0);
3804 }
Cary Clark8032b982017-07-28 11:04:54 -04003805}
3806##
3807
3808#ToDo incomplete ##
3809
3810##
3811
3812# ------------------------------------------------------------------------------
3813#Topic Draw_Image
3814
Cary Clarkbad5ad72017-08-03 17:14:08 -04003815drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
3816a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04003817
Cary Clark73fa9722017-08-29 17:36:51 -04003818#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04003819
3820Draw Image image, with its top-left corner at (left, top),
3821using Clip, Matrix, and optional Paint paint.
3822
Cary Clarkbad5ad72017-08-03 17:14:08 -04003823If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode,
3824and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3825If paint contains Mask_Filter, generate mask from image bounds. If generated
3826mask extends beyond image bounds, replicate image edge colors, just as Shader
3827made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
3828image's edge color when it samples outside of its bounds.
Cary Clark8032b982017-07-28 11:04:54 -04003829
Cary Clarkbad5ad72017-08-03 17:14:08 -04003830#Param image uncompressed rectangular map of pixels ##
3831#Param left left side of image ##
3832#Param top top side of image ##
3833#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3834 and so on; or nullptr
3835##
Cary Clark8032b982017-07-28 11:04:54 -04003836
3837#Example
3838#Height 64
3839#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003840void draw(SkCanvas* canvas) {
3841 // sk_sp<SkImage> image;
3842 SkImage* imagePtr = image.get();
3843 canvas->drawImage(imagePtr, 0, 0);
3844 SkPaint paint;
3845 canvas->drawImage(imagePtr, 80, 0, &paint);
3846 paint.setAlpha(0x80);
3847 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003848}
3849##
3850
3851#ToDo incomplete ##
3852
3853##
3854
3855# ------------------------------------------------------------------------------
3856
3857#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003858 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04003859
3860Draw Image image, with its top-left corner at (left, top),
3861using Clip, Matrix, and optional Paint paint.
3862
Cary Clarkbad5ad72017-08-03 17:14:08 -04003863If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3864Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3865If paint contains Mask_Filter, generate mask from image bounds. If generated
3866mask extends beyond image bounds, replicate image edge colors, just as Shader
3867made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
3868image's edge color when it samples outside of its bounds.
Cary Clark8032b982017-07-28 11:04:54 -04003869
Cary Clarkbad5ad72017-08-03 17:14:08 -04003870#Param image uncompressed rectangular map of pixels ##
3871#Param left left side of image ##
3872#Param top pop side of image ##
3873#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3874 and so on; or nullptr
3875##
Cary Clark8032b982017-07-28 11:04:54 -04003876
3877#Example
3878#Height 64
3879#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003880void draw(SkCanvas* canvas) {
3881 // sk_sp<SkImage> image;
3882 canvas->drawImage(image, 0, 0);
3883 SkPaint paint;
3884 canvas->drawImage(image, 80, 0, &paint);
3885 paint.setAlpha(0x80);
3886 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003887}
3888##
3889
3890#ToDo incomplete ##
3891
3892##
3893
3894# ------------------------------------------------------------------------------
3895
3896#Enum SrcRectConstraint
3897
3898#Code
3899 enum SrcRectConstraint {
3900 kStrict_SrcRectConstraint,
3901 kFast_SrcRectConstraint,
3902 };
3903##
3904
Cary Clarkce101242017-09-01 15:51:02 -04003905SrcRectConstraint controls the behavior at the edge of source Rect,
3906provided to drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04003907
Cary Clarkce101242017-09-01 15:51:02 -04003908Image_Filter in Paint may sample multiple pixels in the image. Source Rect
Cary Clarkbad5ad72017-08-03 17:14:08 -04003909restricts the bounds of pixels that may be read. Image_Filter may slow down if
Cary Clarkce101242017-09-01 15:51:02 -04003910it cannot read outside the bounds, when sampling near the edge of source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003911SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
Cary Clarkce101242017-09-01 15:51:02 -04003912outside source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003913
3914#Const kStrict_SrcRectConstraint
Cary Clarkce101242017-09-01 15:51:02 -04003915 Requires Image_Filter to respect source Rect,
Cary Clark8032b982017-07-28 11:04:54 -04003916 sampling only inside of its bounds, possibly with a performance penalty.
3917##
3918
3919#Const kFast_SrcRectConstraint
Cary Clarkce101242017-09-01 15:51:02 -04003920 Permits Image_Filter to sample outside of source Rect
Cary Clark8032b982017-07-28 11:04:54 -04003921 by half the width of Image_Filter, permitting it to run faster but with
3922 error at the image edges.
3923##
3924
3925#Example
3926#Height 64
3927#Description
3928 redBorder contains a black and white checkerboard bordered by red.
3929 redBorder is drawn scaled by 16 on the left.
Cary Clarkce101242017-09-01 15:51:02 -04003930 The middle and right bitmaps are filtered checkerboards.
Cary Clark8032b982017-07-28 11:04:54 -04003931 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3932 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3933##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003934void draw(SkCanvas* canvas) {
3935 SkBitmap redBorder;
3936 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3937 SkCanvas checkRed(redBorder);
3938 checkRed.clear(SK_ColorRED);
3939 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3940 { SK_ColorWHITE, SK_ColorBLACK } };
3941 checkRed.writePixels(
3942 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3943 canvas->scale(16, 16);
3944 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3945 canvas->resetMatrix();
3946 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3947 SkPaint lowPaint;
3948 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3949 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3950 SkCanvas::kFast_SrcRectConstraint } ) {
3951 canvas->translate(80, 0);
3952 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3953 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3954 }
Cary Clark8032b982017-07-28 11:04:54 -04003955}
3956##
3957
3958#ToDo incomplete ##
3959
3960##
3961
3962# ------------------------------------------------------------------------------
3963
3964#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3965 const SkPaint* paint,
3966 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3967
3968Draw Rect src of Image image, scaled and translated to fill Rect dst.
3969Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003970
Cary Clarkbad5ad72017-08-03 17:14:08 -04003971If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3972Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3973If paint contains Mask_Filter, generate mask from image bounds.
3974
3975If generated mask extends beyond image bounds, replicate image edge colors, just
3976as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
3977replicates the image's edge color when it samples outside of its bounds.
3978
3979constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
3980sample within src; set to kFast_SrcRectConstraint allows sampling outside to
3981improve performance.
3982
3983#Param image Image containing pixels, dimensions, and format ##
3984#Param src source Rect of image to draw from ##
3985#Param dst destination Rect of image to draw to ##
3986#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3987 and so on; or nullptr
3988##
3989#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04003990
3991#Example
3992#Height 64
3993#Description
3994 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
3995 its bounds; there's no bleeding with kFast_SrcRectConstraint.
3996 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3997 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3998 with kFast_SrcRectConstraint red bleeds on the edges.
3999##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004000void draw(SkCanvas* canvas) {
4001 uint32_t pixels[][4] = {
4002 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
4003 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
4004 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
4005 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
4006 SkBitmap redBorder;
4007 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
4008 (void*) pixels, sizeof(pixels[0]));
4009 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
4010 SkPaint lowPaint;
4011 for (auto constraint : {
4012 SkCanvas::kFast_SrcRectConstraint,
4013 SkCanvas::kStrict_SrcRectConstraint,
4014 SkCanvas::kFast_SrcRectConstraint } ) {
4015 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
4016 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
4017 lowPaint.setFilterQuality(kLow_SkFilterQuality);
4018 canvas->translate(80, 0);
4019 }
4020}
Cary Clark8032b982017-07-28 11:04:54 -04004021##
4022
4023#ToDo incomplete ##
4024
4025##
4026
4027# ------------------------------------------------------------------------------
4028
4029#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
4030 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4031
4032Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004033Note that isrc is on integer pixel boundaries; dst may include fractional
4034boundaries. Additionally transform draw using Clip, Matrix, and optional Paint
4035paint.
Cary Clark8032b982017-07-28 11:04:54 -04004036
Cary Clarkbad5ad72017-08-03 17:14:08 -04004037If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4038Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4039If paint contains Mask_Filter, generate mask from image bounds.
4040
4041If generated mask extends beyond image bounds, replicate image edge colors, just
4042as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4043replicates the image's edge color when it samples outside of its bounds.
4044
4045constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004046sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004047improve performance.
4048
4049#Param image Image containing pixels, dimensions, and format ##
4050#Param isrc source IRect of image to draw from ##
4051#Param dst destination Rect of image to draw to ##
4052#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4053 and so on; or nullptr
4054##
Cary Clarkce101242017-09-01 15:51:02 -04004055#Param constraint filter strictly within isrc or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004056
4057#Example
4058#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04004059void draw(SkCanvas* canvas) {
4060 // sk_sp<SkImage> image;
4061 for (auto i : { 1, 2, 4, 8 } ) {
4062 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
4063 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
4064 }
Cary Clark8032b982017-07-28 11:04:54 -04004065}
4066##
4067
4068#ToDo incomplete ##
4069
4070##
4071
4072# ------------------------------------------------------------------------------
4073
4074#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
4075 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4076
Cary Clarkbad5ad72017-08-03 17:14:08 -04004077Draw Image image, scaled and translated to fill Rect dst, using Clip, Matrix,
4078and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004079
Cary Clarkbad5ad72017-08-03 17:14:08 -04004080If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4081Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4082If paint contains Mask_Filter, generate mask from image bounds.
4083
4084If generated mask extends beyond image bounds, replicate image edge colors, just
4085as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4086replicates the image's edge color when it samples outside of its bounds.
4087
4088constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004089sample within image; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004090improve performance.
4091
4092#Param image Image containing pixels, dimensions, and format ##
4093#Param dst destination Rect of image to draw to ##
4094#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4095 and so on; or nullptr
4096##
Cary Clarkce101242017-09-01 15:51:02 -04004097#Param constraint filter strictly within image or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004098
4099#Example
4100#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04004101void draw(SkCanvas* canvas) {
4102 // sk_sp<SkImage> image;
4103 for (auto i : { 20, 40, 80, 160 } ) {
4104 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
4105 }
Cary Clark8032b982017-07-28 11:04:54 -04004106}
4107##
4108
4109#ToDo incomplete ##
4110
4111##
4112
4113# ------------------------------------------------------------------------------
4114
4115#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
4116 const SkPaint* paint,
4117 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4118
4119Draw Rect src of Image image, scaled and translated to fill Rect dst.
4120Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004121
Cary Clarkbad5ad72017-08-03 17:14:08 -04004122If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4123Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4124If paint contains Mask_Filter, generate mask from image bounds.
4125
4126If generated mask extends beyond image bounds, replicate image edge colors, just
4127as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4128replicates the image's edge color when it samples outside of its bounds.
4129
4130constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4131sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4132improve performance.
4133
4134#Param image Image containing pixels, dimensions, and format ##
4135#Param src source Rect of image to draw from ##
4136#Param dst destination Rect of image to draw to ##
4137#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4138 and so on; or nullptr
4139##
4140#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004141
4142#Example
4143#Height 64
4144#Description
4145 Canvas scales and translates; transformation from src to dst also scales.
4146 The two matrices are concatenated to create the final transformation.
4147##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004148void draw(SkCanvas* canvas) {
4149 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
4150 { SK_ColorWHITE, SK_ColorBLACK } };
4151 SkBitmap bitmap;
4152 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4153 (void*) pixels, sizeof(pixels[0]));
4154 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4155 SkPaint paint;
4156 canvas->scale(4, 4);
4157 for (auto alpha : { 50, 100, 150, 255 } ) {
4158 paint.setAlpha(alpha);
4159 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
4160 canvas->translate(8, 0);
4161 }
4162}
Cary Clark8032b982017-07-28 11:04:54 -04004163##
4164
4165#ToDo incomplete ##
4166
4167##
4168
4169# ------------------------------------------------------------------------------
4170
4171#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
4172 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4173
4174Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004175isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004176Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004177
Cary Clarkbad5ad72017-08-03 17:14:08 -04004178If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4179Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4180If paint contains Mask_Filter, generate mask from image bounds.
4181
4182If generated mask extends beyond image bounds, replicate image edge colors, just
4183as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4184replicates the image's edge color when it samples outside of its bounds.
4185
4186constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004187sample within image; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004188improve performance.
4189
4190#Param image Image containing pixels, dimensions, and format ##
4191#Param isrc source IRect of image to draw from ##
4192#Param dst destination Rect of image to draw to ##
4193#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4194 and so on; or nullptr
4195##
Cary Clarkce101242017-09-01 15:51:02 -04004196#Param constraint filter strictly within image or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004197
4198#Example
4199#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004200void draw(SkCanvas* canvas) {
4201 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
4202 { 0xAAAAAAAA, 0xFFFFFFFF} };
4203 SkBitmap bitmap;
4204 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4205 (void*) pixels, sizeof(pixels[0]));
4206 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4207 SkPaint paint;
4208 canvas->scale(4, 4);
4209 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4210 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4211 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
4212 canvas->translate(8, 0);
4213 }
Cary Clark8032b982017-07-28 11:04:54 -04004214}
4215##
4216
4217#ToDo incomplete ##
4218##
4219
4220# ------------------------------------------------------------------------------
4221
4222#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
4223 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4224
4225Draw Image image, scaled and translated to fill Rect dst,
4226using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004227
Cary Clarkbad5ad72017-08-03 17:14:08 -04004228If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4229Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4230If paint contains Mask_Filter, generate mask from image bounds.
4231
4232If generated mask extends beyond image bounds, replicate image edge colors, just
4233as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4234replicates the image's edge color when it samples outside of its bounds.
4235
4236constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004237sample within image; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004238improve performance.
4239
4240#Param image Image containing pixels, dimensions, and format ##
4241#Param dst destination Rect of image to draw to ##
4242#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4243 and so on; or nullptr
4244##
Cary Clarkce101242017-09-01 15:51:02 -04004245#Param constraint filter strictly within image or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004246
4247#Example
4248#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004249void draw(SkCanvas* canvas) {
4250 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4251 { 0xAAAA0000, 0xFFFF0000} };
4252 SkBitmap bitmap;
4253 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4254 (void*) pixels, sizeof(pixels[0]));
4255 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4256 SkPaint paint;
4257 canvas->scale(4, 4);
4258 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4259 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4260 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
4261 canvas->translate(8, 0);
4262 }
Cary Clark8032b982017-07-28 11:04:54 -04004263}
4264##
4265
4266#ToDo incomplete ##
4267
4268##
4269
4270# ------------------------------------------------------------------------------
4271
4272#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
4273 const SkPaint* paint = nullptr)
4274
Cary Clarkd0530ba2017-09-14 11:25:39 -04004275Draw Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004276IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04004277the center. Corners are unmodified or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04004278are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004279
Cary Clarkbad5ad72017-08-03 17:14:08 -04004280Additionally transform draw using Clip, Matrix, and optional Paint paint.
4281
4282If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4283Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4284If paint contains Mask_Filter, generate mask from image bounds.
4285
4286If generated mask extends beyond image bounds, replicate image edge colors, just
4287as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4288replicates the image's edge color when it samples outside of its bounds.
4289
4290#Param image Image containing pixels, dimensions, and format ##
4291#Param center IRect edge of image corners and sides ##
4292#Param dst destination Rect of image to draw to ##
4293#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4294 and so on; or nullptr
4295##
Cary Clark8032b982017-07-28 11:04:54 -04004296
4297#Example
4298#Height 128
4299#Description
4300 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004301 The second image equals the size of center; only corners are drawn without scaling.
4302 The remaining images are larger than center. All corners draw without scaling.
4303 The sides and center are scaled if needed to take up the remaining space.
Cary Clark8032b982017-07-28 11:04:54 -04004304##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004305void draw(SkCanvas* canvas) {
4306 SkIRect center = { 20, 10, 50, 40 };
4307 SkBitmap bitmap;
4308 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4309 SkCanvas bitCanvas(bitmap);
4310 SkPaint paint;
4311 SkColor gray = 0xFF000000;
4312 int left = 0;
4313 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4314 int top = 0;
4315 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4316 paint.setColor(gray);
4317 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4318 gray += 0x001f1f1f;
4319 top = bottom;
4320 }
4321 left = right;
4322 }
4323 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4324 SkImage* imagePtr = image.get();
4325 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4326 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4327 canvas->translate(dest + 4, 0);
4328 }
Cary Clark8032b982017-07-28 11:04:54 -04004329}
4330##
4331
4332#ToDo incomplete ##
4333
4334##
4335
4336# ------------------------------------------------------------------------------
4337
4338#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
4339 const SkPaint* paint = nullptr)
4340
Cary Clarkd0530ba2017-09-14 11:25:39 -04004341Draw Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004342IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04004343the center. Corners are not scaled, or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04004344are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004345
Cary Clarkbad5ad72017-08-03 17:14:08 -04004346Additionally transform draw using Clip, Matrix, and optional Paint paint.
4347
4348If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4349Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4350If paint contains Mask_Filter, generate mask from image bounds.
4351
4352If generated mask extends beyond image bounds, replicate image edge colors, just
4353as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4354replicates the image's edge color when it samples outside of its bounds.
4355
4356#Param image Image containing pixels, dimensions, and format ##
4357#Param center IRect edge of image corners and sides ##
4358#Param dst destination Rect of image to draw to ##
4359#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4360 and so on; or nullptr
4361##
Cary Clark8032b982017-07-28 11:04:54 -04004362
4363#Example
4364#Height 128
4365#Description
4366 The two leftmost images has four corners and sides to the left and right of center.
4367 The leftmost image scales the width of corners proportionately to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004368 The third and fourth image corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04004369 fill the remaining space.
4370 The rightmost image has four corners scaled vertically to fit, and uses sides above
4371 and below center to fill the remaining space.
4372##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004373void draw(SkCanvas* canvas) {
4374 SkIRect center = { 20, 10, 50, 40 };
4375 SkBitmap bitmap;
4376 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4377 SkCanvas bitCanvas(bitmap);
4378 SkPaint paint;
4379 SkColor gray = 0xFF000000;
4380 int left = 0;
4381 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4382 int top = 0;
4383 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4384 paint.setColor(gray);
4385 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4386 gray += 0x001f1f1f;
4387 top = bottom;
4388 }
4389 left = right;
4390 }
4391 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4392 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4393 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4394 canvas->translate(dest + 4, 0);
4395 }
Cary Clark8032b982017-07-28 11:04:54 -04004396}
4397##
4398
4399#ToDo incomplete ##
4400
4401##
4402
4403# ------------------------------------------------------------------------------
4404
4405#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04004406 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04004407
4408Draw Bitmap bitmap, with its top-left corner at (left, top),
4409using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004410
Cary Clarkbad5ad72017-08-03 17:14:08 -04004411If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4412Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4413If paint contains Mask_Filter, generate mask from bitmap bounds.
4414
4415If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4416just as Shader made from SkShader::MakeBitmapShader with
4417SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4418outside of its bounds.
4419
4420#Param bitmap Bitmap containing pixels, dimensions, and format ##
4421#Param left left side of bitmap ##
4422#Param top top side of bitmap ##
4423#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4424 and so on; or nullptr
4425##
Cary Clark8032b982017-07-28 11:04:54 -04004426
4427#Example
4428#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004429void draw(SkCanvas* canvas) {
4430 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4431 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4432 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4433 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4434 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4435 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4436 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
4437 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
4438 SkBitmap bitmap;
4439 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4440 (void*) pixels, sizeof(pixels[0]));
4441 SkPaint paint;
4442 canvas->scale(4, 4);
4443 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4444 paint.setColor(color);
4445 canvas->drawBitmap(bitmap, 0, 0, &paint);
4446 canvas->translate(12, 0);
4447 }
Cary Clark8032b982017-07-28 11:04:54 -04004448}
4449##
4450
4451#ToDo incomplete ##
4452
4453##
4454
4455# ------------------------------------------------------------------------------
4456
4457#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
4458 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4459
4460Draw Rect src of Bitmap bitmap, scaled and translated to fill Rect dst.
4461Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004462
Cary Clarkbad5ad72017-08-03 17:14:08 -04004463If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4464Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4465If paint contains Mask_Filter, generate mask from bitmap bounds.
4466
4467If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4468just as Shader made from SkShader::MakeBitmapShader with
4469SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4470outside of its bounds.
4471
4472constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4473sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4474improve performance.
4475
4476#Param bitmap Bitmap containing pixels, dimensions, and format ##
4477#Param src source Rect of image to draw from ##
4478#Param dst destination Rect of image to draw to ##
4479#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4480 and so on; or nullptr
4481##
4482#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004483
4484#Example
4485#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004486void draw(SkCanvas* canvas) {
4487 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4488 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4489 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4490 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4491 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4492 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4493 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4494 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
4495 SkBitmap bitmap;
4496 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4497 (void*) pixels, sizeof(pixels[0]));
4498 SkPaint paint;
4499 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 6));
4500 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4501 paint.setColor(color);
4502 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4503 canvas->translate(48, 0);
4504 }
Cary Clark8032b982017-07-28 11:04:54 -04004505}
4506##
4507
4508#ToDo incomplete ##
4509
4510##
4511
4512# ------------------------------------------------------------------------------
4513
4514#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
4515 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4516
4517Draw IRect isrc of Bitmap bitmap, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004518isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004519Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004520
Cary Clarkbad5ad72017-08-03 17:14:08 -04004521If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4522Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4523If paint contains Mask_Filter, generate mask from bitmap bounds.
4524
4525If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4526just as Shader made from SkShader::MakeBitmapShader with
4527SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4528outside of its bounds.
4529
4530constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004531sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004532improve performance.
4533
4534#Param bitmap Bitmap containing pixels, dimensions, and format ##
4535#Param isrc source IRect of image to draw from ##
4536#Param dst destination Rect of image to draw to ##
4537#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4538 and so on; or nullptr
4539##
Cary Clarkce101242017-09-01 15:51:02 -04004540#Param constraint sample strictly within isrc, or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004541
4542#Example
4543#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004544void draw(SkCanvas* canvas) {
4545 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4546 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4547 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4548 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4549 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
4550 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
4551 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4552 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
4553 SkBitmap bitmap;
4554 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4555 (void*) pixels, sizeof(pixels[0]));
4556 SkPaint paint;
4557 paint.setFilterQuality(kHigh_SkFilterQuality);
4558 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
4559 paint.setColor(color);
4560 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4561 canvas->translate(48.25f, 0);
4562 }
Cary Clark8032b982017-07-28 11:04:54 -04004563}
4564##
4565
4566#ToDo incomplete ##
4567
4568##
4569
4570# ------------------------------------------------------------------------------
4571
4572#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
4573 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4574
4575Draw Bitmap bitmap, scaled and translated to fill Rect dst.
Cary Clarkce101242017-09-01 15:51:02 -04004576bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004577Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004578
Cary Clarkbad5ad72017-08-03 17:14:08 -04004579If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4580Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4581If paint contains Mask_Filter, generate mask from bitmap bounds.
4582
4583If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4584just as Shader made from SkShader::MakeBitmapShader with
4585SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4586outside of its bounds.
4587
4588constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004589sample within bitmap; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004590improve performance.
4591
4592#Param bitmap Bitmap containing pixels, dimensions, and format ##
4593#Param dst destination Rect of image to draw to ##
4594#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4595 and so on; or nullptr
4596##
Cary Clarkce101242017-09-01 15:51:02 -04004597#Param constraint filter strictly within bitmap or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004598
4599#Example
4600#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004601void draw(SkCanvas* canvas) {
4602 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4603 { 0xAAAA0000, 0xFFFF0000} };
4604 SkBitmap bitmap;
4605 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4606 (void*) pixels, sizeof(pixels[0]));
4607 SkPaint paint;
4608 canvas->scale(4, 4);
4609 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4610 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4611 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
4612 canvas->translate(8, 0);
4613 }
Cary Clark8032b982017-07-28 11:04:54 -04004614}
4615##
4616
4617#ToDo incomplete ##
4618
4619##
4620
4621# ------------------------------------------------------------------------------
4622
4623#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04004624 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04004625
Cary Clarkd0530ba2017-09-14 11:25:39 -04004626Draw Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004627IRect center divides the bitmap into nine sections: four sides, four corners,
Cary Clarkce101242017-09-01 15:51:02 -04004628and the center. Corners are not scaled, or scaled down proportionately if their
Cary Clarkbad5ad72017-08-03 17:14:08 -04004629sides are larger than dst; center and four sides are scaled to fit remaining
4630space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004631
Cary Clarkbad5ad72017-08-03 17:14:08 -04004632Additionally transform draw using Clip, Matrix, and optional Paint paint.
4633
4634If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4635Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4636If paint contains Mask_Filter, generate mask from bitmap bounds.
4637
4638If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4639just as Shader made from SkShader::MakeBitmapShader with
4640SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4641outside of its bounds.
4642
4643#Param bitmap Bitmap containing pixels, dimensions, and format ##
4644#Param center IRect edge of image corners and sides ##
4645#Param dst destination Rect of image to draw to ##
4646#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4647 and so on; or nullptr
4648##
Cary Clark8032b982017-07-28 11:04:54 -04004649
4650#Example
4651#Height 128
4652#Description
4653 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4654 The leftmost bitmap draw scales the width of corners proportionately to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004655 The third and fourth draw corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04004656 fill the remaining space.
4657 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4658 and below center to fill the remaining space.
4659##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004660void draw(SkCanvas* canvas) {
4661 SkIRect center = { 20, 10, 50, 40 };
4662 SkBitmap bitmap;
4663 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4664 SkCanvas bitCanvas(bitmap);
4665 SkPaint paint;
4666 SkColor gray = 0xFF000000;
4667 int left = 0;
4668 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4669 int top = 0;
4670 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4671 paint.setColor(gray);
4672 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4673 gray += 0x001f1f1f;
4674 top = bottom;
4675 }
4676 left = right;
4677 }
4678 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4679 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4680 canvas->translate(dest + 4, 0);
4681 }
Cary Clark8032b982017-07-28 11:04:54 -04004682}
4683##
4684
4685#ToDo incomplete ##
4686
4687##
4688
4689# ------------------------------------------------------------------------------
4690#Struct Lattice
4691
4692 Lattice divides Bitmap or Image into a rectangular grid.
4693 Grid entries on even columns and even rows are fixed; these entries are
4694 always drawn at their original size if the destination is large enough.
4695 If the destination side is too small to hold the fixed entries, all fixed
4696 entries are proportionately scaled down to fit.
4697 The grid entries not on even columns and rows are scaled to fit the
4698 remaining space, if any.
4699
4700#Code
4701 struct Lattice {
4702 enum Flags {...
4703
4704 const int* fXDivs;
4705 const int* fYDivs;
4706 const Flags* fFlags;
4707 int fXCount;
4708 int fYCount;
4709 const SkIRect* fBounds;
4710 };
4711##
4712
4713 #Enum Flags
4714 #Code
4715 enum Flags : uint8_t {
4716 kTransparent_Flags = 1 << 0,
4717 };
4718 ##
4719
4720 Optional setting per rectangular grid entry to make it transparent.
4721
4722 #Const kTransparent_Flags 1
4723 Set to skip lattice rectangle by making it transparent.
4724 ##
4725 ##
4726
4727 #Member const int* fXDivs
4728 Array of x-coordinates that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004729 Array entries must be unique, increasing, greater than or equal to
4730 fBounds left edge, and less than fBounds right edge.
4731 Set the first element to fBounds left to collapse the left column of
4732 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04004733 ##
4734
4735 #Member const int* fYDivs
4736 Array of y-coordinates that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004737 Array entries must be unique, increasing, greater than or equal to
4738 fBounds top edge, and less than fBounds bottom edge.
4739 Set the first element to fBounds top to collapse the top row of fixed
4740 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04004741 ##
4742
4743 #Member const Flags* fFlags
4744 Optional array of Flags, one per rectangular grid entry:
Cary Clarkbad5ad72017-08-03 17:14:08 -04004745 array length must be
4746 #Formula
4747 (fXCount + 1) * (fYCount + 1)
4748 ##
4749 .
Cary Clark6fc50412017-09-21 12:31:06 -04004750
Cary Clark8032b982017-07-28 11:04:54 -04004751 Array entries correspond to the rectangular grid entries, ascending
4752 left to right and then top to bottom.
4753 ##
4754
4755 #Member int fXCount
Cary Clarkbad5ad72017-08-03 17:14:08 -04004756 Number of entries in fXDivs array; one less than the number of
4757 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04004758 ##
4759
4760 #Member int fYCount
Cary Clarkbad5ad72017-08-03 17:14:08 -04004761 Number of entries in fYDivs array; one less than the number of vertical
4762 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04004763 ##
4764
4765 #Member const SkIRect* fBounds
4766 Optional subset IRect source to draw from.
4767 If nullptr, source bounds is dimensions of Bitmap or Image.
4768 ##
4769
4770#Struct Lattice ##
4771
4772#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
4773 const SkPaint* paint = nullptr)
4774
Cary Clarkd0530ba2017-09-14 11:25:39 -04004775Draw Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04004776
4777Lattice lattice divides bitmap into a rectangular grid.
4778Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04004779of drawBitmapNine, fixed lattice elements never scale larger than their initial
4780size and shrink proportionately when all fixed elements exceed the bitmap's
4781dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004782
4783Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004784
Cary Clarkbad5ad72017-08-03 17:14:08 -04004785If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4786Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4787If paint contains Mask_Filter, generate mask from bitmap bounds.
4788
4789If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4790just as Shader made from SkShader::MakeBitmapShader with
4791SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4792outside of its bounds.
4793
4794#Param bitmap Bitmap containing pixels, dimensions, and format ##
4795#Param lattice division of bitmap into fixed and variable rectangles ##
4796#Param dst destination Rect of image to draw to ##
4797#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4798 and so on; or nullptr
4799##
Cary Clark8032b982017-07-28 11:04:54 -04004800
4801#Example
4802#Height 128
4803#Description
4804 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4805 The leftmost bitmap draw scales the width of corners proportionately to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004806 The third and fourth draw corners are not scaled; the sides are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04004807 fill the remaining space; the center is transparent.
4808 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4809 and below center to fill the remaining space.
4810##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004811void draw(SkCanvas* canvas) {
4812 SkIRect center = { 20, 10, 50, 40 };
4813 SkBitmap bitmap;
4814 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4815 SkCanvas bitCanvas(bitmap);
4816 SkPaint paint;
4817 SkColor gray = 0xFF000000;
4818 int left = 0;
4819 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4820 int top = 0;
4821 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4822 paint.setColor(gray);
4823 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4824 gray += 0x001f1f1f;
4825 top = bottom;
4826 }
4827 left = right;
4828 }
4829 const int xDivs[] = { center.fLeft, center.fRight };
4830 const int yDivs[] = { center.fTop, center.fBottom };
4831 SkCanvas::Lattice::Flags flags[3][3];
4832 memset(flags, 0, sizeof(flags));
4833 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4834 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4835 SK_ARRAY_COUNT(yDivs), nullptr };
4836 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4837 canvas->drawBitmapLattice(bitmap, lattice , SkRect::MakeWH(dest, 110 - dest), nullptr);
4838 canvas->translate(dest + 4, 0);
4839 }
Cary Clark8032b982017-07-28 11:04:54 -04004840}
4841##
4842
4843#ToDo incomplete ##
4844
4845##
4846
4847# ------------------------------------------------------------------------------
4848
4849#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
4850 const SkPaint* paint = nullptr)
4851
Cary Clarkd0530ba2017-09-14 11:25:39 -04004852Draw Image image stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04004853
4854Lattice lattice divides image into a rectangular grid.
4855Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04004856of drawBitmapNine, fixed lattice elements never scale larger than their initial
4857size and shrink proportionately when all fixed elements exceed the bitmap's
4858dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004859
4860Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004861
Cary Clarkbad5ad72017-08-03 17:14:08 -04004862If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4863Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4864If paint contains Mask_Filter, generate mask from bitmap bounds.
4865
4866If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4867just as Shader made from SkShader::MakeBitmapShader with
4868SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4869outside of its bounds.
4870
4871#Param image Image containing pixels, dimensions, and format ##
4872#Param lattice division of bitmap into fixed and variable rectangles ##
4873#Param dst destination Rect of image to draw to ##
4874#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4875 and so on; or nullptr
4876##
Cary Clark8032b982017-07-28 11:04:54 -04004877
4878#Example
4879#Height 128
4880#Description
4881 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004882 The second image equals the size of center; only corners are drawn without scaling.
4883 The remaining images are larger than center. All corners draw without scaling. The sides
Cary Clark8032b982017-07-28 11:04:54 -04004884 are scaled if needed to take up the remaining space; the center is transparent.
4885##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004886void draw(SkCanvas* canvas) {
4887 SkIRect center = { 20, 10, 50, 40 };
4888 SkBitmap bitmap;
4889 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4890 SkCanvas bitCanvas(bitmap);
4891 SkPaint paint;
4892 SkColor gray = 0xFF000000;
4893 int left = 0;
4894 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4895 int top = 0;
4896 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4897 paint.setColor(gray);
4898 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4899 gray += 0x001f1f1f;
4900 top = bottom;
4901 }
4902 left = right;
4903 }
4904 const int xDivs[] = { center.fLeft, center.fRight };
4905 const int yDivs[] = { center.fTop, center.fBottom };
4906 SkCanvas::Lattice::Flags flags[3][3];
4907 memset(flags, 0, sizeof(flags));
4908 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4909 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4910 SK_ARRAY_COUNT(yDivs), nullptr };
4911 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4912 SkImage* imagePtr = image.get();
4913 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4914 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4915 canvas->translate(dest + 4, 0);
4916 }
Cary Clark8032b982017-07-28 11:04:54 -04004917}
4918##
4919
4920#ToDo incomplete ##
4921
4922##
4923
4924#Topic Draw_Image ##
4925
4926# ------------------------------------------------------------------------------
4927
4928#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
4929 const SkPaint& paint)
4930
4931Draw text, with origin at (x, y), using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004932
Cary Clarkbad5ad72017-08-03 17:14:08 -04004933text's meaning depends on Paint_Text_Encoding; by default, text encoding is
4934UTF-8.
Cary Clark8032b982017-07-28 11:04:54 -04004935
Cary Clarkbad5ad72017-08-03 17:14:08 -04004936x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
4937text draws left to right, positioning the first glyph's left side bearing at x
4938and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4939
4940All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
4941Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04004942filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004943
Cary Clarkce101242017-09-01 15:51:02 -04004944#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004945#Param byteLength byte length of text array ##
4946#Param x start of text on x-axis ##
4947#Param y start of text on y-axis ##
4948#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004949
4950#Example
4951#Height 200
4952#Description
4953 The same text is drawn varying Paint_Text_Size and varying
4954 Matrix.
4955##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004956void draw(SkCanvas* canvas) {
4957 SkPaint paint;
4958 paint.setAntiAlias(true);
4959 float textSizes[] = { 12, 18, 24, 36 };
4960 for (auto size: textSizes ) {
4961 paint.setTextSize(size);
4962 canvas->drawText("Aa", 2, 10, 20, paint);
4963 canvas->translate(0, size * 2);
4964 }
4965 paint.reset();
4966 paint.setAntiAlias(true);
4967 float yPos = 20;
4968 for (auto size: textSizes ) {
4969 float scale = size / 12.f;
4970 canvas->resetMatrix();
4971 canvas->translate(100, 0);
4972 canvas->scale(scale, scale);
4973 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
4974 yPos += size * 2;
4975 }
4976}
Cary Clark8032b982017-07-28 11:04:54 -04004977##
4978
4979#ToDo incomplete ##
4980
4981##
4982
4983#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
4984
Cary Clarkbad5ad72017-08-03 17:14:08 -04004985Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
4986Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004987
Cary Clarkbad5ad72017-08-03 17:14:08 -04004988string's meaning depends on Paint_Text_Encoding; by default, string encoding is
4989UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
4990results, since zero bytes may be embedded in the string.
Cary Clark8032b982017-07-28 11:04:54 -04004991
Cary Clarkbad5ad72017-08-03 17:14:08 -04004992x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
4993string draws left to right, positioning the first glyph's left side bearing at x
4994and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4995
4996All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
4997Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04004998filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004999
Cary Clarkce101242017-09-01 15:51:02 -04005000#Param string character code points or Glyphs drawn,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005001 ending with a char value of zero
5002##
5003#Param x start of string on x-axis ##
5004#Param y start of string on y-axis ##
5005#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005006
5007#Example
5008 SkPaint paint;
5009 canvas->drawString("a small hello", 20, 20, paint);
5010##
5011
5012#SeeAlso drawText
5013
5014##
5015
5016#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
5017
Cary Clarkbad5ad72017-08-03 17:14:08 -04005018Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
5019Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005020
Cary Clarkbad5ad72017-08-03 17:14:08 -04005021string's meaning depends on Paint_Text_Encoding; by default, string encoding is
5022UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
5023results, since zero bytes may be embedded in the string.
Cary Clark8032b982017-07-28 11:04:54 -04005024
Cary Clarkbad5ad72017-08-03 17:14:08 -04005025x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
5026string draws left to right, positioning the first glyph's left side bearing at x
5027and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
5028
5029All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5030Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005031filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005032
Cary Clarkce101242017-09-01 15:51:02 -04005033#Param string character code points or Glyphs drawn,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005034 ending with a char value of zero
5035##
5036#Param x start of string on x-axis ##
5037#Param y start of string on y-axis ##
5038#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005039
5040#Example
5041 SkPaint paint;
5042 SkString string("a small hello");
5043 canvas->drawString(string, 20, 20, paint);
5044##
5045
5046#SeeAlso drawText
5047
5048##
5049
5050# ------------------------------------------------------------------------------
5051
5052#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
5053 const SkPaint& paint)
5054
Cary Clarkbad5ad72017-08-03 17:14:08 -04005055Draw each glyph in text with the origin in pos array, using Clip, Matrix, and
Cary Clarkce101242017-09-01 15:51:02 -04005056Paint paint. The number of entries in pos array must match the number of Glyphs
Cary Clarkbad5ad72017-08-03 17:14:08 -04005057described by byteLength of text.
Cary Clark8032b982017-07-28 11:04:54 -04005058
Cary Clarkbad5ad72017-08-03 17:14:08 -04005059text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5060UTF-8. pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text;
5061by default each glyph's left side bearing is positioned at x and its
5062baseline is positioned at y. Text size is affected by Matrix and
5063Paint_Text_Size.
Cary Clark8032b982017-07-28 11:04:54 -04005064
Cary Clarkbad5ad72017-08-03 17:14:08 -04005065All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5066Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005067filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005068
5069Layout engines such as Harfbuzz typically position each glyph
Cary Clark8032b982017-07-28 11:04:54 -04005070rather than using the font's advance widths.
5071
Cary Clarkce101242017-09-01 15:51:02 -04005072#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005073#Param byteLength byte length of text array ##
5074#Param pos array of glyph origins ##
5075#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005076
5077#Example
5078#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04005079void draw(SkCanvas* canvas) {
5080 const char hello[] = "HeLLo!";
5081 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
5082 {172, 100} };
5083 SkPaint paint;
5084 paint.setTextSize(60);
5085 canvas->drawPosText(hello, strlen(hello), pos, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005086}
5087##
5088
5089#ToDo incomplete ##
5090
5091##
5092
5093# ------------------------------------------------------------------------------
5094
5095#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
5096 const SkPaint& paint)
5097
Cary Clarkbad5ad72017-08-03 17:14:08 -04005098Draw each glyph in text with its (x, y) origin composed from xpos array and
5099constY, using Clip, Matrix, and Paint paint. The number of entries in xpos array
Cary Clarkce101242017-09-01 15:51:02 -04005100must match the number of Glyphs described by byteLength of text.
Cary Clark8032b982017-07-28 11:04:54 -04005101
Cary Clarkbad5ad72017-08-03 17:14:08 -04005102text's meaning depends on Paint_Text_Encoding; by default, text encoding is
Cary Clarkce101242017-09-01 15:51:02 -04005103UTF-8. xpos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text;
Cary Clarkbad5ad72017-08-03 17:14:08 -04005104by default each glyph's left side bearing is positioned at an xpos element and
5105its baseline is positioned at constY. Text size is affected by Matrix and
5106Paint_Text_Size.
Cary Clark8032b982017-07-28 11:04:54 -04005107
Cary Clarkbad5ad72017-08-03 17:14:08 -04005108All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5109Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005110filled 12 point black Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005111
Cary Clarkbad5ad72017-08-03 17:14:08 -04005112Layout engines such as Harfbuzz typically position each glyph
Cary Clarkce101242017-09-01 15:51:02 -04005113rather than using the font's advance widths if all Glyphs share the same
Cary Clarkbad5ad72017-08-03 17:14:08 -04005114baseline.
5115
Cary Clarkce101242017-09-01 15:51:02 -04005116#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005117#Param byteLength byte length of text array ##
5118#Param xpos array of x positions, used to position each glyph ##
5119#Param constY shared y coordinate for all of x positions ##
5120#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005121
5122#Example
5123#Height 40
Cary Clarkbad5ad72017-08-03 17:14:08 -04005124 void draw(SkCanvas* canvas) {
5125 SkScalar xpos[] = { 20, 40, 80, 160 };
5126 SkPaint paint;
5127 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
5128 }
Cary Clark8032b982017-07-28 11:04:54 -04005129##
5130
5131#ToDo incomplete ##
5132
5133##
5134
5135# ------------------------------------------------------------------------------
5136
5137#Method void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
5138 SkScalar vOffset, const SkPaint& paint)
5139
5140Draw text on Path path, using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005141
Cary Clarkbad5ad72017-08-03 17:14:08 -04005142Origin of text is at distance hOffset along the path, offset by a perpendicular
5143vector of length vOffset. If the path section corresponding the glyph advance is
5144curved, the glyph is drawn curved to match; control points in the glyph are
5145mapped to projected points parallel to the path. If the text's advance is larger
5146than the path length, the excess text is clipped.
5147
5148text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5149UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by
5150default text positions the first glyph's left side bearing at origin x and its
Cary Clark8032b982017-07-28 11:04:54 -04005151baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
5152
Cary Clarkbad5ad72017-08-03 17:14:08 -04005153All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5154Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005155filled 12 point black Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005156
Cary Clarkce101242017-09-01 15:51:02 -04005157#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005158#Param byteLength byte length of text array ##
5159#Param path Path providing text baseline ##
5160#Param hOffset distance along path to offset origin ##
5161#Param vOffset offset of text above (if negative) or below (if positive) the path ##
5162#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005163
5164#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005165 void draw(SkCanvas* canvas) {
5166 const char aero[] = "correo a" "\xC3" "\xA9" "reo";
5167 const size_t len = sizeof(aero) - 1;
5168 SkPath path;
5169 path.addOval({43-26, 43-26, 43+26, 43+26}, SkPath::kCW_Direction, 3);
5170 SkPaint paint;
5171 paint.setTextSize(24);
5172 for (auto offset : { 0, 10, 20 } ) {
5173 canvas->drawTextOnPathHV(aero, len, path, 0, -offset, paint);
5174 canvas->translate(70 + offset, 70 + offset);
5175 }
5176 }
Cary Clark8032b982017-07-28 11:04:54 -04005177##
5178
5179#ToDo incomplete ##
5180
5181##
5182
5183# ------------------------------------------------------------------------------
5184
5185#Method void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
5186 const SkMatrix* matrix, const SkPaint& paint)
5187
5188Draw text on Path path, using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005189
Cary Clarkbad5ad72017-08-03 17:14:08 -04005190Origin of text is at beginning of path offset by matrix, if provided, before it
5191is mapped to path. If the path section corresponding the glyph advance is
5192curved, the glyph is drawn curved to match; control points in the glyph are
5193mapped to projected points parallel to the path. If the text's advance is larger
5194than the path length, the excess text is clipped.
5195
5196text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5197UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by
5198default text positions the first glyph's left side bearing at origin x and its
Cary Clark8032b982017-07-28 11:04:54 -04005199baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
5200
Cary Clarkbad5ad72017-08-03 17:14:08 -04005201All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5202Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005203filled 12 point black Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005204
Cary Clarkce101242017-09-01 15:51:02 -04005205#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005206#Param byteLength byte length of text array ##
5207#Param path Path providing text baseline ##
Cary Clarkce101242017-09-01 15:51:02 -04005208#Param matrix transform of Glyphs before mapping to path; may be nullptr
Cary Clarka523d2d2017-08-30 08:58:10 -04005209 to use identity Matrix
Cary Clarkbad5ad72017-08-03 17:14:08 -04005210##
5211#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005212
5213#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005214 void draw(SkCanvas* canvas) {
5215 const char roller[] = "rollercoaster";
5216 const size_t len = sizeof(roller) - 1;
5217 SkPath path;
5218 path.cubicTo(40, -80, 120, 80, 160, -40);
5219 SkPaint paint;
5220 paint.setTextSize(32);
5221 paint.setStyle(SkPaint::kStroke_Style);
5222 SkMatrix matrix;
5223 matrix.setIdentity();
5224 for (int i = 0; i < 3; ++i) {
5225 canvas->translate(25, 60);
5226 canvas->drawPath(path, paint);
5227 canvas->drawTextOnPath(roller, len, path, &matrix, paint);
5228 matrix.preTranslate(0, 10);
5229 }
5230 }
Cary Clark8032b982017-07-28 11:04:54 -04005231##
5232
5233#ToDo incomplete ##
5234
5235##
5236
5237# ------------------------------------------------------------------------------
5238
5239#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
5240 const SkRect* cullRect, const SkPaint& paint)
5241
5242Draw text, transforming each glyph by the corresponding SkRSXform,
5243using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005244
Cary Clark8032b982017-07-28 11:04:54 -04005245RSXform array specifies a separate square scale, rotation, and translation for
5246each glyph.
Cary Clark8032b982017-07-28 11:04:54 -04005247
Cary Clarkbad5ad72017-08-03 17:14:08 -04005248Optional Rect cullRect is a conservative bounds of text, taking into account
Cary Clarkce101242017-09-01 15:51:02 -04005249RSXform and paint. If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005250
Cary Clarkbad5ad72017-08-03 17:14:08 -04005251All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5252Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005253filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005254
Cary Clarkce101242017-09-01 15:51:02 -04005255#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005256#Param byteLength byte length of text array ##
5257#Param xform RSXform rotates, scales, and translates each glyph individually ##
5258#Param cullRect Rect bounds of text for efficient clipping; or nullptr ##
5259#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005260
5261#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005262void draw(SkCanvas* canvas) {
5263 const int iterations = 26;
5264 SkRSXform transforms[iterations];
5265 char alphabet[iterations];
5266 SkScalar angle = 0;
5267 SkScalar scale = 1;
5268 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
5269 const SkScalar s = SkScalarSin(angle) * scale;
5270 const SkScalar c = SkScalarCos(angle) * scale;
5271 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
5272 angle += .45;
5273 scale += .2;
5274 alphabet[i] = 'A' + i;
5275 }
5276 SkPaint paint;
5277 paint.setTextAlign(SkPaint::kCenter_Align);
5278 canvas->translate(110, 138);
5279 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005280}
5281##
5282
5283#ToDo incomplete ##
5284
5285##
5286
5287# ------------------------------------------------------------------------------
5288
5289#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
5290
5291Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005292
Cary Clarkce101242017-09-01 15:51:02 -04005293blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clarkbad5ad72017-08-03 17:14:08 -04005294Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X,
5295Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold,
5296Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
5297Subpixel_Text, and Paint_Vertical_Text.
Cary Clark8032b982017-07-28 11:04:54 -04005298
5299Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
5300Image_Filter, and Draw_Looper; apply to blob.
5301
Cary Clarkce101242017-09-01 15:51:02 -04005302#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005303#Param x horizontal offset applied to blob ##
5304#Param y vertical offset applied to blob ##
5305#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005306
5307#Example
5308#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04005309 void draw(SkCanvas* canvas) {
5310 SkTextBlobBuilder textBlobBuilder;
5311 const char bunny[] = "/(^x^)\\";
5312 const int len = sizeof(bunny) - 1;
5313 uint16_t glyphs[len];
5314 SkPaint paint;
5315 paint.textToGlyphs(bunny, len, glyphs);
5316 int runs[] = { 3, 1, 3 };
5317 SkPoint textPos = { 20, 100 };
5318 int glyphIndex = 0;
5319 for (auto runLen : runs) {
5320 paint.setTextSize(1 == runLen ? 20 : 50);
5321 const SkTextBlobBuilder::RunBuffer& run =
5322 textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
5323 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
5324 textPos.fX += paint.measureText(&bunny[glyphIndex], runLen, nullptr);
5325 glyphIndex += runLen;
5326 }
5327 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5328 paint.reset();
5329 canvas->drawTextBlob(blob.get(), 0, 0, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005330 }
5331##
5332
5333#ToDo incomplete ##
5334
5335##
5336
5337# ------------------------------------------------------------------------------
5338
5339#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
5340
5341Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005342
Cary Clarkce101242017-09-01 15:51:02 -04005343blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clarkbad5ad72017-08-03 17:14:08 -04005344Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X,
5345Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold,
5346Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
5347Subpixel_Text, and Paint_Vertical_Text.
Cary Clark8032b982017-07-28 11:04:54 -04005348
5349Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
5350Image_Filter, and Draw_Looper; apply to blob.
5351
Cary Clarkce101242017-09-01 15:51:02 -04005352#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005353#Param x horizontal offset applied to blob ##
5354#Param y vertical offset applied to blob ##
5355#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005356
5357#Example
5358#Height 120
5359#Description
5360Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob.
5361Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
5362##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005363 void draw(SkCanvas* canvas) {
5364 SkTextBlobBuilder textBlobBuilder;
5365 SkPaint paint;
5366 paint.setTextSize(50);
5367 paint.setColor(SK_ColorRED);
5368 const SkTextBlobBuilder::RunBuffer& run =
5369 textBlobBuilder.allocRun(paint, 1, 20, 100);
5370 run.glyphs[0] = 20;
5371 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5372 paint.setTextSize(10);
5373 paint.setColor(SK_ColorBLUE);
5374 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5375 }
Cary Clark8032b982017-07-28 11:04:54 -04005376##
5377
5378#ToDo incomplete ##
5379
5380##
5381
5382# ------------------------------------------------------------------------------
5383
5384#Method void drawPicture(const SkPicture* picture)
5385
5386Draw Picture picture, using Clip and Matrix.
5387Clip and Matrix are unchanged by picture contents, as if
5388save() was called before and restore() was called after drawPicture.
5389
5390Picture records a series of draw commands for later playback.
5391
Cary Clarkbad5ad72017-08-03 17:14:08 -04005392#Param picture recorded drawing commands to play ##
Cary Clark8032b982017-07-28 11:04:54 -04005393
5394#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005395void draw(SkCanvas* canvas) {
5396 SkPictureRecorder recorder;
5397 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5398 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5399 SkPaint paint;
5400 paint.setColor(color);
5401 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5402 recordingCanvas->translate(10, 10);
5403 recordingCanvas->scale(1.2f, 1.4f);
5404 }
5405 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5406 const SkPicture* playbackPtr = playback.get();
5407 canvas->drawPicture(playback);
5408 canvas->scale(2, 2);
5409 canvas->translate(50, 0);
5410 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04005411}
5412##
5413
5414#ToDo incomplete ##
5415
5416##
5417
5418# ------------------------------------------------------------------------------
5419
5420#Method void drawPicture(const sk_sp<SkPicture>& picture)
5421
5422Draw Picture picture, using Clip and Matrix.
5423Clip and Matrix are unchanged by picture contents, as if
5424save() was called before and restore() was called after drawPicture.
5425
5426Picture records a series of draw commands for later playback.
5427
Cary Clarkbad5ad72017-08-03 17:14:08 -04005428#Param picture recorded drawing commands to play ##
Cary Clark8032b982017-07-28 11:04:54 -04005429
5430#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005431void draw(SkCanvas* canvas) {
5432 SkPictureRecorder recorder;
5433 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5434 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5435 SkPaint paint;
5436 paint.setColor(color);
5437 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5438 recordingCanvas->translate(10, 10);
5439 recordingCanvas->scale(1.2f, 1.4f);
5440 }
5441 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5442 canvas->drawPicture(playback);
5443 canvas->scale(2, 2);
5444 canvas->translate(50, 0);
5445 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04005446}
5447##
5448
5449#ToDo incomplete ##
5450
5451##
5452
5453# ------------------------------------------------------------------------------
5454
5455#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
5456
Cary Clarkbad5ad72017-08-03 17:14:08 -04005457Draw Picture picture, using Clip and Matrix; transforming picture with
5458Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
5459Image_Filter, and Blend_Mode, if provided.
Cary Clark8032b982017-07-28 11:04:54 -04005460
5461matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5462paint use is equivalent to: saveLayer, drawPicture, restore().
5463
Cary Clarkbad5ad72017-08-03 17:14:08 -04005464#Param picture recorded drawing commands to play ##
5465#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
5466#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005467
5468#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005469void draw(SkCanvas* canvas) {
5470 SkPaint paint;
5471 SkPictureRecorder recorder;
5472 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5473 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5474 paint.setColor(color);
5475 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5476 recordingCanvas->translate(10, 10);
5477 recordingCanvas->scale(1.2f, 1.4f);
5478 }
5479 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5480 const SkPicture* playbackPtr = playback.get();
5481 SkMatrix matrix;
5482 matrix.reset();
5483 for (auto alpha : { 70, 140, 210 } ) {
5484 paint.setAlpha(alpha);
5485 canvas->drawPicture(playbackPtr, &matrix, &paint);
5486 matrix.preTranslate(70, 70);
5487 }
Cary Clark8032b982017-07-28 11:04:54 -04005488}
5489##
5490
5491#ToDo incomplete ##
5492
5493##
5494
5495# ------------------------------------------------------------------------------
5496
5497#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
5498
Cary Clarkbad5ad72017-08-03 17:14:08 -04005499Draw Picture picture, using Clip and Matrix; transforming picture with
5500Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
5501Image_Filter, and Blend_Mode, if provided.
Cary Clark8032b982017-07-28 11:04:54 -04005502
5503matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5504paint use is equivalent to: saveLayer, drawPicture, restore().
5505
Cary Clarkbad5ad72017-08-03 17:14:08 -04005506#Param picture recorded drawing commands to play ##
5507#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
5508#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005509
5510#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005511void draw(SkCanvas* canvas) {
5512 SkPaint paint;
5513 SkPictureRecorder recorder;
5514 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5515 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5516 paint.setColor(color);
5517 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5518 recordingCanvas->translate(10, 10);
5519 recordingCanvas->scale(1.2f, 1.4f);
5520 }
5521 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5522 SkMatrix matrix;
5523 matrix.reset();
5524 for (auto alpha : { 70, 140, 210 } ) {
5525 paint.setAlpha(alpha);
5526 canvas->drawPicture(playback, &matrix, &paint);
5527 matrix.preTranslate(70, 70);
5528 }
Cary Clark8032b982017-07-28 11:04:54 -04005529}
5530##
5531
5532#ToDo incomplete ##
5533
5534##
5535
5536# ------------------------------------------------------------------------------
5537
5538#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
5539
5540Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005541If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
5542contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
Cary Clark8032b982017-07-28 11:04:54 -04005543
Cary Clarkbad5ad72017-08-03 17:14:08 -04005544#Param vertices triangle mesh to draw ##
5545#Param mode combines Vertices_Colors with Shader, if both are present ##
5546#Param paint specifies the Shader, used as Vertices texture; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005547
5548#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005549void draw(SkCanvas* canvas) {
5550 SkPaint paint;
5551 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5552 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5553 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5554 SK_ARRAY_COUNT(points), points, nullptr, colors);
5555 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
5556}
Cary Clark8032b982017-07-28 11:04:54 -04005557##
5558
5559#ToDo incomplete ##
5560
5561##
5562
5563# ------------------------------------------------------------------------------
5564
5565#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
5566
5567Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005568If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
5569contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
Cary Clark8032b982017-07-28 11:04:54 -04005570
Cary Clarkbad5ad72017-08-03 17:14:08 -04005571#Param vertices triangle mesh to draw ##
5572#Param mode combines Vertices_Colors with Shader, if both are present ##
5573#Param paint specifies the Shader, used as Vertices texture, may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005574
5575#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005576void draw(SkCanvas* canvas) {
5577 SkPaint paint;
5578 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5579 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
5580 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5581 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
5582 SkShader::kClamp_TileMode));
5583 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5584 SK_ARRAY_COUNT(points), points, texs, colors);
5585 canvas->drawVertices(vertices.get(), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005586}
5587##
5588
5589#ToDo incomplete ##
5590
5591##
5592
5593# ------------------------------------------------------------------------------
5594
5595#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5596 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
5597
Cary Clarkce101242017-09-01 15:51:02 -04005598Draws a Coons patch: the interpolation of four cubics with shared corners,
Cary Clark8032b982017-07-28 11:04:54 -04005599associating a color, and optionally a texture coordinate, with each corner.
5600
Cary Clarkbad5ad72017-08-03 17:14:08 -04005601The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter,
5602Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
5603as the Coons patch texture; Blend_Mode mode combines Color colors and Shader if
5604both are provided.
Cary Clark8032b982017-07-28 11:04:54 -04005605
Cary Clarkce101242017-09-01 15:51:02 -04005606Point array cubics specifies four Cubics starting at the top left corner,
5607in clockwise order, sharing every fourth point. The last Cubic ends at the
Cary Clarkbad5ad72017-08-03 17:14:08 -04005608first point.
Cary Clark8032b982017-07-28 11:04:54 -04005609
Cary Clarkbad5ad72017-08-03 17:14:08 -04005610Color array color associates colors with corners in top left, top right,
5611bottom right, bottom left order.
5612
5613If paint contains Shader, Point array texCoords maps Shader as texture to
5614corners in top left, top right, bottom right, bottom left order.
5615
Cary Clarka523d2d2017-08-30 08:58:10 -04005616#Param cubics Path_Cubic array, sharing common points ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005617#Param colors Color array, one for each corner ##
Cary Clarkce101242017-09-01 15:51:02 -04005618#Param texCoords Point array of texture coordinates, mapping Shader to corners;
Cary Clarkbad5ad72017-08-03 17:14:08 -04005619 may be nullptr
Cary Clark579985c2017-07-31 11:48:27 -04005620#Param ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005621#Param mode Blend_Mode for colors, and for Shader if paint has one ##
5622#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005623
5624#Example
5625#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04005626void draw(SkCanvas* canvas) {
5627 // SkBitmap source = cmbkygk;
5628 SkPaint paint;
5629 paint.setFilterQuality(kLow_SkFilterQuality);
5630 paint.setAntiAlias(true);
5631 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5632 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5633 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5634 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5635 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
5636 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
5637 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5638 SkShader::kClamp_TileMode, nullptr));
5639 canvas->scale(15, 15);
5640 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
5641 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
5642 canvas->translate(4, 4);
5643 }
Cary Clark8032b982017-07-28 11:04:54 -04005644}
5645##
5646
Cary Clarkbad5ad72017-08-03 17:14:08 -04005647#ToDo incomplete; can patch use image filter? ##
Cary Clark8032b982017-07-28 11:04:54 -04005648
5649##
5650
5651# ------------------------------------------------------------------------------
5652
5653#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5654 const SkPoint texCoords[4], const SkPaint& paint)
5655
Cary Clarkce101242017-09-01 15:51:02 -04005656Draws Cubic Coons patch: the interpolation of four cubics with shared corners,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005657associating a color, and optionally a texture coordinate, with each corner.
Cary Clark8032b982017-07-28 11:04:54 -04005658
Cary Clarkbad5ad72017-08-03 17:14:08 -04005659The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter,
5660Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
5661as the Coons patch texture; Blend_Mode mode combines Color colors and Shader if
5662both are provided.
Cary Clark8032b982017-07-28 11:04:54 -04005663
Cary Clarkce101242017-09-01 15:51:02 -04005664Point array cubics specifies four Cubics starting at the top left corner,
5665in clockwise order, sharing every fourth point. The last Cubic ends at the
Cary Clarkbad5ad72017-08-03 17:14:08 -04005666first point.
5667
5668Color array color associates colors with corners in top left, top right,
5669bottom right, bottom left order.
5670
5671If paint contains Shader, Point array texCoords maps Shader as texture to
5672corners in top left, top right, bottom right, bottom left order.
5673
Cary Clarka523d2d2017-08-30 08:58:10 -04005674#Param cubics Path_Cubic array, sharing common points ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005675#Param colors Color array, one for each corner ##
Cary Clarkce101242017-09-01 15:51:02 -04005676#Param texCoords Point array of texture coordinates, mapping Shader to corners;
Cary Clarkbad5ad72017-08-03 17:14:08 -04005677 may be nullptr
Cary Clark579985c2017-07-31 11:48:27 -04005678#Param ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005679#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005680
5681#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005682void draw(SkCanvas* canvas) {
5683 SkPaint paint;
5684 paint.setAntiAlias(true);
5685 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5686 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5687 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5688 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5689 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5690 canvas->scale(30, 30);
5691 canvas->drawPatch(cubics, colors, nullptr, paint);
5692 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
5693 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
5694 {0.5f,3.2f} };
5695 paint.setTextSize(18.f / 30);
5696 paint.setTextAlign(SkPaint::kCenter_Align);
5697 for (int i = 0; i< 10; ++i) {
5698 char digit = '0' + i;
5699 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
5700 }
5701 canvas->drawString("10", text[10].fX, text[10].fY, paint);
5702 canvas->drawString("11", text[11].fX, text[11].fY, paint);
5703 paint.setStyle(SkPaint::kStroke_Style);
5704 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
5705 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005706}
5707##
5708
5709#Example
5710#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04005711void draw(SkCanvas* canvas) {
5712 // SkBitmap source = checkerboard;
5713 SkPaint paint;
5714 paint.setFilterQuality(kLow_SkFilterQuality);
5715 paint.setAntiAlias(true);
5716 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5717 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5718 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5719 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5720 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
5721 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5722 SkShader::kClamp_TileMode, nullptr));
5723 canvas->scale(30, 30);
5724 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005725}
5726##
5727
Cary Clarkbad5ad72017-08-03 17:14:08 -04005728#ToDo incomplete; can patch use image filter? ##
Cary Clark8032b982017-07-28 11:04:54 -04005729
5730##
5731
5732# ------------------------------------------------------------------------------
5733
5734#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
5735 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5736 const SkPaint* paint)
5737
5738Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005739paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5740to draw, if present. For each entry in the array, Rect tex locates sprite in
5741atlas, and RSXform xform transforms it into destination space.
5742
Cary Clark8032b982017-07-28 11:04:54 -04005743xform, text, and colors if present, must contain count entries.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005744Optional colors are applied for each sprite using Blend_Mode.
Cary Clark8032b982017-07-28 11:04:54 -04005745Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005746If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005747
Cary Clarkbad5ad72017-08-03 17:14:08 -04005748#Param atlas Image containing sprites ##
5749#Param xform RSXform mappings for sprites in atlas ##
5750#Param tex Rect locations of sprites in atlas ##
Cary Clark6fc50412017-09-21 12:31:06 -04005751#Param colors one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005752#Param count number of sprites to draw ##
5753#Param mode Blend_Mode combining colors and sprites ##
Cary Clark6fc50412017-09-21 12:31:06 -04005754#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
5755#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005756
5757#Example
5758#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005759void draw(SkCanvas* canvas) {
5760 // SkBitmap source = mandrill;
5761 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5762 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5763 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5764 const SkImage* imagePtr = image.get();
5765 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005766}
5767##
5768
5769#ToDo incomplete ##
5770
5771##
5772
5773# ------------------------------------------------------------------------------
5774
5775#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5776 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5777 const SkPaint* paint)
5778
5779Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005780paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5781to draw, if present. For each entry in the array, Rect tex locates sprite in
5782atlas, and RSXform xform transforms it into destination space.
5783
Cary Clark8032b982017-07-28 11:04:54 -04005784xform, text, and colors if present, must contain count entries.
5785Optional colors is applied for each sprite using Blend_Mode.
5786Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005787If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005788
Cary Clarkbad5ad72017-08-03 17:14:08 -04005789#Param atlas Image containing sprites ##
5790#Param xform RSXform mappings for sprites in atlas ##
5791#Param tex Rect locations of sprites in atlas ##
Cary Clark6fc50412017-09-21 12:31:06 -04005792#Param colors one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005793#Param count number of sprites to draw ##
5794#Param mode Blend_Mode combining colors and sprites ##
Cary Clark6fc50412017-09-21 12:31:06 -04005795#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
5796#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005797
5798#Example
5799#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005800void draw(SkCanvas* canvas) {
5801 // SkBitmap source = mandrill;
5802 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5803 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5804 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5805 SkPaint paint;
5806 paint.setAlpha(127);
5807 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04005808}
5809##
5810
5811#ToDo bug in example on cpu side, gpu looks ok ##
5812
5813##
5814
5815# ------------------------------------------------------------------------------
5816
5817#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
5818 const SkRect* cullRect, const SkPaint* paint)
5819
5820Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005821paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5822to draw, if present. For each entry in the array, Rect tex locates sprite in
5823atlas, and RSXform xform transforms it into destination space.
5824
Cary Clark8032b982017-07-28 11:04:54 -04005825xform and text must contain count entries.
5826Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005827If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005828
Cary Clarkbad5ad72017-08-03 17:14:08 -04005829#Param atlas Image containing sprites ##
5830#Param xform RSXform mappings for sprites in atlas ##
5831#Param tex Rect locations of sprites in atlas ##
5832#Param count number of sprites to draw ##
Cary Clark6fc50412017-09-21 12:31:06 -04005833#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
5834#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005835
5836#Example
5837#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005838void draw(SkCanvas* canvas) {
5839 // sk_sp<SkImage> image = mandrill;
5840 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5841 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5842 const SkImage* imagePtr = image.get();
5843 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005844}
5845##
5846
5847#ToDo incomplete ##
5848
5849##
5850
5851# ------------------------------------------------------------------------------
5852
5853#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5854 int count, const SkRect* cullRect, const SkPaint* paint)
5855
5856Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005857paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5858to draw, if present. For each entry in the array, Rect tex locates sprite in
5859atlas, and RSXform xform transforms it into destination space.
5860
Cary Clark8032b982017-07-28 11:04:54 -04005861xform and text must contain count entries.
5862Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005863If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005864
Cary Clarkbad5ad72017-08-03 17:14:08 -04005865#Param atlas Image containing sprites ##
5866#Param xform RSXform mappings for sprites in atlas ##
5867#Param tex Rect locations of sprites in atlas ##
5868#Param count number of sprites to draw ##
Cary Clark6fc50412017-09-21 12:31:06 -04005869#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
5870#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005871
5872#Example
5873#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005874void draw(SkCanvas* canvas) {
5875 // sk_sp<SkImage> image = mandrill;
5876 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
5877 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
5878 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005879}
5880##
5881
5882#ToDo incomplete ##
5883
5884##
5885
5886# ------------------------------------------------------------------------------
5887
Cary Clark73fa9722017-08-29 17:36:51 -04005888#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04005889
5890Draw Drawable drawable using Clip and Matrix, concatenated with
5891optional matrix.
5892
5893If Canvas has an asynchronous implementation, as is the case
5894when it is recording into Picture, then drawable will be referenced,
5895so that SkDrawable::draw() can be called when the operation is finalized. To force
5896immediate drawing, call SkDrawable::draw() instead.
5897
Cary Clarkbad5ad72017-08-03 17:14:08 -04005898#Param drawable custom struct encapsulating drawing commands ##
5899#Param matrix transformation applied to drawing; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005900
5901#Example
5902#Height 100
5903#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04005904struct MyDrawable : public SkDrawable {
5905 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5906
5907 void onDraw(SkCanvas* canvas) override {
5908 SkPath path;
5909 path.conicTo(10, 90, 50, 90, 0.9f);
5910 SkPaint paint;
5911 paint.setColor(SK_ColorBLUE);
5912 canvas->drawRect(path.getBounds(), paint);
5913 paint.setAntiAlias(true);
5914 paint.setColor(SK_ColorWHITE);
5915 canvas->drawPath(path, paint);
5916 }
5917};
5918
5919#Function ##
5920void draw(SkCanvas* canvas) {
5921 sk_sp<SkDrawable> drawable(new MyDrawable);
5922 SkMatrix matrix;
5923 matrix.setTranslate(10, 10);
5924 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04005925}
5926##
5927
5928#ToDo incomplete ##
5929
5930##
5931
5932# ------------------------------------------------------------------------------
5933
5934#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
5935
5936Draw Drawable drawable using Clip and Matrix, offset by (x, y).
5937
5938If Canvas has an asynchronous implementation, as is the case
5939when it is recording into Picture, then drawable will be referenced,
5940so that SkDrawable::draw() can be called when the operation is finalized. To force
5941immediate drawing, call SkDrawable::draw() instead.
5942
Cary Clarkbad5ad72017-08-03 17:14:08 -04005943#Param drawable custom struct encapsulating drawing commands ##
5944#Param x offset into Canvas writable pixels in x ##
5945#Param y offset into Canvas writable pixels in y ##
Cary Clark8032b982017-07-28 11:04:54 -04005946
5947#Example
5948#Height 100
5949#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04005950struct MyDrawable : public SkDrawable {
5951 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5952
5953 void onDraw(SkCanvas* canvas) override {
5954 SkPath path;
5955 path.conicTo(10, 90, 50, 90, 0.9f);
5956 SkPaint paint;
5957 paint.setColor(SK_ColorBLUE);
5958 canvas->drawRect(path.getBounds(), paint);
5959 paint.setAntiAlias(true);
5960 paint.setColor(SK_ColorWHITE);
5961 canvas->drawPath(path, paint);
5962 }
5963};
5964
5965#Function ##
5966void draw(SkCanvas* canvas) {
5967 sk_sp<SkDrawable> drawable(new MyDrawable);
5968 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04005969}
5970##
5971
5972#ToDo incomplete ##
5973
5974##
5975
5976# ------------------------------------------------------------------------------
5977
5978#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
5979
5980Associate Rect on Canvas when an annotation; a key-value pair, where the key is
5981a null-terminated utf8 string, and optional value is stored as Data.
5982
5983Only some canvas implementations, such as recording to Picture, or drawing to
5984Document_PDF, use annotations.
5985
Cary Clarkbad5ad72017-08-03 17:14:08 -04005986#Param rect Rect extent of canvas to annotate ##
5987#Param key string used for lookup ##
5988#Param value data holding value stored in annotation ##
Cary Clark8032b982017-07-28 11:04:54 -04005989
5990#Example
5991 #Height 1
5992 const char text[] = "Click this link!";
5993 SkRect bounds;
5994 SkPaint paint;
5995 paint.setTextSize(40);
5996 (void)paint.measureText(text, strlen(text), &bounds);
5997 const char url[] = "https://www.google.com/";
5998 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
5999 canvas->drawAnnotation(bounds, "url_key", urlData.get());
6000##
6001
6002#ToDo incomplete ##
6003
6004##
6005
6006# ------------------------------------------------------------------------------
6007
6008#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
6009
6010Associate Rect on Canvas when an annotation; a key-value pair, where the key is
6011a null-terminated utf8 string, and optional value is stored as Data.
6012
6013Only some canvas implementations, such as recording to Picture, or drawing to
6014Document_PDF, use annotations.
6015
Cary Clarkbad5ad72017-08-03 17:14:08 -04006016#Param rect Rect extent of canvas to annotate ##
6017#Param key string used for lookup ##
6018#Param value data holding value stored in annotation ##
Cary Clark8032b982017-07-28 11:04:54 -04006019
6020#Example
6021#Height 1
6022 const char text[] = "Click this link!";
6023 SkRect bounds;
6024 SkPaint paint;
6025 paint.setTextSize(40);
6026 (void)paint.measureText(text, strlen(text), &bounds);
6027 const char url[] = "https://www.google.com/";
6028 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
6029 canvas->drawAnnotation(bounds, "url_key", urlData.get());
6030##
6031
6032#ToDo incomplete ##
6033
6034##
6035
6036#Method SkDrawFilter* getDrawFilter() const
6037
6038Legacy call to be deprecated.
6039
6040#Deprecated
6041##
6042
6043##
6044
6045#Method virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter)
6046
6047Legacy call to be deprecated.
6048
6049#Deprecated
6050##
6051
6052##
6053
6054# ------------------------------------------------------------------------------
6055
6056#Method virtual bool isClipEmpty() const
6057
6058Returns true if Clip is empty; that is, nothing will draw.
6059
Cary Clarkbad5ad72017-08-03 17:14:08 -04006060May do work when called; it should not be called
Cary Clark8032b982017-07-28 11:04:54 -04006061more often than needed. However, once called, subsequent calls perform no
6062work until Clip changes.
6063
Cary Clarkbad5ad72017-08-03 17:14:08 -04006064#Return true if Clip is empty ##
Cary Clark8032b982017-07-28 11:04:54 -04006065
6066#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04006067 void draw(SkCanvas* canvas) {
6068 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
6069 SkPath path;
6070 canvas->clipPath(path);
6071 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04006072 }
6073 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04006074 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04006075 clip is empty
6076 ##
6077##
6078
6079#ToDo incomplete ##
6080
6081##
6082
6083# ------------------------------------------------------------------------------
6084
6085#Method virtual bool isClipRect() const
6086
6087Returns true if Clip is Rect and not empty.
6088Returns false if the clip is empty, or if it is not Rect.
6089
Cary Clarkbad5ad72017-08-03 17:14:08 -04006090#Return true if Clip is Rect and not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04006091
6092#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04006093 void draw(SkCanvas* canvas) {
6094 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
6095 canvas->clipRect({0, 0, 0, 0});
6096 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04006097 }
6098 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04006099 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04006100 clip is not rect
6101 ##
6102##
6103
6104#ToDo incomplete ##
6105
6106##
6107
6108#Class SkCanvas ##
6109#Topic Canvas ##