blob: 8a4fe87fd0b3197b1cf5d71a426a08b5bdb4b56b [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
4Canvas provides an interface for drawing, and how the drawing is clipped and transformed.
5Canvas contains a stack of Matrix and Clip values.
6
7Canvas and Paint together provide the state to draw into Surface or Device.
Cary Clarkbad5ad72017-08-03 17:14:08 -04008Each Canvas draw call transforms the geometry of the object by the concatenation of all
9Matrix values in the stack. The transformed geometry is clipped by the intersection
10of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing
11state such as Color, Typeface, text size, stroke width, Shader and so on.
Cary Clark8032b982017-07-28 11:04:54 -040012
13To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
14Request Canvas from Surface to obtain the interface to draw.
15Canvas generated by Raster_Surface draws to memory visible to the CPU.
16Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
17
Cary Clarkbad5ad72017-08-03 17:14:08 -040018To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
19Document-based Canvas and other Canvas subclasses reference Device describing the
20destination.
21
Cary Clark8032b982017-07-28 11:04:54 -040022Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
23This approach may be deprecated in the future.
24
Cary Clark8032b982017-07-28 11:04:54 -040025#Class SkCanvas
26
27#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. ##
56# SaveLayerRec # Contains state to create the layer offscreen. ##
57#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. ##
98# drawBitmapLattice # Draws differentially stretched Bitmap. ##
99# 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. ##
107# drawImageLattice # Draws differentially stretched Image. ##
108# 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. ##
113# drawPatch # Draws cubic Coons patch. ##
114# 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. ##
132# getBaseLayerSize # Gets size of base layer in global coordinates. ##
133# 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. ##
155# saveLayer # Saves Clip and Matrix on stack; creates offscreen. ##
156# saveLayerAlpha # Saves Clip and Matrix on stack; creates offscreen; sets opacity. ##
157# saveLayerPreserveLCDTextRequests # Saves Clip and Matrix on stack; creates offscreen for LCD text. ##
158# 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* ) {
207 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, premultipled
208 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);
215 canvas->clear(SK_ColorWHITE); // white is unpremultiplied, in ARGB order
216 canvas->flush(); // ensure that pixels are cleared
217 SkPMColor pmWhite = pixels[0]; // the premultiplied format may vary
218 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 Clarkf05bdda2017-08-24 12:59:48 -0400257Pass zero for rowBytes to compute rowBytes from fo width and size of pixel.
258If 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;
281 SkPMColor pixels[height][width]; // allocate a 3x3 premultiplied bitmap on the stack
282 // 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
289 // write a pre-multiplied value for white into all pixels in the bitmap
290 canvas->clear(SK_ColorWHITE);
291 SkPMColor pmWhite = pixels[0][0]; // the premultiplied format may vary
292 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 Clarkf05bdda2017-08-24 12:59:48 -0400317Creates an empty canvas with no backing device or pixels, with
318a width and height of zero.
Cary Clark8032b982017-07-28 11:04:54 -0400319
Cary Clarkbad5ad72017-08-03 17:14:08 -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.
370Used by subclasses with custom implementations for draw methods.
371
Cary Clarkbad5ad72017-08-03 17:14:08 -0400372If props equals nullptr, Surface_Properties are created with Surface_Properties_Legacy_Font_Host settings,
373which choose the pixel striping direction and order. Since a platform may dynamically
374change its direction when the device is rotated, and since a platform may have
375multiple monitors with different characteristics, it's best not to rely on this
376legacy 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);
451 canvas.clear(SK_ColorWHITE); // white is unpremultiplied, in ARGB order
452 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
457 SkPMColor pmWhite = pixels[0]; // the premultiplied format may vary
458 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 Clark73fa9722017-08-29 17:36:51 -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));
543 canvas.clear(SK_ColorWHITE); // white is unpremultiplied, in ARGB order
544 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
549 SkPMColor pmWhite = pixels[0]; // the premultiplied format may vary
550 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 Clarkbad5ad72017-08-03 17:14:08 -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
587Canvas offscreen draws into bitmap. saveLayerAlpha sets up an additional
588drawing surface that blends with the bitmap. When offscreen goes out of
589scope, offscreen destructor is called. The saved layer is restored, drawing
590transparent 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
720Gets the size of the base or root layer in global canvas coordinates. The
721origin of the base layer is always (0,0). The current drawable area may be
722smaller (due to clipping or saveLayer).
723
Cary Clarkbad5ad72017-08-03 17:14:08 -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 ##
817#Param origin storage for Canvas top layer origin, its top left corner;
818 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
835Draws "ABC" on the device. Then draws "DEF" in an offscreen layer, and reads the
836offscreen to add a large dotted "DEF". Finally blends the offscreen with the
837device.
838
839The offscreen and blended result appear on the CPU and GPU but the large dotted
840"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 Clarkbad5ad72017-08-03 17:14:08 -0400891by the host platform's user interface. This accessor returns the custom context generated by
892SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
Cary Clark8032b982017-07-28 11:04:54 -0400893the drawing destination.
894
Cary Clarkbad5ad72017-08-03 17:14:08 -0400895#Return context of custom allocator ##
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
982(this->imageInfo.width(), this->imageInfo.height()).
983Destination rectangle corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
984Copies each readable pixel intersecting both rectangles, without scaling,
985converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400986
Cary Clarkf05bdda2017-08-24 12:59:48 -0400987Pixels are readable when Device is raster, or backed by a GPU.
988Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
989returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
990class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400991
Cary Clarkf05bdda2017-08-24 12:59:48 -0400992The destination pixel storage must be allocated by the caller.
Cary Clark8032b982017-07-28 11:04:54 -0400993
Cary Clarkf05bdda2017-08-24 12:59:48 -0400994Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
995do not match. Only pixels within both source and destination rectangles
996are copied. dstPixels contents outside the rectangle intersection are unchanged.
997
998Pass negative values for srcX or srcY to offset pixels across or down destination.
Cary Clark8032b982017-07-28 11:04:54 -0400999
1000Does not copy, and returns false if:
1001
1002#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001003# Source and destination rectangles do not intersect. ##
1004# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
1005# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001006# dstRowBytes is too small to contain one row of pixels. ##
1007##
1008
Cary Clarkf05bdda2017-08-24 12:59:48 -04001009#Param dstInfo width, height, Image_Color_Type, and Image_Alpha_Type of dstPixels ##
1010#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
1011#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
1012#Param srcX offset into readable pixels in x; may be negative ##
1013#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001014
Cary Clarkbad5ad72017-08-03 17:14:08 -04001015#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001016
1017#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001018#Width 64
1019#Height 64
1020#Description
1021 A black circle drawn on a blue background provides an image to copy.
1022 readPixels copies one quarter of the canvas into each of the four corners.
1023 The offscreen draws over the image.
1024##
1025 canvas->clear(SK_ColorBLUE);
1026 SkPaint paint;
1027 canvas->drawCircle(32, 32, 28, paint);
1028 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
1029 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
1030 sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
1031 for (int x : { 32, -32 } ) {
1032 for (int y : { 32, -32 } ) {
1033 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
1034 }
1035 }
1036 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
1037 canvas->drawImage(image, 0, 0);
1038##
1039
1040#Example
Cary Clark8032b982017-07-28 11:04:54 -04001041#Description
1042 Canvas returned by Raster_Surface has premultiplied pixel values.
1043 clear() takes unpremultiplied input with Color_Alpha equal 0x80
1044 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multipled by Color_Alpha
1045 to generate premultipled value 0x802B5580. readPixels converts pixel back
1046 to unpremultipled value 0x8056A9FF, introducing error.
1047##
1048 canvas->clear(0x8055aaff);
1049 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
1050 uint32_t pixel = 0;
1051 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
1052 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
1053 SkDebugf("pixel = %08x\n", pixel);
1054 }
1055 }
1056
1057 #StdOut
1058 pixel = 802b5580
1059 pixel = 8056a9ff
1060 ##
1061##
1062
Cary Clarkf05bdda2017-08-24 12:59:48 -04001063#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001064
1065##
1066
1067# ------------------------------------------------------------------------------
1068
1069#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
1070
Cary Clarkf05bdda2017-08-24 12:59:48 -04001071Copies rectangle of pixels from Canvas into pixmap. Matrix and Clip are
1072ignored. Source rectangle corners are (srcX, srcY) and
1073(this->imageInfo.width(), this->imageInfo.height()).
1074Destination rectangle are (0, 0) and (pixmap.width(), pixmap.height()).
1075Copies each readable pixel intersecting both rectangles, without scaling,
1076converting to pixmap.colorType() and pixmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001077
Cary Clarkf05bdda2017-08-24 12:59:48 -04001078Pixels are readable when Device is raster, or backed by a GPU.
1079Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
1080returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1081class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001082
Cary Clarkf05bdda2017-08-24 12:59:48 -04001083Allocates pixel storage in pixmap if needed.
Cary Clark8032b982017-07-28 11:04:54 -04001084
Cary Clarkf05bdda2017-08-24 12:59:48 -04001085Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1086do not match. Only pixels within both source and destination rectangles
1087are copied. pixmap pixels contents outside the rectangle intersection are unchanged.
1088
1089Pass negative values for srcX or srcY to offset pixels across or down pixmap.
Cary Clark8032b982017-07-28 11:04:54 -04001090
1091Does not copy, and returns false if:
1092
1093#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001094# Source and destination rectangles do not intersect. ##
1095# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
1096# Canvas pixels are not readable; for instance, Canvas is document-based. ##
1097# Pixmap pixels could not be allocated. ##
1098# pixmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -04001099##
1100
Cary Clarkbad5ad72017-08-03 17:14:08 -04001101#Param pixmap storage for pixels copied from Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001102#Param srcX offset into readable pixels in x; may be negative ##
1103#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001104
Cary Clarkbad5ad72017-08-03 17:14:08 -04001105#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001106
1107#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001108 #Description
1109 clear() takes unpremultiplied input with Color_Alpha equal 0x80
1110 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multipled by Color_Alpha
1111 to generate premultipled value 0x802B5580.
1112 ##
1113 void draw(SkCanvas* canvas) {
1114 canvas->clear(0x8055aaff);
1115 uint32_t pixels[1] = { 0 };
1116 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
1117 canvas->readPixels(pixmap, 0, 0);
1118 SkDebugf("pixel = %08x\n", pixels[0]);
1119 }
Cary Clark8032b982017-07-28 11:04:54 -04001120 #StdOut
1121 pixel = 802b5580
1122 ##
1123##
1124
Cary Clarkf05bdda2017-08-24 12:59:48 -04001125#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001126
1127##
1128
1129# ------------------------------------------------------------------------------
1130
1131#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
1132
Cary Clarkf05bdda2017-08-24 12:59:48 -04001133Copies rectangle of pixels from Canvas into bitmap. Matrix and Clip are
1134ignored. Source rectangle corners are (srcX, srcY) and
1135(this->imageInfo.width(), this->imageInfo.height()).
1136Destination rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
1137Copies each readable pixel intersecting both rectangles, without scaling,
1138converting to bitmap.colorType() and bitmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001139
Cary Clarkf05bdda2017-08-24 12:59:48 -04001140Pixels are readable when Device is raster, or backed by a GPU.
1141Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
1142returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1143class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001144
Cary Clarkf05bdda2017-08-24 12:59:48 -04001145Allocates pixel storage in bitmap if needed.
1146
1147Bitmap values are converted only if Image_Color_Type and Image_Alpha_Type
1148do not match. Only pixels within both source and destination rectangles
1149are copied. Bitmap pixels outside the rectangle intersection are unchanged.
1150
1151Pass negative values for srcX or srcY to offset pixels across or down bitmap.
Cary Clark8032b982017-07-28 11:04:54 -04001152
1153Does not copy, and returns false if:
1154
1155#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001156# Source and destination rectangles do not intersect. ##
1157# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
1158# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001159# bitmap pixels could not be allocated. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001160# bitmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -04001161##
1162
Cary Clarkbad5ad72017-08-03 17:14:08 -04001163#Param bitmap storage for pixels copied from Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001164#Param srcX offset into readable pixels in x; may be negative ##
1165#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001166
Cary Clarkbad5ad72017-08-03 17:14:08 -04001167#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001168
1169#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001170 #Description
1171 clear() takes unpremultiplied input with Color_Alpha equal 0x80
1172 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multipled by Color_Alpha
1173 to generate premultipled value 0x802B5580.
1174 ##
Cary Clark8032b982017-07-28 11:04:54 -04001175void draw(SkCanvas* canvas) {
1176 canvas->clear(0x8055aaff);
1177 SkBitmap bitmap;
1178 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
1179 canvas->readPixels(bitmap, 0, 0);
1180 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
1181}
1182 #StdOut
1183 pixel = 802b5580
1184 ##
1185##
1186
Cary Clarkf05bdda2017-08-24 12:59:48 -04001187#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001188
1189##
1190
1191# ------------------------------------------------------------------------------
1192
1193#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
1194
Cary Clarkf05bdda2017-08-24 12:59:48 -04001195Copies rectangle from pixels to Canvas. Matrix and Clip are ignored.
1196Source rectangle corners are (0, 0) and (info.width(), info.height()).
1197Destination rectangle corners are (x, y) and
1198(this->imageInfo.width(), this->imageInfo.height()). Copies each readable pixel
1199intersecting both rectangles, without scaling, converting to
1200this->imageInfo.colorType() and this->imageInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001201
Cary Clarkf05bdda2017-08-24 12:59:48 -04001202Pixels are writable when Device is raster, or backed by a GPU.
1203Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
1204returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1205class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001206
Cary Clarkf05bdda2017-08-24 12:59:48 -04001207Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1208do not match. Only pixels within both source and destination rectangles
1209are copied. Canvas pixels outside the rectangle intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -04001210
Cary Clarkf05bdda2017-08-24 12:59:48 -04001211Pass negative values for x or y to offset pixels to the left or
1212above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001213
1214Does not copy, and returns false if:
1215
1216#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001217# Source and destination rectangles do not intersect. ##
1218# pixels could not be converted to this->imageInfo.colorType() or this->imageInfo.alphaType(). ##
Cary Clark8032b982017-07-28 11:04:54 -04001219# Canvas pixels are not writable; for instance, Canvas is document-based. ##
1220# rowBytes is too small to contain one row of pixels. ##
1221##
1222
Cary Clarkf05bdda2017-08-24 12:59:48 -04001223#Param info width, height, Image_Color_Type, and Image_Alpha_Type of pixels ##
1224#Param pixels pixels to copy, of size info.height() times rowBytes, or larger ##
1225#Param rowBytes size of one pixels row; info.width() times pixel size, or larger ##
1226#Param x offset into Canvas writable pixels in x; may be negative ##
1227#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001228
Cary Clarkbad5ad72017-08-03 17:14:08 -04001229#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001230
1231#Example
1232 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
1233 for (int y = 0; y < 256; ++y) {
1234 uint32_t pixels[256];
1235 for (int x = 0; x < 256; ++x) {
1236 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
1237 }
1238 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
1239 }
1240##
1241
Cary Clarkf05bdda2017-08-24 12:59:48 -04001242#SeeAlso readPixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001243
1244##
1245
1246# ------------------------------------------------------------------------------
1247
1248#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
1249
Cary Clarkf05bdda2017-08-24 12:59:48 -04001250Copies rectangle from pixels to Canvas. Matrix and Clip are ignored.
1251Source rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
1252Destination rectangle corners are (x, y) and
1253(this->imageInfo.width(), this->imageInfo.height()). Copies each readable pixel
1254intersecting both rectangles, without scaling, converting to
1255this->imageInfo.colorType() and this->imageInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001256
Cary Clarkf05bdda2017-08-24 12:59:48 -04001257Pixels are writable when Device is raster, or backed by a GPU.
1258Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
1259returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1260class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001261
Cary Clarkf05bdda2017-08-24 12:59:48 -04001262Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1263do not match. Only pixels within both source and destination rectangles
1264are copied. Canvas pixels outside the rectangle intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -04001265
Cary Clarkf05bdda2017-08-24 12:59:48 -04001266Pass negative values for x or y to offset pixels to the left or
1267above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001268
1269Does not copy, and returns false if:
1270
1271#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001272# Source and destination rectangles do not intersect. ##
Cary Clark8032b982017-07-28 11:04:54 -04001273# bitmap does not have allocated pixels. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001274# bitmap pixels could not be converted to this->imageInfo.colorType() or this->imageInfo.alphaType(). ##
Cary Clark8032b982017-07-28 11:04:54 -04001275# Canvas pixels are not writable; for instance, Canvas is document-based. ##
1276# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
1277##
1278
Cary Clarkbad5ad72017-08-03 17:14:08 -04001279#Param bitmap contains pixels copied to Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001280#Param x offset into Canvas writable pixels in x; may be negative ##
1281#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001282
Cary Clarkbad5ad72017-08-03 17:14:08 -04001283#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001284
1285#Example
1286void draw(SkCanvas* canvas) {
1287 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
1288 SkBitmap bitmap;
1289 bitmap.setInfo(imageInfo);
1290 uint32_t pixels[4];
1291 bitmap.setPixels(pixels);
1292 for (int y = 0; y < 256; y += 2) {
1293 for (int x = 0; x < 256; x += 2) {
1294 pixels[0] = SkColorSetRGB(x, y, x | y);
1295 pixels[1] = SkColorSetRGB(x ^ y, y, x);
1296 pixels[2] = SkColorSetRGB(x, x & y, y);
1297 pixels[3] = SkColorSetRGB(~x, ~y, x);
1298 canvas->writePixels(bitmap, x, y);
1299 }
1300 }
1301}
1302##
1303
Cary Clarkf05bdda2017-08-24 12:59:48 -04001304#SeeAlso readPixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001305
1306##
1307
1308# ------------------------------------------------------------------------------
1309#Topic State_Stack
1310
1311Canvas maintains a stack of state that allows hierarchical drawing, commonly used
Cary Clarkbad5ad72017-08-03 17:14:08 -04001312to implement windows and views. The initial state has an identity matrix and and
1313an infinite clip. Even with a wide-open clip, drawing is constrained by the
1314bounds of the Canvas Surface or Device.
Cary Clark8032b982017-07-28 11:04:54 -04001315
1316Canvas savable state consists of Clip, Matrix, and Draw_Filter.
1317Clip describes the area that may be drawn to.
1318Matrix transforms the geometry.
1319Draw_Filter (deprecated on most platforms) modifies the paint before drawing.
1320
1321save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
1322save state and return the depth of the stack.
1323
Cary Clarkbad5ad72017-08-03 17:14:08 -04001324restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
Cary Clark8032b982017-07-28 11:04:54 -04001325
1326Each state on the stack intersects Clip with the previous Clip,
1327and concatenates Matrix with the previous Matrix.
1328The intersected Clip makes the drawing area the same or smaller;
1329the concatenated Matrix may move the origin and potentially scale or rotate
1330the coordinate space.
1331
1332Canvas does not require balancing the state stack but it is a good idea
1333to do so. Calling save() without restore() will eventually cause Skia to fail;
1334mismatched save() and restore() create hard to find bugs.
1335
1336It is not possible to use state to draw outside of the clip defined by the
1337previous state.
1338
1339#Example
1340#Description
1341Draw to ever smaller clips; then restore drawing to full canvas.
1342Note that the second clipRect is not permitted to enlarge Clip.
1343##
1344#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001345void draw(SkCanvas* canvas) {
1346 SkPaint paint;
1347 canvas->save(); // records stack depth to restore
1348 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
1349 canvas->clear(SK_ColorRED); // draws to limit of clip
1350 canvas->save(); // records stack depth to restore
1351 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
1352 canvas->clear(SK_ColorBLUE); // draws to smaller clip
1353 canvas->restore(); // enlarges clip
1354 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
1355 canvas->restore(); // enlarges clip
1356 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
Cary Clark8032b982017-07-28 11:04:54 -04001357}
1358##
1359
1360Each Clip uses the current Matrix for its coordinates.
1361
1362#Example
1363#Description
1364While clipRect is given the same rectangle twice, Matrix makes the second
1365clipRect draw at half the size of the first.
1366##
1367#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001368void draw(SkCanvas* canvas) {
1369 canvas->clipRect(SkRect::MakeWH(100, 100));
1370 canvas->clear(SK_ColorRED);
1371 canvas->scale(.5, .5);
1372 canvas->clipRect(SkRect::MakeWH(100, 100));
1373 canvas->clear(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001374}
1375##
1376
1377#SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
1378
1379#Method int save()
1380
1381Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms).
1382Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1383restoring the Matrix, Clip, and Draw_Filter to their state when save() was called.
1384
Cary Clarkbad5ad72017-08-03 17:14:08 -04001385Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix,
1386and resetMatrix. Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001387
Cary Clarkbad5ad72017-08-03 17:14:08 -04001388Saved Canvas state is put on a stack; multiple calls to save() should be balance
1389by an equal number of calls to restore().
Cary Clark8032b982017-07-28 11:04:54 -04001390
1391Call restoreToCount with result to restore this and subsequent saves.
1392
Cary Clarkbad5ad72017-08-03 17:14:08 -04001393#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001394
1395#Example
1396#Description
1397The black square is translated 50 pixels down and to the right.
1398Restoring Canvas state removes translate() from Canvas stack;
1399the red square is not translated, and is drawn at the origin.
1400##
1401#Height 100
1402void draw(SkCanvas* canvas) {
1403 SkPaint paint;
1404 SkRect rect = { 0, 0, 25, 25 };
1405 canvas->drawRect(rect, paint);
1406 canvas->save();
1407 canvas->translate(50, 50);
1408 canvas->drawRect(rect, paint);
1409 canvas->restore();
1410 paint.setColor(SK_ColorRED);
1411 canvas->drawRect(rect, paint);
1412}
1413##
1414
1415#ToDo incomplete ##
1416
1417##
1418
1419# ------------------------------------------------------------------------------
1420#Subtopic Layer
1421
Cary Clarkbad5ad72017-08-03 17:14:08 -04001422Layer allocates a temporary offscreen Bitmap to draw into. When the drawing is
1423complete, the Bitmap is drawn into the Canvas.
Cary Clark8032b982017-07-28 11:04:54 -04001424
1425Layer is saved in a stack along with other saved state. When state with a Layer
1426is restored, the offscreen Bitmap is drawn into the previous layer.
1427
1428Layer may be initialized with the contents of the previous layer. When Layer is
Cary Clarkbad5ad72017-08-03 17:14:08 -04001429restored, its Bitmap can be modified by Paint passed to Layer to apply
1430Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
Cary Clark8032b982017-07-28 11:04:54 -04001431
1432#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1433
1434Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1435and allocates an offscreen Bitmap for subsequent drawing.
1436Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1437and draws the offscreen bitmap.
Cary Clark8032b982017-07-28 11:04:54 -04001438
Cary Clarkbad5ad72017-08-03 17:14:08 -04001439Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1440setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1441clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001442
Cary Clarkbad5ad72017-08-03 17:14:08 -04001443Rect bounds suggests but does not define the offscreen size. To clip drawing to
1444a specific rectangle, use clipRect.
Cary Clark8032b982017-07-28 11:04:54 -04001445
Cary Clarkbad5ad72017-08-03 17:14:08 -04001446Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1447Blend_Mode when restore() is called.
Cary Clark8032b982017-07-28 11:04:54 -04001448
Cary Clarkbad5ad72017-08-03 17:14:08 -04001449Call restoreToCount with returned value to restore this and subsequent saves.
Cary Clark8032b982017-07-28 11:04:54 -04001450
Cary Clarkbad5ad72017-08-03 17:14:08 -04001451#Param bounds hint to limit the size of the offscreen; may be nullptr ##
1452#Param paint graphics state for offscreen; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04001453
Cary Clarkbad5ad72017-08-03 17:14:08 -04001454#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001455
1456#Example
1457#Description
Cary Clarkbad5ad72017-08-03 17:14:08 -04001458Rectangles are blurred by Image_Filter when restore() draws offscreen to main
1459Canvas.
Cary Clark8032b982017-07-28 11:04:54 -04001460##
1461#Height 128
1462void draw(SkCanvas* canvas) {
1463 SkPaint paint, blur;
1464 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1465 canvas->saveLayer(nullptr, &blur);
1466 SkRect rect = { 25, 25, 50, 50};
1467 canvas->drawRect(rect, paint);
1468 canvas->translate(50, 50);
1469 paint.setColor(SK_ColorRED);
1470 canvas->drawRect(rect, paint);
1471 canvas->restore();
1472}
1473##
1474
1475#ToDo incomplete ##
1476
1477##
1478
1479#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
1480
1481Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1482and allocates an offscreen Bitmap for subsequent drawing.
1483Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1484and draws the offscreen Bitmap.
Cary Clark8032b982017-07-28 11:04:54 -04001485
Cary Clarkbad5ad72017-08-03 17:14:08 -04001486Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1487setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1488clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001489
Cary Clarkbad5ad72017-08-03 17:14:08 -04001490Rect bounds suggests but does not define the offscreen size. To clip drawing to
1491a specific rectangle, use clipRect.
Cary Clark8032b982017-07-28 11:04:54 -04001492
Cary Clarkbad5ad72017-08-03 17:14:08 -04001493Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1494Blend_Mode when restore() is called.
Cary Clark8032b982017-07-28 11:04:54 -04001495
Cary Clarkbad5ad72017-08-03 17:14:08 -04001496Call restoreToCount with returned value to restore this and subsequent saves.
Cary Clark8032b982017-07-28 11:04:54 -04001497
Cary Clarkbad5ad72017-08-03 17:14:08 -04001498#Param bounds hint to limit the size of the offscreen; may be nullptr ##
1499#Param paint graphics state for offscreen; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04001500
Cary Clarkbad5ad72017-08-03 17:14:08 -04001501#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001502
1503#Example
1504#Description
1505Rectangles are blurred by Image_Filter when restore() draws offscreen to main Canvas.
1506The red rectangle is clipped; it does not fully fit on the offscreen Canvas.
1507Image_Filter blurs past edge of offscreen so red rectangle is blurred on all sides.
1508##
1509#Height 128
1510void draw(SkCanvas* canvas) {
1511 SkPaint paint, blur;
1512 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1513 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1514 SkRect rect = { 25, 25, 50, 50};
1515 canvas->drawRect(rect, paint);
1516 canvas->translate(50, 50);
1517 paint.setColor(SK_ColorRED);
1518 canvas->drawRect(rect, paint);
1519 canvas->restore();
1520}
1521##
1522
1523#ToDo incomplete ##
1524
1525##
1526
1527#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
1528
1529Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1530and allocates an offscreen bitmap for subsequent drawing.
1531LCD_Text is preserved when the offscreen is drawn to the prior layer.
1532
Cary Clark8032b982017-07-28 11:04:54 -04001533Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1534and draws the offscreen bitmap.
Cary Clark8032b982017-07-28 11:04:54 -04001535
Cary Clarkbad5ad72017-08-03 17:14:08 -04001536Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1537setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1538clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001539
Cary Clarkbad5ad72017-08-03 17:14:08 -04001540Rect bounds suggests but does not define the offscreen size. To clip drawing to
1541a specific rectangle, use clipRect.
Cary Clark8032b982017-07-28 11:04:54 -04001542
Cary Clarkbad5ad72017-08-03 17:14:08 -04001543Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1544Blend_Mode when restore() is called.
Cary Clark8032b982017-07-28 11:04:54 -04001545
Cary Clarkbad5ad72017-08-03 17:14:08 -04001546Call restoreToCount with returned value to restore this and subsequent saves.
Cary Clark8032b982017-07-28 11:04:54 -04001547
Cary Clarkbad5ad72017-08-03 17:14:08 -04001548Draw text on an opaque background so that LCD_Text blends correctly with the
1549prior layer. LCD_Text drawn on a background with transparency may result in
1550incorrect banding.
Cary Clark8032b982017-07-28 11:04:54 -04001551
Cary Clarkbad5ad72017-08-03 17:14:08 -04001552#Param bounds hint to limit the size of the offscreen; may be nullptr ##
1553#Param paint graphics state for offscreen; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04001554
Cary Clarkbad5ad72017-08-03 17:14:08 -04001555#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001556
1557#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001558 SkPaint paint;
1559 paint.setAntiAlias(true);
1560 paint.setLCDRenderText(true);
1561 paint.setTextSize(20);
1562 for (auto preserve : { false, true } ) {
1563 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
1564 : canvas->saveLayer(nullptr, nullptr);
1565 SkPaint p;
1566 p.setColor(SK_ColorWHITE);
1567 // Comment out the next line to draw on a non-opaque background.
1568 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
1569 canvas->drawString("Hamburgefons", 30, 60, paint);
1570
1571 p.setColor(0xFFCCCCCC);
1572 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
1573 canvas->drawString("Hamburgefons", 30, 90, paint);
1574
1575 canvas->restore();
1576 canvas->translate(0, 80);
Cary Clark8032b982017-07-28 11:04:54 -04001577 }
1578 ##
1579
1580#ToDo incomplete ##
1581
1582##
1583
1584#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1585
1586Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1587and allocates an offscreen bitmap for subsequent drawing.
1588
1589Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1590and blends the offscreen bitmap with alpha opacity onto the prior layer.
Cary Clark8032b982017-07-28 11:04:54 -04001591
Cary Clarkbad5ad72017-08-03 17:14:08 -04001592Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1593setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1594clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001595
Cary Clarkbad5ad72017-08-03 17:14:08 -04001596Rect bounds suggests but does not define the offscreen size. To clip drawing to
1597a specific rectangle, use clipRect.
Cary Clark8032b982017-07-28 11:04:54 -04001598
Cary Clarkbad5ad72017-08-03 17:14:08 -04001599alpha of zero is fully transparent, 255 is fully opaque.
Cary Clark8032b982017-07-28 11:04:54 -04001600
Cary Clarkbad5ad72017-08-03 17:14:08 -04001601Call restoreToCount with returned value to restore this and subsequent saves.
Cary Clark8032b982017-07-28 11:04:54 -04001602
Cary Clarkbad5ad72017-08-03 17:14:08 -04001603#Param bounds hint to limit the size of the offscreen; may be nullptr ##
1604#Param alpha opacity of the offscreen ##
1605
1606#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001607
1608#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001609 SkPaint paint;
1610 paint.setColor(SK_ColorRED);
1611 canvas->drawCircle(50, 50, 50, paint);
1612 canvas->saveLayerAlpha(nullptr, 128);
1613 paint.setColor(SK_ColorBLUE);
1614 canvas->drawCircle(100, 50, 50, paint);
1615 paint.setColor(SK_ColorGREEN);
1616 paint.setAlpha(128);
1617 canvas->drawCircle(75, 90, 50, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001618 canvas->restore();
1619##
1620
1621#ToDo incomplete ##
1622
1623##
1624
Cary Clarkbad5ad72017-08-03 17:14:08 -04001625#Enum
Cary Clark8032b982017-07-28 11:04:54 -04001626
1627#Code
1628 enum {
1629 kIsOpaque_SaveLayerFlag = 1 << 0,
1630 kPreserveLCDText_SaveLayerFlag = 1 << 1,
1631 kInitWithPrevious_SaveLayerFlag = 1 << 2,
Cary Clarkbad5ad72017-08-03 17:14:08 -04001632 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
Cary Clark8032b982017-07-28 11:04:54 -04001633 };
1634
1635 typedef uint32_t SaveLayerFlags;
1636##
1637
1638SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
1639defining how the offscreen allocated by saveLayer operates.
1640
1641#Const kIsOpaque_SaveLayerFlag 1
1642 Creates offscreen without transparency. Flag is ignored if layer Paint contains
1643 Image_Filter or Color_Filter.
1644##
1645
1646#Const kPreserveLCDText_SaveLayerFlag 2
1647 Creates offscreen for LCD text. Flag is ignored if layer Paint contains
1648 Image_Filter or Color_Filter.
1649##
1650
1651#Const kInitWithPrevious_SaveLayerFlag 4
1652 Initializes offscreen with the contents of the previous layer.
1653##
1654
Cary Clarkbad5ad72017-08-03 17:14:08 -04001655#Const kDontClipToLayer_Legacy_SaveLayerFlag 0x80000000
1656#Private
1657 to be deprecated: bug.skia.org/2440
1658##
1659 Only present on Android.
1660 Skips setting a clip to the layer bounds.
1661##
1662
Cary Clark8032b982017-07-28 11:04:54 -04001663#Example
1664#Height 160
1665#Description
1666Canvas layer captures red and blue circles scaled up by four.
1667scalePaint blends offscreen back with transparency.
1668##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001669void draw(SkCanvas* canvas) {
1670 SkPaint redPaint, bluePaint, scalePaint;
1671 redPaint.setColor(SK_ColorRED);
1672 canvas->drawCircle(21, 21, 8, redPaint);
1673 bluePaint.setColor(SK_ColorBLUE);
1674 canvas->drawCircle(31, 21, 8, bluePaint);
1675 SkMatrix matrix;
1676 matrix.setScale(4, 4);
1677 scalePaint.setAlpha(0x40);
1678 scalePaint.setImageFilter(
1679 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1680 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
1681 SkCanvas::kInitWithPrevious_SaveLayerFlag);
1682 canvas->saveLayer(saveLayerRec);
1683 canvas->restore();
Cary Clark8032b982017-07-28 11:04:54 -04001684}
1685##
1686
1687#ToDo incomplete ##
1688
1689#Enum ##
1690
1691#Struct SaveLayerRec
1692
1693#Code
1694 struct SaveLayerRec {
1695 SaveLayerRec*(...
1696
1697 const SkRect* fBounds;
1698 const SkPaint* fPaint;
1699 const SkImageFilter* fBackdrop;
1700 SaveLayerFlags fSaveLayerFlags;
1701 };
1702##
1703
1704SaveLayerRec contains the state used to create the layer offscreen.
1705
1706#Member const SkRect* fBounds
1707 fBounds is used as a hint to limit the size of the offscreen; may be nullptr.
Cary Clarkbad5ad72017-08-03 17:14:08 -04001708 fBounds suggests but does not define the offscreen size. To clip drawing to
1709 a specific rectangle, use clipRect.
Cary Clark8032b982017-07-28 11:04:54 -04001710##
1711
1712#Member const SkPaint* fPaint
Cary Clarkbad5ad72017-08-03 17:14:08 -04001713 fPaint modifies how the offscreen overlays the prior layer; may be nullptr.
1714 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1715 Mask_Filter affect the offscreen draw.
Cary Clark8032b982017-07-28 11:04:54 -04001716##
1717
1718#Member const SkImageFilter* fBackdrop
Cary Clarkbad5ad72017-08-03 17:14:08 -04001719 fBackdrop applies Image_Filter to the prior layer when copying to the layer
1720 offscreen; may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1721 prior layer without an Image_Filter.
Cary Clark8032b982017-07-28 11:04:54 -04001722##
1723
1724#Member const SkImage* fClipMask
Cary Clarkbad5ad72017-08-03 17:14:08 -04001725 restore() clips the layer offscreen by the alpha channel of fClipMask when
1726 the offscreen is copied to Device. fClipMask may be nullptr. .
Cary Clark8032b982017-07-28 11:04:54 -04001727##
1728
1729#Member const SkMatrix* fClipMatrix
Cary Clarkbad5ad72017-08-03 17:14:08 -04001730 fClipMatrix transforms fClipMask before it clips the layer offscreen. If
1731 fClipMask describes a translucent gradient, it may be scaled and rotated
1732 without introducing artifacts. fClipMatrix may be nullptr.
Cary Clark8032b982017-07-28 11:04:54 -04001733##
1734
1735#Member SaveLayerFlags fSaveLayerFlags
Cary Clarkbad5ad72017-08-03 17:14:08 -04001736 fSaveLayerFlags are used to create layer offscreen without transparency,
1737 create layer offscreen for LCD text, and to create layer offscreen with the
1738 contents of the previous layer.
Cary Clark8032b982017-07-28 11:04:54 -04001739##
1740
1741#Example
1742#Height 160
1743#Description
Cary Clarkbad5ad72017-08-03 17:14:08 -04001744Canvas layer captures a red anti-aliased circle and a blue aliased circle scaled
1745up by four. After drawing another unscaled red circle on top, the offscreen is
1746transferred to the main canvas.
Cary Clark8032b982017-07-28 11:04:54 -04001747##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001748void draw(SkCanvas* canvas) {
1749 SkPaint redPaint, bluePaint;
1750 redPaint.setAntiAlias(true);
1751 redPaint.setColor(SK_ColorRED);
1752 canvas->drawCircle(21, 21, 8, redPaint);
1753 bluePaint.setColor(SK_ColorBLUE);
1754 canvas->drawCircle(31, 21, 8, bluePaint);
1755 SkMatrix matrix;
1756 matrix.setScale(4, 4);
1757 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
1758 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
1759 canvas->saveLayer(saveLayerRec);
1760 canvas->drawCircle(125, 85, 8, redPaint);
1761 canvas->restore();
Cary Clark8032b982017-07-28 11:04:54 -04001762}
1763##
1764
1765#Method SaveLayerRec()
1766
1767Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
1768
Cary Clarkbad5ad72017-08-03 17:14:08 -04001769#Return empty SaveLayerRec ##
Cary Clark8032b982017-07-28 11:04:54 -04001770
1771#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001772 SkCanvas::SaveLayerRec rec1;
1773 rec1.fSaveLayerFlags = SkCanvas::kIsOpaque_SaveLayerFlag;
1774 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kIsOpaque_SaveLayerFlag);
1775 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1776 && rec1.fPaint == rec2.fPaint
1777 && rec1.fBackdrop == rec2.fBackdrop
Cary Clark8032b982017-07-28 11:04:54 -04001778 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1779 #StdOut
1780 rec1 == rec2
1781 ##
1782##
1783
1784##
1785
1786#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
1787
1788Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
1789
Cary Clarkbad5ad72017-08-03 17:14:08 -04001790#Param bounds offscreen dimensions; may be nullptr ##
1791#Param paint applied to offscreen when overlaying prior layer; may be nullptr ##
1792#Param saveLayerFlags SaveLayerRec options to modify offscreen ##
Cary Clark8032b982017-07-28 11:04:54 -04001793
Cary Clarkbad5ad72017-08-03 17:14:08 -04001794#Return SaveLayerRec with empty backdrop ##
Cary Clark8032b982017-07-28 11:04:54 -04001795
1796#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001797 SkCanvas::SaveLayerRec rec1;
1798 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1799 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1800 && rec1.fPaint == rec2.fPaint
1801 && rec1.fBackdrop == rec2.fBackdrop
Cary Clark8032b982017-07-28 11:04:54 -04001802 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1803 #StdOut
1804 rec1 == rec2
1805 ##
1806##
1807
1808##
1809
1810#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1811 SaveLayerFlags saveLayerFlags)
1812
1813Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
1814
Cary Clarkbad5ad72017-08-03 17:14:08 -04001815#Param bounds offscreen dimensions; may be nullptr ##
1816#Param paint applied to offscreen when overlaying prior layer;
1817 may be nullptr
1818##
1819#Param backdrop prior layer copied to offscreen with Image_Filter;
1820 may be nullptr
1821##
1822#Param saveLayerFlags SaveLayerRec options to modify offscreen ##
Cary Clark8032b982017-07-28 11:04:54 -04001823
Cary Clarkbad5ad72017-08-03 17:14:08 -04001824#Return SaveLayerRec fully specified ##
Cary Clark8032b982017-07-28 11:04:54 -04001825
1826#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001827 SkCanvas::SaveLayerRec rec1;
1828 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1829 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1830 && rec1.fPaint == rec2.fPaint
1831 && rec1.fBackdrop == rec2.fBackdrop
Cary Clark8032b982017-07-28 11:04:54 -04001832 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1833 #StdOut
1834 rec1 == rec2
1835 ##
1836##
1837
1838##
1839
1840#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1841 const SkImage* clipMask, const SkMatrix* clipMatrix,
1842 SaveLayerFlags saveLayerFlags)
1843
1844#Experimental
1845Not ready for general use.
1846##
1847
Cary Clarkbad5ad72017-08-03 17:14:08 -04001848Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
1849clipMatrix uses alpha channel of image, transformed by clipMatrix, to clip layer
1850when drawn to Canvas.
Cary Clark8032b982017-07-28 11:04:54 -04001851
Cary Clarkbad5ad72017-08-03 17:14:08 -04001852Implementation is incomplete; has no effect if Device is GPU-backed.
1853
1854#Param bounds offscreen dimensions; may be nullptr ##
1855#Param paint graphics state applied to offscreen when overlaying prior
1856 layer; may be nullptr
1857##
1858#Param backdrop prior layer copied to offscreen with Image_Filter;
1859 may be nullptr
1860##
1861#Param clipMask clip applied to layer; may be nullptr ##
1862#Param clipMatrix matrix applied to clipMask; may be nullptr to use
1863 identity matrix
1864##
1865#Param saveLayerFlags SaveLayerRec options to modify offscreen ##
1866
1867#Return SaveLayerRec fully specified ##
Cary Clark8032b982017-07-28 11:04:54 -04001868
1869#ToDo incomplete ##
1870
1871##
1872
1873#Struct ##
1874
1875#Method int saveLayer(const SaveLayerRec& layerRec)
1876
1877Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1878and allocates an offscreen bitmap for subsequent drawing.
1879
1880Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1881and blends the offscreen bitmap with alpha opacity onto the prior layer.
Cary Clark8032b982017-07-28 11:04:54 -04001882
Cary Clarkbad5ad72017-08-03 17:14:08 -04001883Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1884setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1885clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001886
1887SaveLayerRec contains the state used to create the layer offscreen.
1888
Cary Clarkbad5ad72017-08-03 17:14:08 -04001889Call restoreToCount with returned value to restore this and subsequent saves.
Cary Clark8032b982017-07-28 11:04:54 -04001890
Cary Clarkbad5ad72017-08-03 17:14:08 -04001891#Param layerRec offscreen state ##
Cary Clark8032b982017-07-28 11:04:54 -04001892
Cary Clarkbad5ad72017-08-03 17:14:08 -04001893#Return depth of save state stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001894
1895#Example
1896#Description
1897The example draws an image, and saves it into a layer with kInitWithPrevious_SaveLayerFlag.
1898Next it punches a hole in the layer and restore with SkBlendMode::kPlus.
1899Where the layer was cleared, the original image will draw unchanged.
1900Outside of the circle the mandrill is brightened.
1901##
1902 #Image 3
1903 // sk_sp<SkImage> image = GetResourceAsImage("mandrill_256.png");
1904 canvas->drawImage(image, 0, 0, nullptr);
1905 SkCanvas::SaveLayerRec rec;
1906 SkPaint paint;
1907 paint.setBlendMode(SkBlendMode::kPlus);
1908 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1909 rec.fPaint = &paint;
1910 canvas->saveLayer(rec);
1911 paint.setBlendMode(SkBlendMode::kClear);
1912 canvas->drawCircle(128, 128, 96, paint);
1913 canvas->restore();
1914##
1915
1916#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
1917
1918##
1919
1920#Subtopic Layer ##
1921
1922# ------------------------------------------------------------------------------
1923
1924#Method void restore()
1925
1926Removes changes to Matrix, Clip, and Draw_Filter since Canvas state was
1927last saved. The state is removed from the stack.
1928
1929Does nothing if the stack is empty.
1930
1931#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001932void draw(SkCanvas* canvas) {
1933 SkCanvas simple;
1934 SkDebugf("depth = %d\n", simple.getSaveCount());
1935 simple.restore();
1936 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001937}
1938##
1939
1940##
1941
1942# ------------------------------------------------------------------------------
1943
1944#Method int getSaveCount() const
1945
1946Returns the number of saved states, each containing: Matrix, Clip, and Draw_Filter.
1947Equals the number of save() calls less the number of restore() calls plus one.
1948The save count of a new canvas is one.
1949
Cary Clarkbad5ad72017-08-03 17:14:08 -04001950#Return depth of save state stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001951
1952#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001953void draw(SkCanvas* canvas) {
1954 SkCanvas simple;
1955 SkDebugf("depth = %d\n", simple.getSaveCount());
1956 simple.save();
1957 SkDebugf("depth = %d\n", simple.getSaveCount());
1958 simple.restore();
1959 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001960}
1961#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001962depth = 1
1963depth = 2
Cary Clark8032b982017-07-28 11:04:54 -04001964depth = 1
1965##
1966##
1967
1968##
1969
1970# ------------------------------------------------------------------------------
1971
1972#Method void restoreToCount(int saveCount)
1973
Cary Clarkbad5ad72017-08-03 17:14:08 -04001974Restores state to Matrix, Clip, and Draw_Filter values when save(), saveLayer,
1975saveLayerPreserveLCDTextRequests, or saveLayerAlpha returned saveCount.
Cary Clark8032b982017-07-28 11:04:54 -04001976
1977Does nothing if saveCount is greater than state stack count.
1978Restores state to initial values if saveCount is less than or equal to one.
1979
Cary Clarkbad5ad72017-08-03 17:14:08 -04001980#Param saveCount depth of state stack to restore ##
Cary Clark8032b982017-07-28 11:04:54 -04001981
1982#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001983void draw(SkCanvas* canvas) {
1984 SkDebugf("depth = %d\n", canvas->getSaveCount());
1985 canvas->save();
1986 canvas->save();
1987 SkDebugf("depth = %d\n", canvas->getSaveCount());
1988 canvas->restoreToCount(0);
1989 SkDebugf("depth = %d\n", canvas->getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001990}
1991#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001992depth = 1
1993depth = 3
Cary Clark8032b982017-07-28 11:04:54 -04001994depth = 1
1995##
1996##
1997
1998##
1999
2000#Topic State_Stack ##
2001
2002# ------------------------------------------------------------------------------
2003#Topic Matrix
2004
2005#Method void translate(SkScalar dx, SkScalar dy)
2006
2007Translate Matrix by dx along the x-axis and dy along the y-axis.
2008
2009Mathematically, replace Matrix with a translation matrix
2010pre-multiplied with Matrix.
2011
2012This has the effect of moving the drawing by (dx, dy) before transforming
2013the result with Matrix.
2014
Cary Clarkbad5ad72017-08-03 17:14:08 -04002015#Param dx distance to translate in x ##
2016#Param dy distance to translate in y ##
Cary Clark8032b982017-07-28 11:04:54 -04002017
2018#Example
2019#Height 128
2020#Description
2021scale() followed by translate() produces different results from translate() followed
2022by scale().
2023
2024The blue stroke follows translate of (50, 50); a black
2025fill follows scale of (2, 1/2.f). After restoring the clip, which resets
2026Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
2027follows translate of (50, 50).
2028##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002029void draw(SkCanvas* canvas) {
2030 SkPaint filledPaint;
2031 SkPaint outlinePaint;
2032 outlinePaint.setStyle(SkPaint::kStroke_Style);
2033 outlinePaint.setColor(SK_ColorBLUE);
2034 canvas->save();
2035 canvas->translate(50, 50);
2036 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
2037 canvas->scale(2, 1/2.f);
2038 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
2039 canvas->restore();
2040 filledPaint.setColor(SK_ColorGRAY);
2041 outlinePaint.setColor(SK_ColorRED);
2042 canvas->scale(2, 1/2.f);
2043 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
2044 canvas->translate(50, 50);
2045 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04002046}
2047##
2048
2049#ToDo incomplete ##
2050
2051##
2052
2053# ------------------------------------------------------------------------------
2054
2055#Method void scale(SkScalar sx, SkScalar sy)
2056
2057Scale Matrix by sx on the x-axis and sy on the y-axis.
2058
2059Mathematically, replace Matrix with a scale matrix
2060pre-multiplied with Matrix.
2061
2062This has the effect of scaling the drawing by (sx, sy) before transforming
2063the result with Matrix.
2064
Cary Clarkbad5ad72017-08-03 17:14:08 -04002065#Param sx amount to scale in x ##
2066#Param sy amount to scale in y ##
Cary Clark8032b982017-07-28 11:04:54 -04002067
2068#Example
2069#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04002070void draw(SkCanvas* canvas) {
2071 SkPaint paint;
2072 SkRect rect = { 10, 20, 60, 120 };
2073 canvas->translate(20, 20);
2074 canvas->drawRect(rect, paint);
2075 canvas->scale(2, .5f);
2076 paint.setColor(SK_ColorGRAY);
2077 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002078}
2079##
2080
2081#ToDo incomplete ##
2082
2083##
2084
2085# ------------------------------------------------------------------------------
2086
2087#Method void rotate(SkScalar degrees)
2088
2089Rotate Matrix by degrees. Positive degrees rotates clockwise.
2090
2091Mathematically, replace Matrix with a rotation matrix
2092pre-multiplied with Matrix.
2093
2094This has the effect of rotating the drawing by degrees before transforming
2095the result with Matrix.
2096
Cary Clarkbad5ad72017-08-03 17:14:08 -04002097#Param degrees amount to rotate, in degrees ##
Cary Clark8032b982017-07-28 11:04:54 -04002098
2099#Example
2100#Description
2101Draw clock hands at time 5:10. The hour hand and minute hand point up and
2102are rotated clockwise.
2103##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002104void draw(SkCanvas* canvas) {
2105 SkPaint paint;
2106 paint.setStyle(SkPaint::kStroke_Style);
2107 canvas->translate(128, 128);
2108 canvas->drawCircle(0, 0, 60, paint);
2109 canvas->save();
2110 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
2111 canvas->drawLine(0, 0, 0, -50, paint);
2112 canvas->restore();
2113 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
2114 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002115}
2116##
2117
2118#ToDo incomplete ##
2119
2120##
2121
2122# ------------------------------------------------------------------------------
2123
2124#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
2125
Cary Clarkbad5ad72017-08-03 17:14:08 -04002126Rotate Matrix by degrees about a point at (px, py). Positive degrees rotates
2127clockwise.
Cary Clark8032b982017-07-28 11:04:54 -04002128
2129Mathematically, construct a rotation matrix. Pre-multiply the rotation matrix by
2130a translation matrix, then replace Matrix with the resulting matrix
2131pre-multiplied with Matrix.
2132
Cary Clarkbad5ad72017-08-03 17:14:08 -04002133This has the effect of rotating the drawing about a given point before
2134transforming the result with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002135
Cary Clarkbad5ad72017-08-03 17:14:08 -04002136#Param degrees amount to rotate, in degrees ##
2137#Param px x-coordinate of the point to rotate about ##
2138#Param py y-coordinate of the point to rotate about ##
Cary Clark8032b982017-07-28 11:04:54 -04002139
2140#Example
2141#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04002142void draw(SkCanvas* canvas) {
2143 SkPaint paint;
2144 paint.setTextSize(96);
2145 canvas->drawString("A1", 130, 100, paint);
2146 canvas->rotate(180, 130, 100);
2147 canvas->drawString("A1", 130, 100, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002148}
2149##
2150
2151#ToDo incomplete ##
2152
2153##
2154
2155# ------------------------------------------------------------------------------
2156
2157#Method void skew(SkScalar sx, SkScalar sy)
2158
Cary Clarkbad5ad72017-08-03 17:14:08 -04002159Skew Matrix by sx on the x-axis and sy on the y-axis. A positive value of sx
2160skews the drawing right as y increases; a positive value of sy skews the drawing
2161down as x increases.
Cary Clark8032b982017-07-28 11:04:54 -04002162
Cary Clarkbad5ad72017-08-03 17:14:08 -04002163Mathematically, replace Matrix with a skew matrix pre-multiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002164
Cary Clarkbad5ad72017-08-03 17:14:08 -04002165This has the effect of skewing the drawing by (sx, sy) before transforming
Cary Clark8032b982017-07-28 11:04:54 -04002166the result with Matrix.
2167
Cary Clarkbad5ad72017-08-03 17:14:08 -04002168#Param sx amount to skew in x ##
2169#Param sy amount to skew in y ##
2170
Cary Clark8032b982017-07-28 11:04:54 -04002171#Example
2172 #Description
2173 Black text mimics an oblique text style by using a negative skew in x that
2174 shifts the geometry to the right as the y values decrease.
2175 Red text uses a positive skew in y to shift the geometry down as the x values
2176 increase.
2177 Blue text combines x and y skew to rotate and scale.
2178 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002179 SkPaint paint;
2180 paint.setTextSize(128);
2181 canvas->translate(30, 130);
2182 canvas->save();
2183 canvas->skew(-.5, 0);
2184 canvas->drawString("A1", 0, 0, paint);
2185 canvas->restore();
2186 canvas->save();
2187 canvas->skew(0, .5);
2188 paint.setColor(SK_ColorRED);
2189 canvas->drawString("A1", 0, 0, paint);
2190 canvas->restore();
2191 canvas->skew(-.5, .5);
2192 paint.setColor(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04002193 canvas->drawString("A1", 0, 0, paint);
2194##
2195
2196#ToDo incomplete ##
2197
2198##
2199
2200# ------------------------------------------------------------------------------
2201
2202#Method void concat(const SkMatrix& matrix)
2203
Cary Clarkbad5ad72017-08-03 17:14:08 -04002204Replace Matrix with matrix pre-multiplied with existing Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002205
Cary Clarkbad5ad72017-08-03 17:14:08 -04002206This has the effect of transforming the drawn geometry by matrix, before
2207transforming the result with existing Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002208
Cary Clarkbad5ad72017-08-03 17:14:08 -04002209#Param matrix matrix to pre-multiply with existing Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04002210
2211#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002212void draw(SkCanvas* canvas) {
2213 SkPaint paint;
2214 paint.setTextSize(80);
2215 paint.setTextScaleX(.3);
2216 SkMatrix matrix;
2217 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
2218 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
2219 canvas->drawRect(rect[0], paint);
2220 canvas->drawRect(rect[1], paint);
2221 paint.setColor(SK_ColorWHITE);
2222 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
2223 canvas->concat(matrix);
2224 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002225}
2226##
2227
2228#ToDo incomplete ##
2229
2230##
2231
2232# ------------------------------------------------------------------------------
2233
2234#Method void setMatrix(const SkMatrix& matrix)
2235
2236Replace Matrix with matrix.
2237Unlike concat(), any prior matrix state is overwritten.
2238
Cary Clarkbad5ad72017-08-03 17:14:08 -04002239#Param matrix matrix to copy, replacing existing Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04002240
2241#Example
2242#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002243void draw(SkCanvas* canvas) {
2244 SkPaint paint;
2245 canvas->scale(4, 6);
2246 canvas->drawString("truth", 2, 10, paint);
2247 SkMatrix matrix;
2248 matrix.setScale(2.8f, 6);
2249 canvas->setMatrix(matrix);
2250 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002251}
2252##
2253
2254#ToDo incomplete ##
2255
2256##
2257
2258# ------------------------------------------------------------------------------
2259
2260#Method void resetMatrix()
2261
2262Sets Matrix to the identity matrix.
2263Any prior matrix state is overwritten.
2264
2265#Example
2266#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002267void draw(SkCanvas* canvas) {
2268 SkPaint paint;
2269 canvas->scale(4, 6);
2270 canvas->drawString("truth", 2, 10, paint);
2271 canvas->resetMatrix();
2272 canvas->scale(2.8f, 6);
2273 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002274}
2275##
2276
2277#ToDo incomplete ##
2278
2279##
2280
2281# ------------------------------------------------------------------------------
2282
2283#Method const SkMatrix& getTotalMatrix() const
2284
2285Returns Matrix.
2286This does not account for translation by Device or Surface.
2287
Cary Clarkbad5ad72017-08-03 17:14:08 -04002288#Return Matrix in Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04002289
2290#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002291 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
2292 #StdOut
2293 isIdentity true
2294 ##
Cary Clark8032b982017-07-28 11:04:54 -04002295##
2296
2297#ToDo incomplete ##
2298
2299##
2300
2301#Topic Matrix ##
2302
2303# ------------------------------------------------------------------------------
2304#Topic Clip
2305
2306Clip is built from a stack of clipping paths. Each Path in the
2307stack can be constructed from one or more Path_Contour elements. The
2308Path_Contour may be composed of any number of Path_Verb segments. Each
2309Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
2310by Path_Contour.
2311
2312Clip stack of Path elements successfully restrict the Path area. Each
2313Path is transformed by Matrix, then intersected with or subtracted from the
2314prior Clip to form the replacement Clip. Use SkClipOp::kDifference
2315to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
2316with Clip.
2317
2318A clipping Path may be anti-aliased; if Path, after transformation, is
2319composed of horizontal and vertical lines, clearing Anti-alias allows whole pixels
2320to either be inside or outside the clip. The fastest drawing has a aliased,
2321rectanglar clip.
2322
2323If clipping Path has Anti-alias set, clip may partially clip a pixel, requiring
2324that drawing blend partially with the destination along the edge. A rotated
2325rectangular anti-aliased clip looks smoother but draws slower.
2326
2327Clip can combine with Rect and Round_Rect primitives; like
2328Path, these are transformed by Matrix before they are combined with Clip.
2329
2330Clip can combine with Region. Region is assumed to be in Device coordinates
2331and is unaffected by Matrix.
2332
2333#Example
2334#Height 90
2335 #Description
2336 Draw a red circle with an aliased clip and an anti-aliased clip.
2337 Use an image filter to zoom into the pixels drawn.
2338 The edge of the aliased clip fully draws pixels in the red circle.
2339 The edge of the anti-aliased clip partially draws pixels in the red circle.
2340 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002341 SkPaint redPaint, scalePaint;
2342 redPaint.setAntiAlias(true);
2343 redPaint.setColor(SK_ColorRED);
2344 canvas->save();
2345 for (bool antialias : { false, true } ) {
2346 canvas->save();
2347 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
2348 canvas->drawCircle(17, 11, 8, redPaint);
2349 canvas->restore();
2350 canvas->translate(16, 0);
2351 }
2352 canvas->restore();
2353 SkMatrix matrix;
2354 matrix.setScale(6, 6);
2355 scalePaint.setImageFilter(
2356 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
2357 SkCanvas::SaveLayerRec saveLayerRec(
2358 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
2359 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04002360 canvas->restore();
2361##
2362
2363#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
2364
2365Replace Clip with the intersection or difference of Clip and rect,
2366with an aliased or anti-aliased clip edge. rect is transformed by Matrix
2367before it is combined with Clip.
2368
Cary Clarka523d2d2017-08-30 08:58:10 -04002369#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002370#Param op Clip_Op to apply to Clip ##
2371#Param doAntiAlias true if Clip is to be anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002372
2373#Example
2374#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002375void draw(SkCanvas* canvas) {
2376 canvas->rotate(10);
2377 SkPaint paint;
2378 paint.setAntiAlias(true);
2379 for (auto alias: { false, true } ) {
2380 canvas->save();
2381 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
2382 canvas->drawCircle(100, 60, 60, paint);
2383 canvas->restore();
2384 canvas->translate(80, 0);
2385 }
Cary Clark8032b982017-07-28 11:04:54 -04002386}
2387##
2388
2389#ToDo incomplete ##
2390
2391##
2392
2393#Method void clipRect(const SkRect& rect, SkClipOp op)
2394
2395Replace Clip with the intersection or difference of Clip and rect.
2396Resulting Clip is aliased; pixels are fully contained by the clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002397rect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002398
Cary Clarka523d2d2017-08-30 08:58:10 -04002399#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002400#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002401
2402#Example
2403#Height 192
2404#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04002405void draw(SkCanvas* canvas) {
2406 SkPaint paint;
2407 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
2408 canvas->save();
2409 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
2410 canvas->drawCircle(100, 100, 60, paint);
2411 canvas->restore();
2412 canvas->translate(80, 0);
2413 }
Cary Clark8032b982017-07-28 11:04:54 -04002414}
2415##
2416
2417#ToDo incomplete ##
2418
2419##
2420
2421#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
2422
2423Replace Clip with the intersection of Clip and rect.
2424Resulting Clip is aliased; pixels are fully contained by the clip.
2425rect is transformed by Matrix
2426before it is combined with Clip.
2427
Cary Clarka523d2d2017-08-30 08:58:10 -04002428#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002429#Param doAntiAlias true if Clip is to be anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002430
2431#Example
2432#Height 133
2433 #Description
2434 A circle drawn in pieces looks uniform when drawn aliased.
2435 The same circle pieces blend with pixels more than once when anti-aliased,
2436 visible as a thin pair of lines through the right circle.
2437 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002438void draw(SkCanvas* canvas) {
2439 canvas->clear(SK_ColorWHITE);
2440 SkPaint paint;
2441 paint.setAntiAlias(true);
2442 paint.setColor(0x8055aaff);
2443 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
2444 for (auto alias: { false, true } ) {
2445 canvas->save();
2446 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
2447 canvas->drawCircle(67, 67, 60, paint);
2448 canvas->restore();
2449 canvas->save();
2450 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
2451 canvas->drawCircle(67, 67, 60, paint);
2452 canvas->restore();
2453 canvas->translate(120, 0);
2454 }
Cary Clark8032b982017-07-28 11:04:54 -04002455}
2456##
2457
2458#ToDo incomplete ##
2459
2460##
2461
2462#Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect)
2463
2464Sets the max clip rectangle, which can be set by clipRect, clipRRect and
2465clipPath and intersect the current clip with the specified rect.
2466The max clip affects only future ops (it is not retroactive).
2467The clip restriction is not recorded in pictures.
2468
Cary Clarkbad5ad72017-08-03 17:14:08 -04002469Pass an empty rect to disable max clip.
2470
Cary Clark8032b982017-07-28 11:04:54 -04002471#Private
2472This is private API to be used only by Android framework.
2473##
2474
Cary Clarkbad5ad72017-08-03 17:14:08 -04002475#Param rect maximum allowed clip in device coordinates
Cary Clark579985c2017-07-31 11:48:27 -04002476#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04002477
2478##
2479
2480#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
2481
2482Replace Clip with the intersection or difference of Clip and rrect,
2483with an aliased or anti-aliased clip edge.
2484rrect is transformed by Matrix
2485before it is combined with Clip.
2486
Cary Clarkbad5ad72017-08-03 17:14:08 -04002487#Param rrect Round_Rect to combine with Clip ##
2488#Param op Clip_Op to apply to Clip ##
2489#Param doAntiAlias true if Clip is to be antialiased ##
Cary Clark8032b982017-07-28 11:04:54 -04002490
2491#Example
2492#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002493void draw(SkCanvas* canvas) {
2494 canvas->clear(SK_ColorWHITE);
2495 SkPaint paint;
2496 paint.setAntiAlias(true);
2497 paint.setColor(0x8055aaff);
2498 SkRRect oval;
2499 oval.setOval({10, 20, 90, 100});
2500 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
2501 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002502}
2503##
2504
2505#ToDo incomplete ##
2506
2507##
2508
2509#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
2510
2511Replace Clip with the intersection or difference of Clip and rrect.
2512Resulting Clip is aliased; pixels are fully contained by the clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002513rrect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002514
Cary Clarkbad5ad72017-08-03 17:14:08 -04002515#Param rrect Round_Rect to combine with Clip ##
2516#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002517
2518#Example
2519#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002520void draw(SkCanvas* canvas) {
2521 SkPaint paint;
2522 paint.setColor(0x8055aaff);
2523 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
2524 canvas->clipRRect(oval, SkClipOp::kIntersect);
2525 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002526}
2527##
2528
2529#ToDo incomplete ##
2530
2531##
2532
2533#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
2534
2535Replace Clip with the intersection of Clip and rrect,
2536with an aliased or anti-aliased clip edge.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002537rrect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002538
Cary Clarkbad5ad72017-08-03 17:14:08 -04002539#Param rrect Round_Rect to combine with Clip ##
2540#Param doAntiAlias true if Clip is to be antialiased ##
Cary Clark8032b982017-07-28 11:04:54 -04002541
2542#Example
2543#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002544void draw(SkCanvas* canvas) {
2545 SkPaint paint;
2546 paint.setAntiAlias(true);
2547 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
2548 canvas->clipRRect(oval, true);
2549 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002550}
2551##
2552
2553#ToDo incomplete ##
2554
2555##
2556
2557#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
2558
2559Replace Clip with the intersection or difference of Clip and path,
2560with an aliased or anti-aliased clip edge. Path_Fill_Type determines if path
2561describes the area inside or outside its contours; and if Path_Contour overlaps
2562itself or another Path_Contour, whether the overlaps form part of the area.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002563path is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002564
Cary Clarkbad5ad72017-08-03 17:14:08 -04002565#Param path Path to combine with Clip ##
2566#Param op Clip_Op to apply to Clip ##
2567#Param doAntiAlias true if Clip is to be antialiased ##
Cary Clark8032b982017-07-28 11:04:54 -04002568
2569#Example
2570#Description
2571Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
2572area outside clip is subtracted from circle.
2573
2574Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
2575area inside clip is intersected with circle.
2576##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002577void draw(SkCanvas* canvas) {
2578 SkPaint paint;
2579 paint.setAntiAlias(true);
2580 SkPath path;
2581 path.addRect({20, 30, 100, 110});
2582 path.setFillType(SkPath::kInverseWinding_FillType);
2583 canvas->save();
2584 canvas->clipPath(path, SkClipOp::kDifference, false);
2585 canvas->drawCircle(70, 100, 60, paint);
2586 canvas->restore();
2587 canvas->translate(100, 100);
2588 path.setFillType(SkPath::kWinding_FillType);
2589 canvas->clipPath(path, SkClipOp::kIntersect, false);
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)
2599
2600Replace Clip with the intersection or difference of Clip and path.
2601Resulting Clip is aliased; pixels are fully contained by the clip.
2602Path_Fill_Type determines if path
2603describes the area inside or outside its contours; and if Path_Contour overlaps
2604itself or another Path_Contour, whether the overlaps form part of the area.
2605path is transformed by Matrix
2606before it is combined with Clip.
2607
Cary Clarkbad5ad72017-08-03 17:14:08 -04002608#Param path Path to combine with Clip ##
2609#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002610
2611#Example
2612#Description
2613Overlapping Rects form a clip. When clip's Path_Fill_Type is set to
2614SkPath::kWinding_FillType, the overlap is included. Set to
2615SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2616##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002617void draw(SkCanvas* canvas) {
2618 SkPaint paint;
2619 paint.setAntiAlias(true);
2620 SkPath path;
2621 path.addRect({20, 15, 100, 95});
2622 path.addRect({50, 65, 130, 135});
2623 path.setFillType(SkPath::kWinding_FillType);
2624 canvas->save();
2625 canvas->clipPath(path, SkClipOp::kIntersect);
2626 canvas->drawCircle(70, 85, 60, paint);
2627 canvas->restore();
2628 canvas->translate(100, 100);
2629 path.setFillType(SkPath::kEvenOdd_FillType);
2630 canvas->clipPath(path, SkClipOp::kIntersect);
2631 canvas->drawCircle(70, 85, 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, bool doAntiAlias = false)
2640
2641Replace Clip with the intersection of Clip and path.
2642Resulting Clip is aliased; pixels are fully contained by the clip.
2643Path_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.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002646path is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002647
Cary Clarkbad5ad72017-08-03 17:14:08 -04002648#Param path Path to combine with Clip ##
2649#Param doAntiAlias true if Clip is to be antialiased ##
Cary Clark8032b982017-07-28 11:04:54 -04002650
2651#Example
2652#Height 212
2653#Description
2654Clip loops over itself covering its center twice. When clip's Path_Fill_Type
2655is set to SkPath::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 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2663 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2664 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2665 path.setFillType(SkPath::kWinding_FillType);
2666 canvas->save();
2667 canvas->clipPath(path, SkClipOp::kIntersect);
2668 canvas->drawCircle(50, 50, 45, paint);
2669 canvas->restore();
2670 canvas->translate(100, 100);
2671 path.setFillType(SkPath::kEvenOdd_FillType);
2672 canvas->clipPath(path, SkClipOp::kIntersect);
2673 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002674}
2675##
2676
2677#ToDo incomplete ##
2678
2679##
2680
2681# ------------------------------------------------------------------------------
2682
2683#Method void setAllowSimplifyClip(bool allow)
2684
2685#Experimental
2686Only used for testing.
2687##
2688
2689Set to simplify clip stack using path ops.
2690
2691##
2692
2693# ------------------------------------------------------------------------------
2694
2695#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2696
2697Replace Clip with the intersection or difference of Clip and Region deviceRgn.
2698Resulting Clip is aliased; pixels are fully contained by the clip.
2699deviceRgn is unaffected by Matrix.
2700
Cary Clarkbad5ad72017-08-03 17:14:08 -04002701#Param deviceRgn Region to combine with Clip ##
2702#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002703
2704#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002705#Description
2706 region is unaffected by canvas rotation; rect is affected by canvas rotation.
2707 Both clips are aliased; this is unnoticable on Region clip because it
2708 aligns to pixel boundaries.
2709##
2710void draw(SkCanvas* canvas) {
2711 SkPaint paint;
2712 paint.setAntiAlias(true);
2713 SkIRect iRect = {30, 40, 120, 130 };
2714 SkRegion region(iRect);
2715 canvas->rotate(10);
2716 canvas->save();
2717 canvas->clipRegion(region, SkClipOp::kIntersect);
2718 canvas->drawCircle(50, 50, 45, paint);
2719 canvas->restore();
2720 canvas->translate(100, 100);
2721 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2722 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002723}
2724##
2725
2726#ToDo incomplete ##
2727
2728##
2729
2730#Method bool quickReject(const SkRect& rect) const
2731
2732Return true if Rect rect, transformed by Matrix, can be quickly determined to be
2733outside of Clip. May return false even though rect is outside of Clip.
2734
2735Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2736
Cary Clarkbad5ad72017-08-03 17:14:08 -04002737#Param rect Rect to compare with Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002738
Cary Clarkbad5ad72017-08-03 17:14:08 -04002739#Return true if rect, transformed by Matrix, does not intersect Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002740
2741#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002742void draw(SkCanvas* canvas) {
2743 SkRect testRect = {30, 30, 120, 129 };
2744 SkRect clipRect = {30, 130, 120, 230 };
2745 canvas->save();
2746 canvas->clipRect(clipRect);
2747 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2748 canvas->restore();
2749 canvas->rotate(10);
2750 canvas->clipRect(clipRect);
2751 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002752}
2753 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002754 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002755 quickReject false
2756 ##
2757##
2758
2759#ToDo incomplete ##
2760
2761##
2762
2763#Method bool quickReject(const SkPath& path) const
2764
2765Return true if path, transformed by Matrix, can be quickly determined to be
2766outside of Clip. May return false even though path is outside of Clip.
2767
2768Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2769
Cary Clarkbad5ad72017-08-03 17:14:08 -04002770#Param path Path to compare with Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002771
Cary Clarkbad5ad72017-08-03 17:14:08 -04002772#Return true if path, transformed by Matrix, does not intersect Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002773
2774#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002775void draw(SkCanvas* canvas) {
2776 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2777 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2778 SkPath testPath, clipPath;
2779 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2780 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2781 canvas->save();
2782 canvas->clipPath(clipPath);
2783 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2784 canvas->restore();
2785 canvas->rotate(10);
2786 canvas->clipPath(clipPath);
2787 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002788 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002789 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002790 quickReject false
2791 ##
2792}
2793##
2794
2795#ToDo incomplete ##
2796
2797##
2798
2799#Method SkRect getLocalClipBounds() const
2800
2801Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2802return SkRect::MakeEmpty, where all Rect sides equal zero.
2803
2804Rect returned is outset by one to account for partial pixel coverage if Clip
2805is anti-aliased.
2806
Cary Clarkbad5ad72017-08-03 17:14:08 -04002807#Return bounds of Clip in local coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002808
2809#Example
2810 #Description
2811 Initial bounds is device bounds outset by 1 on all sides.
2812 Clipped bounds is clipPath bounds outset by 1 on all sides.
2813 Scaling the canvas by two in x and y scales the local bounds by 1/2 in x and y.
2814 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002815 SkCanvas local(256, 256);
2816 canvas = &local;
2817 SkRect bounds = canvas->getLocalClipBounds();
2818 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2819 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2820 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2821 SkPath clipPath;
2822 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2823 canvas->clipPath(clipPath);
2824 bounds = canvas->getLocalClipBounds();
2825 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2826 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2827 canvas->scale(2, 2);
2828 bounds = canvas->getLocalClipBounds();
2829 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2830 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2831 #StdOut
2832 left:-1 top:-1 right:257 bottom:257
2833 left:29 top:129 right:121 bottom:231
2834 left:14.5 top:64.5 right:60.5 bottom:115.5
2835 ##
Cary Clark8032b982017-07-28 11:04:54 -04002836##
2837
2838# local canvas in example works around bug in fiddle ##
2839#Bug 6524 ##
2840
2841##
2842
2843#Method bool getLocalClipBounds(SkRect* bounds) const
2844
2845Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2846return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2847
2848bounds is outset by one to account for partial pixel coverage if Clip
2849is anti-aliased.
2850
Cary Clarkbad5ad72017-08-03 17:14:08 -04002851#Param bounds Rect of Clip in local coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002852
Cary Clarkbad5ad72017-08-03 17:14:08 -04002853#Return true if Clip bounds is not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04002854
2855#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002856 void draw(SkCanvas* canvas) {
2857 SkCanvas local(256, 256);
2858 canvas = &local;
2859 SkRect bounds;
2860 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2861 ? "false" : "true");
2862 SkPath path;
2863 canvas->clipPath(path);
2864 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2865 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002866 }
2867 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002868 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002869 local bounds empty = true
2870 ##
2871##
2872
2873# local canvas in example works around bug in fiddle ##
2874#Bug 6524 ##
2875
2876##
2877
2878#Method SkIRect getDeviceClipBounds() const
2879
2880Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2881return SkRect::MakeEmpty, where all Rect sides equal zero.
2882
2883Unlike getLocalClipBounds, returned IRect is not outset.
2884
Cary Clarkbad5ad72017-08-03 17:14:08 -04002885#Return bounds of Clip in Device coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002886
2887#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002888void draw(SkCanvas* canvas) {
2889 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002890 Initial bounds is device bounds, not outset.
2891 Clipped bounds is clipPath bounds, not outset.
2892 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 -04002893 ##
2894 SkCanvas device(256, 256);
2895 canvas = &device;
2896 SkIRect bounds = canvas->getDeviceClipBounds();
2897 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2898 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2899 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2900 SkPath clipPath;
2901 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2902 canvas->save();
2903 canvas->clipPath(clipPath);
2904 bounds = canvas->getDeviceClipBounds();
2905 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2906 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2907 canvas->restore();
2908 canvas->scale(1.f/2, 1.f/2);
2909 canvas->clipPath(clipPath);
2910 bounds = canvas->getDeviceClipBounds();
2911 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2912 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002913 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002914 left:0 top:0 right:256 bottom:256
2915 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002916 left:15 top:65 right:60 bottom:115
2917 ##
2918}
2919##
2920
2921#ToDo some confusion on why with an identity Matrix local and device are different ##
2922
2923# device canvas in example works around bug in fiddle ##
2924#Bug 6524 ##
2925
2926##
2927
2928#Method bool getDeviceClipBounds(SkIRect* bounds) const
2929
2930Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2931return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2932
2933Unlike getLocalClipBounds, bounds is not outset.
2934
Cary Clarkbad5ad72017-08-03 17:14:08 -04002935#Param bounds Rect of Clip in device coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002936
Cary Clarkbad5ad72017-08-03 17:14:08 -04002937#Return true if Clip bounds is not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04002938
2939#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002940 void draw(SkCanvas* canvas) {
2941 SkIRect bounds;
2942 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2943 ? "false" : "true");
2944 SkPath path;
2945 canvas->clipPath(path);
2946 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2947 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002948 }
2949 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002950 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002951 device bounds empty = true
2952 ##
2953##
2954
2955#ToDo incomplete ##
2956
2957##
2958
2959#Topic Clip ##
2960
2961# ------------------------------------------------------------------------------
2962
2963#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
2964
2965Fill Clip with Color color.
2966mode determines how Color_ARGB is combined with destination.
2967
Cary Clarkbad5ad72017-08-03 17:14:08 -04002968#Param color Unpremultiplied Color_ARGB ##
2969#Param mode SkBlendMode used to combine source color and destination ##
Cary Clark8032b982017-07-28 11:04:54 -04002970
2971#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002972 canvas->drawColor(SK_ColorRED);
2973 canvas->clipRect(SkRect::MakeWH(150, 150));
2974 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
2975 canvas->clipRect(SkRect::MakeWH(75, 75));
2976 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04002977##
2978
2979#ToDo incomplete ##
2980
2981##
2982
2983# ------------------------------------------------------------------------------
2984
2985#Method void clear(SkColor color)
2986
2987Fill Clip with Color color using SkBlendMode::kSrc.
2988This has the effect of replacing all pixels contained by Clip with color.
2989
Cary Clarkbad5ad72017-08-03 17:14:08 -04002990#Param color Unpremultiplied Color_ARGB ##
Cary Clark8032b982017-07-28 11:04:54 -04002991
2992#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002993void draw(SkCanvas* canvas) {
2994 canvas->save();
2995 canvas->clipRect(SkRect::MakeWH(256, 128));
2996 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
2997 canvas->restore();
2998 canvas->save();
2999 canvas->clipRect(SkRect::MakeWH(150, 192));
3000 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
3001 canvas->restore();
3002 canvas->clipRect(SkRect::MakeWH(75, 256));
3003 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04003004}
3005##
3006
3007#ToDo incomplete ##
3008
3009##
3010
3011# ------------------------------------------------------------------------------
3012
3013#Method void discard()
3014
3015Make Canvas contents undefined. Subsequent calls that read Canvas pixels,
3016such as drawing with SkBlendMode, return undefined results. discard() does
3017not change Clip or Matrix.
3018
3019discard() may do nothing, depending on the implementation of Surface or Device
3020that created Canvas.
3021
3022discard() allows optimized performance on subsequent draws by removing
3023cached data associated with Surface or Device.
3024It is not necessary to call discard() once done with Canvas;
3025any cached data is deleted when owning Surface or Device is deleted.
3026
3027#ToDo example? not sure how to make this meaningful w/o more implementation detail ##
3028
3029#NoExample
3030##
3031
3032##
3033
3034# ------------------------------------------------------------------------------
3035
3036#Method void drawPaint(const SkPaint& paint)
3037
Cary Clarkbad5ad72017-08-03 17:14:08 -04003038Fill Clip with Paint paint. Paint components Rasterizer, Mask_Filter, Shader,
3039Color_Filter, Image_Filter, and Blend_Mode affect drawing;
3040Path_Effect in paint is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04003041
3042# can Path_Effect in paint ever alter drawPaint?
3043
Cary Clarkbad5ad72017-08-03 17:14:08 -04003044#Param paint graphics state used to fill Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04003045
3046#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003047void draw(SkCanvas* canvas) {
3048 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
3049 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
3050 SkPaint paint;
3051 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
3052 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04003053}
3054##
3055
3056#ToDo incomplete ##
3057
3058##
3059
3060# ------------------------------------------------------------------------------
3061
3062#Enum PointMode
3063
3064#Code
3065 enum PointMode {
3066 kPoints_PointMode,
3067 kLines_PointMode,
3068 kPolygon_PointMode
3069 };
3070##
3071
3072Selects if an array of points are drawn as discrete points, as lines, or as
3073an open polygon.
3074
3075#Const kPoints_PointMode 0
3076 Draw each point separately.
3077##
3078
3079#Const kLines_PointMode 1
3080 Draw each pair of points as a line segment.
3081##
3082
3083#Const kPolygon_PointMode 2
3084 Draw the array of points as a open polygon.
3085##
3086
3087#Example
3088 #Description
3089 The upper left corner shows three squares when drawn as points.
3090 The upper right corner shows one line; when drawn as lines, two points are required per line.
3091 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
3092 The lower left corner shows two lines with a miter when path contains polygon.
3093 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003094void draw(SkCanvas* canvas) {
3095 SkPaint paint;
3096 paint.setStyle(SkPaint::kStroke_Style);
3097 paint.setStrokeWidth(10);
3098 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
3099 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
3100 canvas->translate(128, 0);
3101 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
3102 canvas->translate(0, 128);
3103 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
3104 SkPath path;
3105 path.addPoly(points, 3, false);
3106 canvas->translate(-128, 0);
3107 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003108}
3109##
3110
3111#ToDo incomplete ##
3112
3113##
3114
3115# ------------------------------------------------------------------------------
3116
3117#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
3118
3119Draw pts using Clip, Matrix and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003120count is the number of points; if count is less than one, has no effect.
Cary Clark8032b982017-07-28 11:04:54 -04003121mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
3122
Cary Clarkbad5ad72017-08-03 17:14:08 -04003123If mode is kPoints_PointMode, the shape of point drawn depends on paint
3124Paint_Stroke_Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
3125circle of diameter Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap
3126or SkPaint::kButt_Cap, each point draws a square of width and height
3127Paint_Stroke_Width.
Cary Clark8032b982017-07-28 11:04:54 -04003128
3129If mode is kLines_PointMode, each pair of points draws a line segment.
3130One line is drawn for every two points; each point is used once. If count is odd,
3131the final point is ignored.
3132
3133If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
3134count minus one lines are drawn; the first and last point are used once.
3135
3136Each line segment respects paint Paint_Stroke_Cap and Paint_Stroke_Width.
3137Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3138
Cary Clarkbad5ad72017-08-03 17:14:08 -04003139Always draws each element one at a time; is not affected by
3140Paint_Stroke_Join, and unlike drawPath, does not create a mask from all points
3141and lines before drawing.
Cary Clark8032b982017-07-28 11:04:54 -04003142
Cary Clarka523d2d2017-08-30 08:58:10 -04003143#Param mode whether pts draws points or lines ##
3144#Param count number of points in the array ##
3145#Param pts array of points to draw ##
3146#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003147
3148#Example
3149#Height 200
3150 #Description
3151 #List
3152 # The first column draws points. ##
3153 # The second column draws points as lines. ##
3154 # The third column draws points as a polygon. ##
3155 # The fourth column draws points as a polygonal path. ##
3156 # The first row uses a round cap and round join. ##
3157 # The second row uses a square cap and a miter join. ##
3158 # The third row uses a butt cap and a bevel join. ##
3159 ##
3160 The transparent color makes multiple line draws visible;
3161 the path is drawn all at once.
3162 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003163void draw(SkCanvas* canvas) {
3164 SkPaint paint;
3165 paint.setAntiAlias(true);
3166 paint.setStyle(SkPaint::kStroke_Style);
3167 paint.setStrokeWidth(10);
3168 paint.setColor(0x80349a45);
3169 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
3170 const SkPaint::Join join[] = { SkPaint::kRound_Join,
3171 SkPaint::kMiter_Join,
3172 SkPaint::kBevel_Join };
3173 int joinIndex = 0;
3174 SkPath path;
3175 path.addPoly(points, 3, false);
3176 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
3177 paint.setStrokeCap(cap);
3178 paint.setStrokeJoin(join[joinIndex++]);
3179 for (const auto mode : { SkCanvas::kPoints_PointMode,
3180 SkCanvas::kLines_PointMode,
3181 SkCanvas::kPolygon_PointMode } ) {
3182 canvas->drawPoints(mode, 3, points, paint);
3183 canvas->translate(64, 0);
3184 }
3185 canvas->drawPath(path, paint);
3186 canvas->translate(-192, 64);
3187 }
Cary Clark8032b982017-07-28 11:04:54 -04003188}
3189##
3190
3191#ToDo incomplete ##
3192
3193##
3194
3195# ------------------------------------------------------------------------------
3196
3197#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
3198
3199Draw point at (x, y) using Clip, Matrix and Paint paint.
3200
3201The shape of point drawn depends on paint Paint_Stroke_Cap.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003202If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
3203Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04003204draw a square of width and height Paint_Stroke_Width.
3205Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3206
Cary Clarkbad5ad72017-08-03 17:14:08 -04003207#Param x left edge of circle or square ##
3208#Param y top edge of circle or square ##
3209#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003210
3211#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003212void draw(SkCanvas* canvas) {
3213 SkPaint paint;
3214 paint.setAntiAlias(true);
3215 paint.setColor(0x80349a45);
3216 paint.setStyle(SkPaint::kStroke_Style);
3217 paint.setStrokeWidth(100);
3218 paint.setStrokeCap(SkPaint::kRound_Cap);
3219 canvas->scale(1, 1.2f);
3220 canvas->drawPoint(64, 96, paint);
3221 canvas->scale(.6f, .8f);
3222 paint.setColor(SK_ColorWHITE);
3223 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003224}
3225##
3226
3227#ToDo incomplete ##
3228
3229##
3230
Cary Clarkbad5ad72017-08-03 17:14:08 -04003231#Method void drawPoint(SkPoint p, const SkPaint& paint)
3232
3233Draw point p using Clip, Matrix and Paint paint.
3234
3235The shape of point drawn depends on paint Paint_Stroke_Cap.
3236If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
3237Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
3238draw a square of width and height Paint_Stroke_Width.
3239Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3240
3241#Param p top-left edge of circle or square ##
3242#Param paint stroke, blend, color, and so on, used to draw ##
3243
3244#Example
3245void draw(SkCanvas* canvas) {
3246 SkPaint paint;
3247 paint.setAntiAlias(true);
3248 paint.setColor(0x80349a45);
3249 paint.setStyle(SkPaint::kStroke_Style);
3250 paint.setStrokeWidth(100);
3251 paint.setStrokeCap(SkPaint::kSquare_Cap);
3252 canvas->scale(1, 1.2f);
3253 canvas->drawPoint({64, 96}, paint);
3254 canvas->scale(.6f, .8f);
3255 paint.setColor(SK_ColorWHITE);
3256 canvas->drawPoint(106, 120, paint);
3257}
3258##
3259
3260#SeeAlso drawPoints drawCircle drawRect
3261
3262##
3263
Cary Clark8032b982017-07-28 11:04:54 -04003264# ------------------------------------------------------------------------------
3265
3266#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
3267
Cary Clarkbad5ad72017-08-03 17:14:08 -04003268Draws line segment from (x0, y0) to (x1, y1) using Clip, Matrix, and Paint paint.
3269In paint: Paint_Stroke_Width describes the line thickness;
3270Paint_Stroke_Cap draws the end rounded or square;
Cary Clark8032b982017-07-28 11:04:54 -04003271Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3272
Cary Clarkbad5ad72017-08-03 17:14:08 -04003273#Param x0 start of line segment on x-axis ##
3274#Param y0 start of line segment on y-axis ##
3275#Param x1 end of line segment on x-axis ##
3276#Param y1 end of line segment on y-axis ##
3277#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003278
3279#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003280 SkPaint paint;
3281 paint.setAntiAlias(true);
3282 paint.setColor(0xFF9a67be);
3283 paint.setStrokeWidth(20);
3284 canvas->skew(1, 0);
3285 canvas->drawLine(32, 96, 32, 160, paint);
3286 canvas->skew(-2, 0);
3287 canvas->drawLine(288, 96, 288, 160, paint);
3288##
3289
3290#ToDo incomplete ##
3291
3292##
3293
3294#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
3295
3296Draws line segment from p0 to p1 using Clip, Matrix, and Paint paint.
3297In paint: Paint_Stroke_Width describes the line thickness;
3298Paint_Stroke_Cap draws the end rounded or square;
3299Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3300
3301#Param p0 start of line segment ##
3302#Param p1 end of line segment ##
3303#Param paint stroke, blend, color, and so on, used to draw ##
3304
3305#Example
3306 SkPaint paint;
3307 paint.setAntiAlias(true);
3308 paint.setColor(0xFF9a67be);
3309 paint.setStrokeWidth(20);
3310 canvas->skew(1, 0);
3311 canvas->drawLine({32, 96}, {32, 160}, paint);
3312 canvas->skew(-2, 0);
3313 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003314##
3315
3316#ToDo incomplete ##
3317
3318##
3319
3320# ------------------------------------------------------------------------------
3321
3322#Method void drawRect(const SkRect& rect, const SkPaint& paint)
3323
3324Draw Rect rect using Clip, Matrix, and Paint paint.
3325In paint: Paint_Style determines if rectangle is stroked or filled;
3326if stroked, Paint_Stroke_Width describes the line thickness, and
3327Paint_Stroke_Join draws the corners rounded or square.
3328
Cary Clarkbad5ad72017-08-03 17:14:08 -04003329#Param rect rectangle to be drawn ##
3330#Param paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003331
3332#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003333void draw(SkCanvas* canvas) {
3334 SkPoint rectPts[] = { {64, 48}, {192, 160} };
3335 SkPaint paint;
3336 paint.setAntiAlias(true);
3337 paint.setStyle(SkPaint::kStroke_Style);
3338 paint.setStrokeWidth(20);
3339 paint.setStrokeJoin(SkPaint::kRound_Join);
3340 SkMatrix rotator;
3341 rotator.setRotate(30, 128, 128);
3342 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3343 paint.setColor(color);
3344 SkRect rect;
3345 rect.set(rectPts[0], rectPts[1]);
3346 canvas->drawRect(rect, paint);
3347 rotator.mapPoints(rectPts, 2);
3348 }
Cary Clark8032b982017-07-28 11:04:54 -04003349}
3350##
3351
3352#ToDo incomplete ##
3353
3354##
3355
3356# ------------------------------------------------------------------------------
3357
3358#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
3359
3360Draw IRect rect using Clip, Matrix, and Paint paint.
3361In paint: Paint_Style determines if rectangle is stroked or filled;
3362if stroked, Paint_Stroke_Width describes the line thickness, and
3363Paint_Stroke_Join draws the corners rounded or square.
3364
Cary Clarkbad5ad72017-08-03 17:14:08 -04003365#Param rect rectangle to be drawn ##
3366#Param paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003367
3368#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003369 SkIRect rect = { 64, 48, 192, 160 };
3370 SkPaint paint;
3371 paint.setAntiAlias(true);
3372 paint.setStyle(SkPaint::kStroke_Style);
3373 paint.setStrokeWidth(20);
3374 paint.setStrokeJoin(SkPaint::kRound_Join);
3375 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3376 paint.setColor(color);
3377 canvas->drawIRect(rect, paint);
3378 canvas->rotate(30, 128, 128);
3379 }
Cary Clark8032b982017-07-28 11:04:54 -04003380##
3381
3382#ToDo incomplete ##
3383
3384##
3385
3386# ------------------------------------------------------------------------------
3387
3388#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
3389
3390Draw Region region using Clip, Matrix, and Paint paint.
3391In paint: Paint_Style determines if rectangle is stroked or filled;
3392if stroked, Paint_Stroke_Width describes the line thickness, and
3393Paint_Stroke_Join draws the corners rounded or square.
3394
Cary Clarkbad5ad72017-08-03 17:14:08 -04003395#Param region region to be drawn ##
3396#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003397
3398#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003399void draw(SkCanvas* canvas) {
3400 SkRegion region;
3401 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3402 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3403 SkPaint paint;
3404 paint.setAntiAlias(true);
3405 paint.setStyle(SkPaint::kStroke_Style);
3406 paint.setStrokeWidth(20);
3407 paint.setStrokeJoin(SkPaint::kRound_Join);
3408 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003409}
3410##
3411
3412#ToDo incomplete ##
3413
3414##
3415
3416# ------------------------------------------------------------------------------
3417
3418#Method void drawOval(const SkRect& oval, const SkPaint& paint)
3419
3420Draw Oval oval using Clip, Matrix, and Paint.
3421In paint: Paint_Style determines if Oval is stroked or filled;
3422if stroked, Paint_Stroke_Width describes the line thickness.
3423
Cary Clarkbad5ad72017-08-03 17:14:08 -04003424#Param oval Rect bounds of Oval ##
3425#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003426
3427#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003428void draw(SkCanvas* canvas) {
3429 canvas->clear(0xFF3f5f9f);
3430 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
3431 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
3432 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
3433 SkScalar pos[] = { 0.2f, 1.0f };
3434 SkRect bounds = SkRect::MakeWH(80, 70);
3435 SkPaint paint;
3436 paint.setAntiAlias(true);
3437 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
3438 SkShader::kClamp_TileMode));
3439 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04003440}
3441##
3442
3443#ToDo incomplete ##
3444
3445##
3446
3447# ------------------------------------------------------------------------------
3448
3449#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
3450
3451Draw Round_Rect rrect using Clip, Matrix, and Paint paint.
3452In paint: Paint_Style determines if rrect is stroked or filled;
3453if stroked, Paint_Stroke_Width describes the line thickness.
3454
Cary Clarkbad5ad72017-08-03 17:14:08 -04003455rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
3456may have any combination of positive non-square radii for the four corners.
Cary Clark8032b982017-07-28 11:04:54 -04003457
Cary Clarkbad5ad72017-08-03 17:14:08 -04003458#Param rrect Round_Rect with up to eight corner radii to draw ##
3459#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003460
3461#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003462void draw(SkCanvas* canvas) {
3463 SkPaint paint;
3464 paint.setAntiAlias(true);
3465 SkRect outer = {30, 40, 210, 220};
3466 SkRect radii = {30, 50, 70, 90 };
3467 SkRRect rRect;
3468 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
3469 canvas->drawRRect(rRect, paint);
3470 paint.setColor(SK_ColorWHITE);
3471 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
3472 outer.fLeft + radii.fLeft, outer.fBottom, paint);
3473 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
3474 outer.fRight - radii.fRight, outer.fBottom, paint);
3475 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
3476 outer.fRight, outer.fTop + radii.fTop, paint);
3477 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
3478 outer.fRight, outer.fBottom - radii.fBottom, paint);
3479}
Cary Clark8032b982017-07-28 11:04:54 -04003480##
3481
3482#ToDo incomplete ##
3483
3484##
3485
3486# ------------------------------------------------------------------------------
3487
3488#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
3489
3490Draw Round_Rect outer and inner
3491using Clip, Matrix, and Paint paint.
3492outer must contain inner or the drawing is undefined.
3493In paint: Paint_Style determines if rrect is stroked or filled;
3494if stroked, Paint_Stroke_Width describes the line thickness.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003495If stroked and Round_Rect corner has zero length radii, Paint_Stroke_Join can
3496draw corners rounded or square.
Cary Clark8032b982017-07-28 11:04:54 -04003497
Cary Clarkbad5ad72017-08-03 17:14:08 -04003498GPU-backed platforms optimize drawing when both outer and inner are
Cary Clark8032b982017-07-28 11:04:54 -04003499concave and outer contains inner. These platforms may not be able to draw
3500Path built with identical data as fast.
3501
Cary Clarkbad5ad72017-08-03 17:14:08 -04003502#Param outer Round_Rect outer bounds to draw ##
3503#Param inner Round_Rect inner bounds to draw ##
3504#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003505
3506#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003507void draw(SkCanvas* canvas) {
3508 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3509 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
3510 SkPaint paint;
3511 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003512}
3513##
3514
3515#Example
3516#Description
3517 Outer Rect has no corner radii, but stroke join is rounded.
3518 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
3519 Stroke join does not affect inner Round_Rect since it has no sharp corners.
3520##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003521void draw(SkCanvas* canvas) {
3522 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3523 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
3524 SkPaint paint;
3525 paint.setAntiAlias(true);
3526 paint.setStyle(SkPaint::kStroke_Style);
3527 paint.setStrokeWidth(20);
3528 paint.setStrokeJoin(SkPaint::kRound_Join);
3529 canvas->drawDRRect(outer, inner, paint);
3530 paint.setStrokeWidth(1);
3531 paint.setColor(SK_ColorWHITE);
3532 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003533}
3534##
3535
3536#ToDo incomplete ##
3537
3538##
3539
3540# ------------------------------------------------------------------------------
3541
3542#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
3543
3544Draw Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint.
3545If radius is zero or less, nothing is drawn.
3546In paint: Paint_Style determines if Circle is stroked or filled;
3547if stroked, Paint_Stroke_Width describes the line thickness.
3548
Cary Clarkbad5ad72017-08-03 17:14:08 -04003549#Param cx Circle center on the x-axis ##
3550#Param cy Circle center on the y-axis ##
3551#Param radius half the diameter of Circle ##
3552#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003553
3554#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003555 void draw(SkCanvas* canvas) {
3556 SkPaint paint;
3557 paint.setAntiAlias(true);
3558 canvas->drawCircle(128, 128, 90, paint);
3559 paint.setColor(SK_ColorWHITE);
3560 canvas->drawCircle(86, 86, 20, paint);
3561 canvas->drawCircle(160, 76, 20, paint);
3562 canvas->drawCircle(140, 150, 35, paint);
3563 }
3564##
3565
3566#ToDo incomplete ##
3567
3568##
3569
3570#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
3571
3572Draw Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint.
3573If radius is zero or less, nothing is drawn.
3574In paint: Paint_Style determines if Circle is stroked or filled;
3575if stroked, Paint_Stroke_Width describes the line thickness.
3576
3577#Param center Circle center ##
3578#Param radius half the diameter of Circle ##
3579#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
3580
3581#Example
3582 void draw(SkCanvas* canvas) {
3583 SkPaint paint;
3584 paint.setAntiAlias(true);
3585 canvas->drawCircle(128, 128, 90, paint);
3586 paint.setColor(SK_ColorWHITE);
3587 canvas->drawCircle({86, 86}, 20, paint);
3588 canvas->drawCircle({160, 76}, 20, paint);
3589 canvas->drawCircle({140, 150}, 35, paint);
3590 }
Cary Clark8032b982017-07-28 11:04:54 -04003591##
3592
3593#ToDo incomplete ##
3594
3595##
3596
3597# ------------------------------------------------------------------------------
3598
3599#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
3600 bool useCenter, const SkPaint& paint)
3601
3602Draw Arc using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003603
Cary Clark8032b982017-07-28 11:04:54 -04003604Arc is part of Oval bounded by oval, sweeping from startAngle to startAngle plus
3605sweepAngle. startAngle and sweepAngle are in degrees.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003606
Cary Clark8032b982017-07-28 11:04:54 -04003607startAngle of zero places start point at the right middle edge of oval.
3608A positive sweepAngle places Arc end point clockwise from start point;
3609a negative sweepAngle places Arc end point counterclockwise from start point.
3610sweepAngle may exceed 360 degrees, a full circle.
3611If useCenter is true, draw a wedge that includes lines from oval
3612center to Arc end points. If useCenter is false, draw Arc between end points.
3613
3614If Rect oval is empty or sweepAngle is zero, nothing is drawn.
3615
Cary Clarkbad5ad72017-08-03 17:14:08 -04003616#Param oval Rect bounds of Oval containing Arc to draw ##
3617#Param startAngle angle in degrees where Arc begins ##
3618#Param sweepAngle sweep angle in degrees; positive is clockwise ##
3619#Param useCenter if true, include the center of the oval ##
3620#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003621
3622#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003623 void draw(SkCanvas* canvas) {
3624 SkPaint paint;
3625 paint.setAntiAlias(true);
3626 SkRect oval = { 4, 4, 60, 60};
3627 for (auto useCenter : { false, true } ) {
3628 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
3629 paint.setStyle(style);
3630 for (auto degrees : { 45, 90, 180, 360} ) {
3631 canvas->drawArc(oval, 0, degrees , useCenter, paint);
3632 canvas->translate(64, 0);
3633 }
3634 canvas->translate(-256, 64);
3635 }
3636 }
Cary Clark8032b982017-07-28 11:04:54 -04003637 }
3638##
3639
3640#Example
3641#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003642 void draw(SkCanvas* canvas) {
3643 SkPaint paint;
3644 paint.setAntiAlias(true);
3645 paint.setStyle(SkPaint::kStroke_Style);
3646 paint.setStrokeWidth(4);
3647 SkRect oval = { 4, 4, 60, 60};
3648 float intervals[] = { 5, 5 };
3649 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
3650 for (auto degrees : { 270, 360, 540, 720 } ) {
3651 canvas->drawArc(oval, 0, degrees, false, paint);
3652 canvas->translate(64, 0);
3653 }
Cary Clark8032b982017-07-28 11:04:54 -04003654 }
3655##
3656
3657#ToDo incomplete ##
3658
3659##
3660
3661# ------------------------------------------------------------------------------
3662
3663#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
3664
Cary Clarkbad5ad72017-08-03 17:14:08 -04003665Draw Round_Rect bounded by Rect rect, with corner radii (rx, ry) using Clip,
3666Matrix, and Paint paint.
3667
Cary Clark8032b982017-07-28 11:04:54 -04003668In paint: Paint_Style determines if Round_Rect is stroked or filled;
3669if stroked, Paint_Stroke_Width describes the line thickness.
3670If rx or ry are less than zero, they are treated as if they are zero.
3671If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003672If rx and ry are zero, Round_Rect is drawn as Rect and if stroked is affected by
3673Paint_Stroke_Join.
Cary Clark8032b982017-07-28 11:04:54 -04003674
Cary Clarkbad5ad72017-08-03 17:14:08 -04003675#Param rect Rect bounds of Round_Rect to draw ##
3676#Param rx semiaxis length in x of oval describing rounded corners ##
3677#Param ry semiaxis length in y of oval describing rounded corners ##
3678#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003679
3680#Example
3681#Description
3682 Top row has a zero radius a generates a rectangle.
3683 Second row radii sum to less than sides.
3684 Third row radii sum equals sides.
3685 Fourth row radii sum exceeds sides; radii are scaled to fit.
3686##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003687 void draw(SkCanvas* canvas) {
3688 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
3689 SkPaint paint;
3690 paint.setStrokeWidth(15);
3691 paint.setStrokeJoin(SkPaint::kRound_Join);
3692 paint.setAntiAlias(true);
3693 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
3694 paint.setStyle(style );
3695 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
3696 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
3697 canvas->translate(0, 60);
3698 }
3699 canvas->translate(80, -240);
3700 }
Cary Clark8032b982017-07-28 11:04:54 -04003701 }
3702##
3703
3704#ToDo incomplete ##
3705
3706##
3707
3708# ------------------------------------------------------------------------------
3709
3710#Method void drawPath(const SkPath& path, const SkPaint& paint)
3711
3712Draw Path path using Clip, Matrix, and Paint paint.
3713Path contains an array of Path_Contour, each of which may be open or closed.
3714
3715In paint: Paint_Style determines if Round_Rect is stroked or filled:
Cary Clarkbad5ad72017-08-03 17:14:08 -04003716if filled, Path_Fill_Type determines whether Path_Contour describes inside or
3717outside of fill; if stroked, Paint_Stroke_Width describes the line thickness,
3718Paint_Stroke_Cap describes line ends, and Paint_Stroke_Join describes how
3719corners are drawn.
Cary Clark8032b982017-07-28 11:04:54 -04003720
Cary Clarkbad5ad72017-08-03 17:14:08 -04003721#Param path Path to draw ##
3722#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003723
3724#Example
3725#Description
3726 Top rows draw stroked path with combinations of joins and caps. The open contour
3727 is affected by caps; the closed contour is affected by joins.
3728 Bottom row draws fill the same for open and closed contour.
3729 First bottom column shows winding fills overlap.
3730 Second bottom column shows even odd fills exclude overlap.
3731 Third bottom column shows inverse winding fills area outside both contours.
3732##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003733void draw(SkCanvas* canvas) {
3734 SkPath path;
3735 path.moveTo(20, 20);
3736 path.quadTo(60, 20, 60, 60);
3737 path.close();
3738 path.moveTo(60, 20);
3739 path.quadTo(60, 60, 20, 60);
3740 SkPaint paint;
3741 paint.setStrokeWidth(10);
3742 paint.setAntiAlias(true);
3743 paint.setStyle(SkPaint::kStroke_Style);
3744 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
3745 paint.setStrokeJoin(join);
3746 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
3747 paint.setStrokeCap(cap);
3748 canvas->drawPath(path, paint);
3749 canvas->translate(80, 0);
3750 }
3751 canvas->translate(-240, 60);
3752 }
3753 paint.setStyle(SkPaint::kFill_Style);
3754 for (auto fill : { SkPath::kWinding_FillType,
3755 SkPath::kEvenOdd_FillType,
3756 SkPath::kInverseWinding_FillType } ) {
3757 path.setFillType(fill);
3758 canvas->save();
3759 canvas->clipRect({0, 10, 80, 70});
3760 canvas->drawPath(path, paint);
3761 canvas->restore();
3762 canvas->translate(80, 0);
3763 }
Cary Clark8032b982017-07-28 11:04:54 -04003764}
3765##
3766
3767#ToDo incomplete ##
3768
3769##
3770
3771# ------------------------------------------------------------------------------
3772#Topic Draw_Image
3773
Cary Clarkbad5ad72017-08-03 17:14:08 -04003774drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
3775a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04003776
Cary Clark73fa9722017-08-29 17:36:51 -04003777#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04003778
3779Draw Image image, with its top-left corner at (left, top),
3780using Clip, Matrix, and optional Paint paint.
3781
Cary Clarkbad5ad72017-08-03 17:14:08 -04003782If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode,
3783and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3784If paint contains Mask_Filter, generate mask from image bounds. If generated
3785mask extends beyond image bounds, replicate image edge colors, just as Shader
3786made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
3787image's edge color when it samples outside of its bounds.
Cary Clark8032b982017-07-28 11:04:54 -04003788
Cary Clarkbad5ad72017-08-03 17:14:08 -04003789#Param image uncompressed rectangular map of pixels ##
3790#Param left left side of image ##
3791#Param top top side of image ##
3792#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3793 and so on; or nullptr
3794##
Cary Clark8032b982017-07-28 11:04:54 -04003795
3796#Example
3797#Height 64
3798#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003799void draw(SkCanvas* canvas) {
3800 // sk_sp<SkImage> image;
3801 SkImage* imagePtr = image.get();
3802 canvas->drawImage(imagePtr, 0, 0);
3803 SkPaint paint;
3804 canvas->drawImage(imagePtr, 80, 0, &paint);
3805 paint.setAlpha(0x80);
3806 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003807}
3808##
3809
3810#ToDo incomplete ##
3811
3812##
3813
3814# ------------------------------------------------------------------------------
3815
3816#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003817 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04003818
3819Draw Image image, with its top-left corner at (left, top),
3820using Clip, Matrix, and optional Paint paint.
3821
Cary Clarkbad5ad72017-08-03 17:14:08 -04003822If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3823Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3824If paint contains Mask_Filter, generate mask from image bounds. If generated
3825mask extends beyond image bounds, replicate image edge colors, just as Shader
3826made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
3827image's edge color when it samples outside of its bounds.
Cary Clark8032b982017-07-28 11:04:54 -04003828
Cary Clarkbad5ad72017-08-03 17:14:08 -04003829#Param image uncompressed rectangular map of pixels ##
3830#Param left left side of image ##
3831#Param top pop side of image ##
3832#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3833 and so on; or nullptr
3834##
Cary Clark8032b982017-07-28 11:04:54 -04003835
3836#Example
3837#Height 64
3838#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003839void draw(SkCanvas* canvas) {
3840 // sk_sp<SkImage> image;
3841 canvas->drawImage(image, 0, 0);
3842 SkPaint paint;
3843 canvas->drawImage(image, 80, 0, &paint);
3844 paint.setAlpha(0x80);
3845 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003846}
3847##
3848
3849#ToDo incomplete ##
3850
3851##
3852
3853# ------------------------------------------------------------------------------
3854
3855#Enum SrcRectConstraint
3856
3857#Code
3858 enum SrcRectConstraint {
3859 kStrict_SrcRectConstraint,
3860 kFast_SrcRectConstraint,
3861 };
3862##
3863
Cary Clarkbad5ad72017-08-03 17:14:08 -04003864SrcRectConstraint controls the behavior at the edge of the Rect src, provided to
3865drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04003866
Cary Clarkbad5ad72017-08-03 17:14:08 -04003867Image_Filter in Paint may sample multiple pixels in the image. Rect src
3868restricts the bounds of pixels that may be read. Image_Filter may slow down if
3869it cannot read outside the bounds, when sampling near the edge of Rect src.
Cary Clark8032b982017-07-28 11:04:54 -04003870SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
3871outside Rect src.
3872
3873#Const kStrict_SrcRectConstraint
3874 Requires Image_Filter to respect Rect src,
3875 sampling only inside of its bounds, possibly with a performance penalty.
3876##
3877
3878#Const kFast_SrcRectConstraint
3879 Permits Image_Filter to sample outside of Rect src
3880 by half the width of Image_Filter, permitting it to run faster but with
3881 error at the image edges.
3882##
3883
3884#Example
3885#Height 64
3886#Description
3887 redBorder contains a black and white checkerboard bordered by red.
3888 redBorder is drawn scaled by 16 on the left.
3889 The middle and right bitmaps are filtered checkboards.
3890 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3891 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3892##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003893void draw(SkCanvas* canvas) {
3894 SkBitmap redBorder;
3895 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3896 SkCanvas checkRed(redBorder);
3897 checkRed.clear(SK_ColorRED);
3898 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3899 { SK_ColorWHITE, SK_ColorBLACK } };
3900 checkRed.writePixels(
3901 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3902 canvas->scale(16, 16);
3903 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3904 canvas->resetMatrix();
3905 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3906 SkPaint lowPaint;
3907 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3908 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3909 SkCanvas::kFast_SrcRectConstraint } ) {
3910 canvas->translate(80, 0);
3911 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3912 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3913 }
Cary Clark8032b982017-07-28 11:04:54 -04003914}
3915##
3916
3917#ToDo incomplete ##
3918
3919##
3920
3921# ------------------------------------------------------------------------------
3922
3923#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3924 const SkPaint* paint,
3925 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3926
3927Draw Rect src of Image image, scaled and translated to fill Rect dst.
3928Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003929
Cary Clarkbad5ad72017-08-03 17:14:08 -04003930If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3931Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3932If paint contains Mask_Filter, generate mask from image bounds.
3933
3934If generated mask extends beyond image bounds, replicate image edge colors, just
3935as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
3936replicates the image's edge color when it samples outside of its bounds.
3937
3938constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
3939sample within src; set to kFast_SrcRectConstraint allows sampling outside to
3940improve performance.
3941
3942#Param image Image containing pixels, dimensions, and format ##
3943#Param src source Rect of image to draw from ##
3944#Param dst destination Rect of image to draw to ##
3945#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3946 and so on; or nullptr
3947##
3948#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04003949
3950#Example
3951#Height 64
3952#Description
3953 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
3954 its bounds; there's no bleeding with kFast_SrcRectConstraint.
3955 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3956 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3957 with kFast_SrcRectConstraint red bleeds on the edges.
3958##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003959void draw(SkCanvas* canvas) {
3960 uint32_t pixels[][4] = {
3961 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
3962 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
3963 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
3964 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
3965 SkBitmap redBorder;
3966 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
3967 (void*) pixels, sizeof(pixels[0]));
3968 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3969 SkPaint lowPaint;
3970 for (auto constraint : {
3971 SkCanvas::kFast_SrcRectConstraint,
3972 SkCanvas::kStrict_SrcRectConstraint,
3973 SkCanvas::kFast_SrcRectConstraint } ) {
3974 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3975 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3976 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3977 canvas->translate(80, 0);
3978 }
3979}
Cary Clark8032b982017-07-28 11:04:54 -04003980##
3981
3982#ToDo incomplete ##
3983
3984##
3985
3986# ------------------------------------------------------------------------------
3987
3988#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
3989 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3990
3991Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003992Note that isrc is on integer pixel boundaries; dst may include fractional
3993boundaries. Additionally transform draw using Clip, Matrix, and optional Paint
3994paint.
Cary Clark8032b982017-07-28 11:04:54 -04003995
Cary Clarkbad5ad72017-08-03 17:14:08 -04003996If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3997Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3998If paint contains Mask_Filter, generate mask from image bounds.
3999
4000If generated mask extends beyond image bounds, replicate image edge colors, just
4001as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4002replicates the image's edge color when it samples outside of its bounds.
4003
4004constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4005sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4006improve performance.
4007
4008#Param image Image containing pixels, dimensions, and format ##
4009#Param isrc source IRect of image to draw from ##
4010#Param dst destination Rect of image to draw to ##
4011#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4012 and so on; or nullptr
4013##
4014#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004015
4016#Example
4017#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04004018void draw(SkCanvas* canvas) {
4019 // sk_sp<SkImage> image;
4020 for (auto i : { 1, 2, 4, 8 } ) {
4021 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
4022 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
4023 }
Cary Clark8032b982017-07-28 11:04:54 -04004024}
4025##
4026
4027#ToDo incomplete ##
4028
4029##
4030
4031# ------------------------------------------------------------------------------
4032
4033#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
4034 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4035
Cary Clarkbad5ad72017-08-03 17:14:08 -04004036Draw Image image, scaled and translated to fill Rect dst, using Clip, Matrix,
4037and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004038
Cary Clarkbad5ad72017-08-03 17:14:08 -04004039If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4040Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4041If paint contains Mask_Filter, generate mask from image bounds.
4042
4043If generated mask extends beyond image bounds, replicate image edge colors, just
4044as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4045replicates the image's edge color when it samples outside of its bounds.
4046
4047constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4048sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4049improve performance.
4050
4051#Param image Image containing pixels, dimensions, and format ##
4052#Param dst destination Rect of image to draw to ##
4053#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4054 and so on; or nullptr
4055##
4056#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004057
4058#Example
4059#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04004060void draw(SkCanvas* canvas) {
4061 // sk_sp<SkImage> image;
4062 for (auto i : { 20, 40, 80, 160 } ) {
4063 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), 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 sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
4075 const SkPaint* paint,
4076 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4077
4078Draw Rect src of Image image, scaled and translated to fill Rect dst.
4079Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004080
Cary Clarkbad5ad72017-08-03 17:14:08 -04004081If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4082Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4083If paint contains Mask_Filter, generate mask from image bounds.
4084
4085If generated mask extends beyond image bounds, replicate image edge colors, just
4086as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4087replicates the image's edge color when it samples outside of its bounds.
4088
4089constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4090sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4091improve performance.
4092
4093#Param image Image containing pixels, dimensions, and format ##
4094#Param src source Rect of image to draw from ##
4095#Param dst destination Rect of image to draw to ##
4096#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4097 and so on; or nullptr
4098##
4099#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004100
4101#Example
4102#Height 64
4103#Description
4104 Canvas scales and translates; transformation from src to dst also scales.
4105 The two matrices are concatenated to create the final transformation.
4106##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004107void draw(SkCanvas* canvas) {
4108 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
4109 { SK_ColorWHITE, SK_ColorBLACK } };
4110 SkBitmap bitmap;
4111 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4112 (void*) pixels, sizeof(pixels[0]));
4113 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4114 SkPaint paint;
4115 canvas->scale(4, 4);
4116 for (auto alpha : { 50, 100, 150, 255 } ) {
4117 paint.setAlpha(alpha);
4118 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
4119 canvas->translate(8, 0);
4120 }
4121}
Cary Clark8032b982017-07-28 11:04:54 -04004122##
4123
4124#ToDo incomplete ##
4125
4126##
4127
4128# ------------------------------------------------------------------------------
4129
4130#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
4131 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4132
4133Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004134isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004135Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004136
Cary Clarkbad5ad72017-08-03 17:14:08 -04004137If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4138Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4139If paint contains Mask_Filter, generate mask from image bounds.
4140
4141If generated mask extends beyond image bounds, replicate image edge colors, just
4142as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4143replicates the image's edge color when it samples outside of its bounds.
4144
4145constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4146sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4147improve performance.
4148
4149#Param image Image containing pixels, dimensions, and format ##
4150#Param isrc source IRect of image to draw from ##
4151#Param dst destination Rect of image to draw to ##
4152#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4153 and so on; or nullptr
4154##
4155#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004156
4157#Example
4158#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004159void draw(SkCanvas* canvas) {
4160 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
4161 { 0xAAAAAAAA, 0xFFFFFFFF} };
4162 SkBitmap bitmap;
4163 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4164 (void*) pixels, sizeof(pixels[0]));
4165 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4166 SkPaint paint;
4167 canvas->scale(4, 4);
4168 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4169 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4170 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
4171 canvas->translate(8, 0);
4172 }
Cary Clark8032b982017-07-28 11:04:54 -04004173}
4174##
4175
4176#ToDo incomplete ##
4177##
4178
4179# ------------------------------------------------------------------------------
4180
4181#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
4182 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4183
4184Draw Image image, scaled and translated to fill Rect dst,
4185using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004186
Cary Clarkbad5ad72017-08-03 17:14:08 -04004187If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4188Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4189If paint contains Mask_Filter, generate mask from image bounds.
4190
4191If generated mask extends beyond image bounds, replicate image edge colors, just
4192as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4193replicates the image's edge color when it samples outside of its bounds.
4194
4195constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4196sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4197improve performance.
4198
4199#Param image Image containing pixels, dimensions, and format ##
4200#Param dst destination Rect of image to draw to ##
4201#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4202 and so on; or nullptr
4203##
4204#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004205
4206#Example
4207#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004208void draw(SkCanvas* canvas) {
4209 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4210 { 0xAAAA0000, 0xFFFF0000} };
4211 SkBitmap bitmap;
4212 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4213 (void*) pixels, sizeof(pixels[0]));
4214 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4215 SkPaint paint;
4216 canvas->scale(4, 4);
4217 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4218 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4219 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
4220 canvas->translate(8, 0);
4221 }
Cary Clark8032b982017-07-28 11:04:54 -04004222}
4223##
4224
4225#ToDo incomplete ##
4226
4227##
4228
4229# ------------------------------------------------------------------------------
4230
4231#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
4232 const SkPaint* paint = nullptr)
4233
4234Draw Image image stretched differentially to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004235IRect center divides the image into nine sections: four sides, four corners, and
4236the center. Corners are unscaled or scaled down proportionately if their sides
4237are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004238
Cary Clarkbad5ad72017-08-03 17:14:08 -04004239Additionally transform draw using Clip, Matrix, and optional Paint paint.
4240
4241If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4242Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4243If paint contains Mask_Filter, generate mask from image bounds.
4244
4245If generated mask extends beyond image bounds, replicate image edge colors, just
4246as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4247replicates the image's edge color when it samples outside of its bounds.
4248
4249#Param image Image containing pixels, dimensions, and format ##
4250#Param center IRect edge of image corners and sides ##
4251#Param dst destination Rect of image to draw to ##
4252#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4253 and so on; or nullptr
4254##
Cary Clark8032b982017-07-28 11:04:54 -04004255
4256#Example
4257#Height 128
4258#Description
4259 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
4260 The second image equals the size of center; only corners are drawn, unscaled.
4261 The remaining images are larger than center. All corners draw unscaled. The sides
4262 and center are scaled if needed to take up the remaining space.
4263##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004264void draw(SkCanvas* canvas) {
4265 SkIRect center = { 20, 10, 50, 40 };
4266 SkBitmap bitmap;
4267 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4268 SkCanvas bitCanvas(bitmap);
4269 SkPaint paint;
4270 SkColor gray = 0xFF000000;
4271 int left = 0;
4272 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4273 int top = 0;
4274 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4275 paint.setColor(gray);
4276 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4277 gray += 0x001f1f1f;
4278 top = bottom;
4279 }
4280 left = right;
4281 }
4282 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4283 SkImage* imagePtr = image.get();
4284 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4285 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4286 canvas->translate(dest + 4, 0);
4287 }
Cary Clark8032b982017-07-28 11:04:54 -04004288}
4289##
4290
4291#ToDo incomplete ##
4292
4293##
4294
4295# ------------------------------------------------------------------------------
4296
4297#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
4298 const SkPaint* paint = nullptr)
4299
4300Draw Image image stretched differentially to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004301IRect center divides the image into nine sections: four sides, four corners, and
4302the center. Corners are unscaled or scaled down proportionately if their sides
4303are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004304
Cary Clarkbad5ad72017-08-03 17:14:08 -04004305Additionally transform draw using Clip, Matrix, and optional Paint paint.
4306
4307If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4308Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4309If paint contains Mask_Filter, generate mask from image bounds.
4310
4311If generated mask extends beyond image bounds, replicate image edge colors, just
4312as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4313replicates the image's edge color when it samples outside of its bounds.
4314
4315#Param image Image containing pixels, dimensions, and format ##
4316#Param center IRect edge of image corners and sides ##
4317#Param dst destination Rect of image to draw to ##
4318#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4319 and so on; or nullptr
4320##
Cary Clark8032b982017-07-28 11:04:54 -04004321
4322#Example
4323#Height 128
4324#Description
4325 The two leftmost images has four corners and sides to the left and right of center.
4326 The leftmost image scales the width of corners proportionately to fit.
4327 The third and fourth image corners are unscaled; the sides and center are scaled to
4328 fill the remaining space.
4329 The rightmost image has four corners scaled vertically to fit, and uses sides above
4330 and below center to fill the remaining space.
4331##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004332void draw(SkCanvas* canvas) {
4333 SkIRect center = { 20, 10, 50, 40 };
4334 SkBitmap bitmap;
4335 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4336 SkCanvas bitCanvas(bitmap);
4337 SkPaint paint;
4338 SkColor gray = 0xFF000000;
4339 int left = 0;
4340 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4341 int top = 0;
4342 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4343 paint.setColor(gray);
4344 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4345 gray += 0x001f1f1f;
4346 top = bottom;
4347 }
4348 left = right;
4349 }
4350 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4351 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4352 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4353 canvas->translate(dest + 4, 0);
4354 }
Cary Clark8032b982017-07-28 11:04:54 -04004355}
4356##
4357
4358#ToDo incomplete ##
4359
4360##
4361
4362# ------------------------------------------------------------------------------
4363
4364#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04004365 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04004366
4367Draw Bitmap bitmap, with its top-left corner at (left, top),
4368using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004369
Cary Clarkbad5ad72017-08-03 17:14:08 -04004370If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4371Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4372If paint contains Mask_Filter, generate mask from bitmap bounds.
4373
4374If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4375just as Shader made from SkShader::MakeBitmapShader with
4376SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4377outside of its bounds.
4378
4379#Param bitmap Bitmap containing pixels, dimensions, and format ##
4380#Param left left side of bitmap ##
4381#Param top top side of bitmap ##
4382#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4383 and so on; or nullptr
4384##
Cary Clark8032b982017-07-28 11:04:54 -04004385
4386#Example
4387#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004388void draw(SkCanvas* canvas) {
4389 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4390 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4391 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4392 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4393 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4394 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4395 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
4396 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
4397 SkBitmap bitmap;
4398 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4399 (void*) pixels, sizeof(pixels[0]));
4400 SkPaint paint;
4401 canvas->scale(4, 4);
4402 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4403 paint.setColor(color);
4404 canvas->drawBitmap(bitmap, 0, 0, &paint);
4405 canvas->translate(12, 0);
4406 }
Cary Clark8032b982017-07-28 11:04:54 -04004407}
4408##
4409
4410#ToDo incomplete ##
4411
4412##
4413
4414# ------------------------------------------------------------------------------
4415
4416#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
4417 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4418
4419Draw Rect src of Bitmap bitmap, scaled and translated to fill Rect dst.
4420Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004421
Cary Clarkbad5ad72017-08-03 17:14:08 -04004422If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4423Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4424If paint contains Mask_Filter, generate mask from bitmap bounds.
4425
4426If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4427just as Shader made from SkShader::MakeBitmapShader with
4428SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4429outside of its bounds.
4430
4431constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4432sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4433improve performance.
4434
4435#Param bitmap Bitmap containing pixels, dimensions, and format ##
4436#Param src source Rect of image to draw from ##
4437#Param dst destination Rect of image to draw to ##
4438#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4439 and so on; or nullptr
4440##
4441#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004442
4443#Example
4444#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004445void draw(SkCanvas* canvas) {
4446 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4447 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4448 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4449 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4450 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4451 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4452 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4453 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
4454 SkBitmap bitmap;
4455 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4456 (void*) pixels, sizeof(pixels[0]));
4457 SkPaint paint;
4458 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 6));
4459 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4460 paint.setColor(color);
4461 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4462 canvas->translate(48, 0);
4463 }
Cary Clark8032b982017-07-28 11:04:54 -04004464}
4465##
4466
4467#ToDo incomplete ##
4468
4469##
4470
4471# ------------------------------------------------------------------------------
4472
4473#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
4474 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4475
4476Draw IRect isrc of Bitmap bitmap, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004477isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004478Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004479
Cary Clarkbad5ad72017-08-03 17:14:08 -04004480If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4481Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4482If paint contains Mask_Filter, generate mask from bitmap bounds.
4483
4484If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4485just as Shader made from SkShader::MakeBitmapShader with
4486SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4487outside of its bounds.
4488
4489constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4490sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4491improve performance.
4492
4493#Param bitmap Bitmap containing pixels, dimensions, and format ##
4494#Param isrc source IRect of image to draw from ##
4495#Param dst destination Rect of image to draw to ##
4496#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4497 and so on; or nullptr
4498##
Cary Clarka523d2d2017-08-30 08:58:10 -04004499#Param constraint sample strictly within src, or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004500
4501#Example
4502#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004503void draw(SkCanvas* canvas) {
4504 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4505 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4506 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4507 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4508 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
4509 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
4510 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4511 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
4512 SkBitmap bitmap;
4513 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4514 (void*) pixels, sizeof(pixels[0]));
4515 SkPaint paint;
4516 paint.setFilterQuality(kHigh_SkFilterQuality);
4517 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
4518 paint.setColor(color);
4519 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4520 canvas->translate(48.25f, 0);
4521 }
Cary Clark8032b982017-07-28 11:04:54 -04004522}
4523##
4524
4525#ToDo incomplete ##
4526
4527##
4528
4529# ------------------------------------------------------------------------------
4530
4531#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
4532 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4533
4534Draw Bitmap bitmap, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004535isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004536Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004537
Cary Clarkbad5ad72017-08-03 17:14:08 -04004538If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4539Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4540If paint contains Mask_Filter, generate mask from bitmap bounds.
4541
4542If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4543just as Shader made from SkShader::MakeBitmapShader with
4544SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4545outside of its bounds.
4546
4547constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4548sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4549improve performance.
4550
4551#Param bitmap Bitmap containing pixels, dimensions, and format ##
4552#Param dst destination Rect of image to draw to ##
4553#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4554 and so on; or nullptr
4555##
4556#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004557
4558#Example
4559#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004560void draw(SkCanvas* canvas) {
4561 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4562 { 0xAAAA0000, 0xFFFF0000} };
4563 SkBitmap bitmap;
4564 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4565 (void*) pixels, sizeof(pixels[0]));
4566 SkPaint paint;
4567 canvas->scale(4, 4);
4568 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4569 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4570 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
4571 canvas->translate(8, 0);
4572 }
Cary Clark8032b982017-07-28 11:04:54 -04004573}
4574##
4575
4576#ToDo incomplete ##
4577
4578##
4579
4580# ------------------------------------------------------------------------------
4581
4582#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04004583 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04004584
4585Draw Bitmap bitmap stretched differentially to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004586IRect center divides the bitmap into nine sections: four sides, four corners,
4587and the center. Corners are unscaled or scaled down proportionately if their
4588sides are larger than dst; center and four sides are scaled to fit remaining
4589space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004590
Cary Clarkbad5ad72017-08-03 17:14:08 -04004591Additionally transform draw using Clip, Matrix, and optional Paint paint.
4592
4593If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4594Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4595If paint contains Mask_Filter, generate mask from bitmap bounds.
4596
4597If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4598just as Shader made from SkShader::MakeBitmapShader with
4599SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4600outside of its bounds.
4601
4602#Param bitmap Bitmap containing pixels, dimensions, and format ##
4603#Param center IRect edge of image corners and sides ##
4604#Param dst destination Rect of image to draw to ##
4605#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4606 and so on; or nullptr
4607##
Cary Clark8032b982017-07-28 11:04:54 -04004608
4609#Example
4610#Height 128
4611#Description
4612 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4613 The leftmost bitmap draw scales the width of corners proportionately to fit.
4614 The third and fourth draw corners are unscaled; the sides and center are scaled to
4615 fill the remaining space.
4616 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4617 and below center to fill the remaining space.
4618##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004619void draw(SkCanvas* canvas) {
4620 SkIRect center = { 20, 10, 50, 40 };
4621 SkBitmap bitmap;
4622 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4623 SkCanvas bitCanvas(bitmap);
4624 SkPaint paint;
4625 SkColor gray = 0xFF000000;
4626 int left = 0;
4627 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4628 int top = 0;
4629 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4630 paint.setColor(gray);
4631 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4632 gray += 0x001f1f1f;
4633 top = bottom;
4634 }
4635 left = right;
4636 }
4637 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4638 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4639 canvas->translate(dest + 4, 0);
4640 }
Cary Clark8032b982017-07-28 11:04:54 -04004641}
4642##
4643
4644#ToDo incomplete ##
4645
4646##
4647
4648# ------------------------------------------------------------------------------
4649#Struct Lattice
4650
4651 Lattice divides Bitmap or Image into a rectangular grid.
4652 Grid entries on even columns and even rows are fixed; these entries are
4653 always drawn at their original size if the destination is large enough.
4654 If the destination side is too small to hold the fixed entries, all fixed
4655 entries are proportionately scaled down to fit.
4656 The grid entries not on even columns and rows are scaled to fit the
4657 remaining space, if any.
4658
4659#Code
4660 struct Lattice {
4661 enum Flags {...
4662
4663 const int* fXDivs;
4664 const int* fYDivs;
4665 const Flags* fFlags;
4666 int fXCount;
4667 int fYCount;
4668 const SkIRect* fBounds;
4669 };
4670##
4671
4672 #Enum Flags
4673 #Code
4674 enum Flags : uint8_t {
4675 kTransparent_Flags = 1 << 0,
4676 };
4677 ##
4678
4679 Optional setting per rectangular grid entry to make it transparent.
4680
4681 #Const kTransparent_Flags 1
4682 Set to skip lattice rectangle by making it transparent.
4683 ##
4684 ##
4685
4686 #Member const int* fXDivs
4687 Array of x-coordinates that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004688 Array entries must be unique, increasing, greater than or equal to
4689 fBounds left edge, and less than fBounds right edge.
4690 Set the first element to fBounds left to collapse the left column of
4691 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04004692 ##
4693
4694 #Member const int* fYDivs
4695 Array of y-coordinates that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004696 Array entries must be unique, increasing, greater than or equal to
4697 fBounds top edge, and less than fBounds bottom edge.
4698 Set the first element to fBounds top to collapse the top row of fixed
4699 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04004700 ##
4701
4702 #Member const Flags* fFlags
4703 Optional array of Flags, one per rectangular grid entry:
Cary Clarkbad5ad72017-08-03 17:14:08 -04004704 array length must be
4705 #Formula
4706 (fXCount + 1) * (fYCount + 1)
4707 ##
4708 .
Cary Clark8032b982017-07-28 11:04:54 -04004709 Array entries correspond to the rectangular grid entries, ascending
4710 left to right and then top to bottom.
4711 ##
4712
4713 #Member int fXCount
Cary Clarkbad5ad72017-08-03 17:14:08 -04004714 Number of entries in fXDivs array; one less than the number of
4715 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04004716 ##
4717
4718 #Member int fYCount
Cary Clarkbad5ad72017-08-03 17:14:08 -04004719 Number of entries in fYDivs array; one less than the number of vertical
4720 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04004721 ##
4722
4723 #Member const SkIRect* fBounds
4724 Optional subset IRect source to draw from.
4725 If nullptr, source bounds is dimensions of Bitmap or Image.
4726 ##
4727
4728#Struct Lattice ##
4729
4730#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
4731 const SkPaint* paint = nullptr)
4732
4733Draw Bitmap bitmap stretched differentially to fit into Rect dst.
4734
4735Lattice lattice divides bitmap into a rectangular grid.
4736Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04004737of drawBitmapNine, fixed lattice elements never scale larger than their initial
4738size and shrink proportionately when all fixed elements exceed the bitmap's
4739dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004740
4741Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004742
Cary Clarkbad5ad72017-08-03 17:14:08 -04004743If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4744Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4745If paint contains Mask_Filter, generate mask from bitmap bounds.
4746
4747If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4748just as Shader made from SkShader::MakeBitmapShader with
4749SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4750outside of its bounds.
4751
4752#Param bitmap Bitmap containing pixels, dimensions, and format ##
4753#Param lattice division of bitmap into fixed and variable rectangles ##
4754#Param dst destination Rect of image to draw to ##
4755#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4756 and so on; or nullptr
4757##
Cary Clark8032b982017-07-28 11:04:54 -04004758
4759#Example
4760#Height 128
4761#Description
4762 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4763 The leftmost bitmap draw scales the width of corners proportionately to fit.
4764 The third and fourth draw corners are unscaled; the sides are scaled to
4765 fill the remaining space; the center is transparent.
4766 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4767 and below center to fill the remaining space.
4768##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004769void draw(SkCanvas* canvas) {
4770 SkIRect center = { 20, 10, 50, 40 };
4771 SkBitmap bitmap;
4772 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4773 SkCanvas bitCanvas(bitmap);
4774 SkPaint paint;
4775 SkColor gray = 0xFF000000;
4776 int left = 0;
4777 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4778 int top = 0;
4779 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4780 paint.setColor(gray);
4781 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4782 gray += 0x001f1f1f;
4783 top = bottom;
4784 }
4785 left = right;
4786 }
4787 const int xDivs[] = { center.fLeft, center.fRight };
4788 const int yDivs[] = { center.fTop, center.fBottom };
4789 SkCanvas::Lattice::Flags flags[3][3];
4790 memset(flags, 0, sizeof(flags));
4791 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4792 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4793 SK_ARRAY_COUNT(yDivs), nullptr };
4794 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4795 canvas->drawBitmapLattice(bitmap, lattice , SkRect::MakeWH(dest, 110 - dest), nullptr);
4796 canvas->translate(dest + 4, 0);
4797 }
Cary Clark8032b982017-07-28 11:04:54 -04004798}
4799##
4800
4801#ToDo incomplete ##
4802
4803##
4804
4805# ------------------------------------------------------------------------------
4806
4807#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
4808 const SkPaint* paint = nullptr)
4809
4810Draw Image image stretched differentially to fit into Rect dst.
4811
4812Lattice lattice divides image into a rectangular grid.
4813Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04004814of drawBitmapNine, fixed lattice elements never scale larger than their initial
4815size and shrink proportionately when all fixed elements exceed the bitmap's
4816dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004817
4818Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004819
Cary Clarkbad5ad72017-08-03 17:14:08 -04004820If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4821Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4822If paint contains Mask_Filter, generate mask from bitmap bounds.
4823
4824If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4825just as Shader made from SkShader::MakeBitmapShader with
4826SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4827outside of its bounds.
4828
4829#Param image Image containing pixels, dimensions, and format ##
4830#Param lattice division of bitmap into fixed and variable rectangles ##
4831#Param dst destination Rect of image to draw to ##
4832#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4833 and so on; or nullptr
4834##
Cary Clark8032b982017-07-28 11:04:54 -04004835
4836#Example
4837#Height 128
4838#Description
4839 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
4840 The second image equals the size of center; only corners are drawn, unscaled.
4841 The remaining images are larger than center. All corners draw unscaled. The sides
4842 are scaled if needed to take up the remaining space; the center is transparent.
4843##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004844void draw(SkCanvas* canvas) {
4845 SkIRect center = { 20, 10, 50, 40 };
4846 SkBitmap bitmap;
4847 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4848 SkCanvas bitCanvas(bitmap);
4849 SkPaint paint;
4850 SkColor gray = 0xFF000000;
4851 int left = 0;
4852 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4853 int top = 0;
4854 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4855 paint.setColor(gray);
4856 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4857 gray += 0x001f1f1f;
4858 top = bottom;
4859 }
4860 left = right;
4861 }
4862 const int xDivs[] = { center.fLeft, center.fRight };
4863 const int yDivs[] = { center.fTop, center.fBottom };
4864 SkCanvas::Lattice::Flags flags[3][3];
4865 memset(flags, 0, sizeof(flags));
4866 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4867 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4868 SK_ARRAY_COUNT(yDivs), nullptr };
4869 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4870 SkImage* imagePtr = image.get();
4871 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4872 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4873 canvas->translate(dest + 4, 0);
4874 }
Cary Clark8032b982017-07-28 11:04:54 -04004875}
4876##
4877
4878#ToDo incomplete ##
4879
4880##
4881
4882#Topic Draw_Image ##
4883
4884# ------------------------------------------------------------------------------
4885
4886#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
4887 const SkPaint& paint)
4888
4889Draw text, with origin at (x, y), using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004890
Cary Clarkbad5ad72017-08-03 17:14:08 -04004891text's meaning depends on Paint_Text_Encoding; by default, text encoding is
4892UTF-8.
Cary Clark8032b982017-07-28 11:04:54 -04004893
Cary Clarkbad5ad72017-08-03 17:14:08 -04004894x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
4895text draws left to right, positioning the first glyph's left side bearing at x
4896and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4897
4898All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
4899Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
4900filled 12 point black glyphs.
4901
4902#Param text character code points or glyphs drawn ##
4903#Param byteLength byte length of text array ##
4904#Param x start of text on x-axis ##
4905#Param y start of text on y-axis ##
4906#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004907
4908#Example
4909#Height 200
4910#Description
4911 The same text is drawn varying Paint_Text_Size and varying
4912 Matrix.
4913##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004914void draw(SkCanvas* canvas) {
4915 SkPaint paint;
4916 paint.setAntiAlias(true);
4917 float textSizes[] = { 12, 18, 24, 36 };
4918 for (auto size: textSizes ) {
4919 paint.setTextSize(size);
4920 canvas->drawText("Aa", 2, 10, 20, paint);
4921 canvas->translate(0, size * 2);
4922 }
4923 paint.reset();
4924 paint.setAntiAlias(true);
4925 float yPos = 20;
4926 for (auto size: textSizes ) {
4927 float scale = size / 12.f;
4928 canvas->resetMatrix();
4929 canvas->translate(100, 0);
4930 canvas->scale(scale, scale);
4931 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
4932 yPos += size * 2;
4933 }
4934}
Cary Clark8032b982017-07-28 11:04:54 -04004935##
4936
4937#ToDo incomplete ##
4938
4939##
4940
4941#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
4942
Cary Clarkbad5ad72017-08-03 17:14:08 -04004943Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
4944Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004945
Cary Clarkbad5ad72017-08-03 17:14:08 -04004946string's meaning depends on Paint_Text_Encoding; by default, string encoding is
4947UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
4948results, since zero bytes may be embedded in the string.
Cary Clark8032b982017-07-28 11:04:54 -04004949
Cary Clarkbad5ad72017-08-03 17:14:08 -04004950x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
4951string draws left to right, positioning the first glyph's left side bearing at x
4952and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4953
4954All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
4955Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
4956filled 12 point black glyphs.
4957
4958#Param string character code points or glyphs drawn,
4959 ending with a char value of zero
4960##
4961#Param x start of string on x-axis ##
4962#Param y start of string on y-axis ##
4963#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004964
4965#Example
4966 SkPaint paint;
4967 canvas->drawString("a small hello", 20, 20, paint);
4968##
4969
4970#SeeAlso drawText
4971
4972##
4973
4974#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
4975
Cary Clarkbad5ad72017-08-03 17:14:08 -04004976Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
4977Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004978
Cary Clarkbad5ad72017-08-03 17:14:08 -04004979string's meaning depends on Paint_Text_Encoding; by default, string encoding is
4980UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
4981results, since zero bytes may be embedded in the string.
Cary Clark8032b982017-07-28 11:04:54 -04004982
Cary Clarkbad5ad72017-08-03 17:14:08 -04004983x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
4984string draws left to right, positioning the first glyph's left side bearing at x
4985and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4986
4987All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
4988Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
4989filled 12 point black glyphs.
4990
4991#Param string character code points or glyphs drawn,
4992 ending with a char value of zero
4993##
4994#Param x start of string on x-axis ##
4995#Param y start of string on y-axis ##
4996#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004997
4998#Example
4999 SkPaint paint;
5000 SkString string("a small hello");
5001 canvas->drawString(string, 20, 20, paint);
5002##
5003
5004#SeeAlso drawText
5005
5006##
5007
5008# ------------------------------------------------------------------------------
5009
5010#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
5011 const SkPaint& paint)
5012
Cary Clarkbad5ad72017-08-03 17:14:08 -04005013Draw each glyph in text with the origin in pos array, using Clip, Matrix, and
5014Paint paint. The number of entries in pos array must match the number of glyphs
5015described by byteLength of text.
Cary Clark8032b982017-07-28 11:04:54 -04005016
Cary Clarkbad5ad72017-08-03 17:14:08 -04005017text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5018UTF-8. pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text;
5019by default each glyph's left side bearing is positioned at x and its
5020baseline is positioned at y. Text size is affected by Matrix and
5021Paint_Text_Size.
Cary Clark8032b982017-07-28 11:04:54 -04005022
Cary Clarkbad5ad72017-08-03 17:14:08 -04005023All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5024Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
5025filled 12 point black glyphs.
5026
5027Layout engines such as Harfbuzz typically position each glyph
Cary Clark8032b982017-07-28 11:04:54 -04005028rather than using the font's advance widths.
5029
Cary Clarkbad5ad72017-08-03 17:14:08 -04005030#Param text character code points or glyphs drawn ##
5031#Param byteLength byte length of text array ##
5032#Param pos array of glyph origins ##
5033#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005034
5035#Example
5036#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04005037void draw(SkCanvas* canvas) {
5038 const char hello[] = "HeLLo!";
5039 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
5040 {172, 100} };
5041 SkPaint paint;
5042 paint.setTextSize(60);
5043 canvas->drawPosText(hello, strlen(hello), pos, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005044}
5045##
5046
5047#ToDo incomplete ##
5048
5049##
5050
5051# ------------------------------------------------------------------------------
5052
5053#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
5054 const SkPaint& paint)
5055
Cary Clarkbad5ad72017-08-03 17:14:08 -04005056Draw each glyph in text with its (x, y) origin composed from xpos array and
5057constY, using Clip, Matrix, and Paint paint. The number of entries in xpos array
5058must match the number of glyphs described by byteLength of text.
Cary Clark8032b982017-07-28 11:04:54 -04005059
Cary Clarkbad5ad72017-08-03 17:14:08 -04005060text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5061UTF-8. pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text;
5062by default each glyph's left side bearing is positioned at an xpos element and
5063its baseline is positioned at constY. Text size is affected by Matrix and
5064Paint_Text_Size.
Cary Clark8032b982017-07-28 11:04:54 -04005065
Cary Clarkbad5ad72017-08-03 17:14:08 -04005066All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5067Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
5068filled 12 point black glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005069
Cary Clarkbad5ad72017-08-03 17:14:08 -04005070Layout engines such as Harfbuzz typically position each glyph
5071rather than using the font's advance widths if all glyphs share the same
5072baseline.
5073
5074#Param text character code points or glyphs drawn ##
5075#Param byteLength byte length of text array ##
5076#Param xpos array of x positions, used to position each glyph ##
5077#Param constY shared y coordinate for all of x positions ##
5078#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005079
5080#Example
5081#Height 40
Cary Clarkbad5ad72017-08-03 17:14:08 -04005082 void draw(SkCanvas* canvas) {
5083 SkScalar xpos[] = { 20, 40, 80, 160 };
5084 SkPaint paint;
5085 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
5086 }
Cary Clark8032b982017-07-28 11:04:54 -04005087##
5088
5089#ToDo incomplete ##
5090
5091##
5092
5093# ------------------------------------------------------------------------------
5094
5095#Method void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
5096 SkScalar vOffset, const SkPaint& paint)
5097
5098Draw text on Path path, using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005099
Cary Clarkbad5ad72017-08-03 17:14:08 -04005100Origin of text is at distance hOffset along the path, offset by a perpendicular
5101vector of length vOffset. If the path section corresponding the glyph advance is
5102curved, the glyph is drawn curved to match; control points in the glyph are
5103mapped to projected points parallel to the path. If the text's advance is larger
5104than the path length, the excess text is clipped.
5105
5106text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5107UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by
5108default text positions the first glyph's left side bearing at origin x and its
Cary Clark8032b982017-07-28 11:04:54 -04005109baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
5110
Cary Clarkbad5ad72017-08-03 17:14:08 -04005111All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5112Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
5113filled 12 point black glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005114
Cary Clarkbad5ad72017-08-03 17:14:08 -04005115#Param text character code points or glyphs drawn ##
5116#Param byteLength byte length of text array ##
5117#Param path Path providing text baseline ##
5118#Param hOffset distance along path to offset origin ##
5119#Param vOffset offset of text above (if negative) or below (if positive) the path ##
5120#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005121
5122#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005123 void draw(SkCanvas* canvas) {
5124 const char aero[] = "correo a" "\xC3" "\xA9" "reo";
5125 const size_t len = sizeof(aero) - 1;
5126 SkPath path;
5127 path.addOval({43-26, 43-26, 43+26, 43+26}, SkPath::kCW_Direction, 3);
5128 SkPaint paint;
5129 paint.setTextSize(24);
5130 for (auto offset : { 0, 10, 20 } ) {
5131 canvas->drawTextOnPathHV(aero, len, path, 0, -offset, paint);
5132 canvas->translate(70 + offset, 70 + offset);
5133 }
5134 }
Cary Clark8032b982017-07-28 11:04:54 -04005135##
5136
5137#ToDo incomplete ##
5138
5139##
5140
5141# ------------------------------------------------------------------------------
5142
5143#Method void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
5144 const SkMatrix* matrix, const SkPaint& paint)
5145
5146Draw text on Path path, using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005147
Cary Clarkbad5ad72017-08-03 17:14:08 -04005148Origin of text is at beginning of path offset by matrix, if provided, before it
5149is mapped to path. If the path section corresponding the glyph advance is
5150curved, the glyph is drawn curved to match; control points in the glyph are
5151mapped to projected points parallel to the path. If the text's advance is larger
5152than the path length, the excess text is clipped.
5153
5154text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5155UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by
5156default text positions the first glyph's left side bearing at origin x and its
Cary Clark8032b982017-07-28 11:04:54 -04005157baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
5158
Cary Clarkbad5ad72017-08-03 17:14:08 -04005159All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5160Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
5161filled 12 point black glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005162
Cary Clarkbad5ad72017-08-03 17:14:08 -04005163#Param text character code points or glyphs drawn ##
5164#Param byteLength byte length of text array ##
5165#Param path Path providing text baseline ##
5166#Param matrix transform of glyphs before mapping to path; may be nullptr
Cary Clarka523d2d2017-08-30 08:58:10 -04005167 to use identity Matrix
Cary Clarkbad5ad72017-08-03 17:14:08 -04005168##
5169#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005170
5171#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005172 void draw(SkCanvas* canvas) {
5173 const char roller[] = "rollercoaster";
5174 const size_t len = sizeof(roller) - 1;
5175 SkPath path;
5176 path.cubicTo(40, -80, 120, 80, 160, -40);
5177 SkPaint paint;
5178 paint.setTextSize(32);
5179 paint.setStyle(SkPaint::kStroke_Style);
5180 SkMatrix matrix;
5181 matrix.setIdentity();
5182 for (int i = 0; i < 3; ++i) {
5183 canvas->translate(25, 60);
5184 canvas->drawPath(path, paint);
5185 canvas->drawTextOnPath(roller, len, path, &matrix, paint);
5186 matrix.preTranslate(0, 10);
5187 }
5188 }
Cary Clark8032b982017-07-28 11:04:54 -04005189##
5190
5191#ToDo incomplete ##
5192
5193##
5194
5195# ------------------------------------------------------------------------------
5196
5197#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
5198 const SkRect* cullRect, const SkPaint& paint)
5199
5200Draw text, transforming each glyph by the corresponding SkRSXform,
5201using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005202
Cary Clark8032b982017-07-28 11:04:54 -04005203RSXform array specifies a separate square scale, rotation, and translation for
5204each glyph.
Cary Clark8032b982017-07-28 11:04:54 -04005205
Cary Clarkbad5ad72017-08-03 17:14:08 -04005206Optional Rect cullRect is a conservative bounds of text, taking into account
5207RSXform and paint. If cullrect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005208
Cary Clarkbad5ad72017-08-03 17:14:08 -04005209All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5210Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
5211filled 12 point black glyphs.
5212
5213#Param text character code points or glyphs drawn ##
5214#Param byteLength byte length of text array ##
5215#Param xform RSXform rotates, scales, and translates each glyph individually ##
5216#Param cullRect Rect bounds of text for efficient clipping; or nullptr ##
5217#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005218
5219#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005220void draw(SkCanvas* canvas) {
5221 const int iterations = 26;
5222 SkRSXform transforms[iterations];
5223 char alphabet[iterations];
5224 SkScalar angle = 0;
5225 SkScalar scale = 1;
5226 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
5227 const SkScalar s = SkScalarSin(angle) * scale;
5228 const SkScalar c = SkScalarCos(angle) * scale;
5229 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
5230 angle += .45;
5231 scale += .2;
5232 alphabet[i] = 'A' + i;
5233 }
5234 SkPaint paint;
5235 paint.setTextAlign(SkPaint::kCenter_Align);
5236 canvas->translate(110, 138);
5237 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005238}
5239##
5240
5241#ToDo incomplete ##
5242
5243##
5244
5245# ------------------------------------------------------------------------------
5246
5247#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
5248
5249Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005250
Cary Clark8032b982017-07-28 11:04:54 -04005251blob contains glyphs, their positions, and paint attributes specific to text:
Cary Clarkbad5ad72017-08-03 17:14:08 -04005252Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X,
5253Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold,
5254Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
5255Subpixel_Text, and Paint_Vertical_Text.
Cary Clark8032b982017-07-28 11:04:54 -04005256
5257Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
5258Image_Filter, and Draw_Looper; apply to blob.
5259
Cary Clarkbad5ad72017-08-03 17:14:08 -04005260#Param blob glyphs, positions, and their paints' text size, typeface, and so on ##
5261#Param x horizontal offset applied to blob ##
5262#Param y vertical offset applied to blob ##
5263#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005264
5265#Example
5266#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04005267 void draw(SkCanvas* canvas) {
5268 SkTextBlobBuilder textBlobBuilder;
5269 const char bunny[] = "/(^x^)\\";
5270 const int len = sizeof(bunny) - 1;
5271 uint16_t glyphs[len];
5272 SkPaint paint;
5273 paint.textToGlyphs(bunny, len, glyphs);
5274 int runs[] = { 3, 1, 3 };
5275 SkPoint textPos = { 20, 100 };
5276 int glyphIndex = 0;
5277 for (auto runLen : runs) {
5278 paint.setTextSize(1 == runLen ? 20 : 50);
5279 const SkTextBlobBuilder::RunBuffer& run =
5280 textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
5281 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
5282 textPos.fX += paint.measureText(&bunny[glyphIndex], runLen, nullptr);
5283 glyphIndex += runLen;
5284 }
5285 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5286 paint.reset();
5287 canvas->drawTextBlob(blob.get(), 0, 0, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005288 }
5289##
5290
5291#ToDo incomplete ##
5292
5293##
5294
5295# ------------------------------------------------------------------------------
5296
5297#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
5298
5299Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005300
Cary Clark8032b982017-07-28 11:04:54 -04005301blob contains glyphs, their positions, and paint attributes specific to text:
Cary Clarkbad5ad72017-08-03 17:14:08 -04005302Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X,
5303Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold,
5304Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
5305Subpixel_Text, and Paint_Vertical_Text.
Cary Clark8032b982017-07-28 11:04:54 -04005306
5307Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
5308Image_Filter, and Draw_Looper; apply to blob.
5309
Cary Clarkbad5ad72017-08-03 17:14:08 -04005310#Param blob glyphs, positions, and their paints' text size, typeface, and so on ##
5311#Param x horizontal offset applied to blob ##
5312#Param y vertical offset applied to blob ##
5313#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005314
5315#Example
5316#Height 120
5317#Description
5318Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob.
5319Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
5320##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005321 void draw(SkCanvas* canvas) {
5322 SkTextBlobBuilder textBlobBuilder;
5323 SkPaint paint;
5324 paint.setTextSize(50);
5325 paint.setColor(SK_ColorRED);
5326 const SkTextBlobBuilder::RunBuffer& run =
5327 textBlobBuilder.allocRun(paint, 1, 20, 100);
5328 run.glyphs[0] = 20;
5329 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5330 paint.setTextSize(10);
5331 paint.setColor(SK_ColorBLUE);
5332 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5333 }
Cary Clark8032b982017-07-28 11:04:54 -04005334##
5335
5336#ToDo incomplete ##
5337
5338##
5339
5340# ------------------------------------------------------------------------------
5341
5342#Method void drawPicture(const SkPicture* picture)
5343
5344Draw Picture picture, using Clip and Matrix.
5345Clip and Matrix are unchanged by picture contents, as if
5346save() was called before and restore() was called after drawPicture.
5347
5348Picture records a series of draw commands for later playback.
5349
Cary Clarkbad5ad72017-08-03 17:14:08 -04005350#Param picture recorded drawing commands to play ##
Cary Clark8032b982017-07-28 11:04:54 -04005351
5352#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005353void draw(SkCanvas* canvas) {
5354 SkPictureRecorder recorder;
5355 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5356 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5357 SkPaint paint;
5358 paint.setColor(color);
5359 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5360 recordingCanvas->translate(10, 10);
5361 recordingCanvas->scale(1.2f, 1.4f);
5362 }
5363 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5364 const SkPicture* playbackPtr = playback.get();
5365 canvas->drawPicture(playback);
5366 canvas->scale(2, 2);
5367 canvas->translate(50, 0);
5368 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04005369}
5370##
5371
5372#ToDo incomplete ##
5373
5374##
5375
5376# ------------------------------------------------------------------------------
5377
5378#Method void drawPicture(const sk_sp<SkPicture>& picture)
5379
5380Draw Picture picture, using Clip and Matrix.
5381Clip and Matrix are unchanged by picture contents, as if
5382save() was called before and restore() was called after drawPicture.
5383
5384Picture records a series of draw commands for later playback.
5385
Cary Clarkbad5ad72017-08-03 17:14:08 -04005386#Param picture recorded drawing commands to play ##
Cary Clark8032b982017-07-28 11:04:54 -04005387
5388#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005389void draw(SkCanvas* canvas) {
5390 SkPictureRecorder recorder;
5391 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5392 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5393 SkPaint paint;
5394 paint.setColor(color);
5395 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5396 recordingCanvas->translate(10, 10);
5397 recordingCanvas->scale(1.2f, 1.4f);
5398 }
5399 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5400 canvas->drawPicture(playback);
5401 canvas->scale(2, 2);
5402 canvas->translate(50, 0);
5403 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04005404}
5405##
5406
5407#ToDo incomplete ##
5408
5409##
5410
5411# ------------------------------------------------------------------------------
5412
5413#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
5414
Cary Clarkbad5ad72017-08-03 17:14:08 -04005415Draw Picture picture, using Clip and Matrix; transforming picture with
5416Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
5417Image_Filter, and Blend_Mode, if provided.
Cary Clark8032b982017-07-28 11:04:54 -04005418
5419matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5420paint use is equivalent to: saveLayer, drawPicture, restore().
5421
Cary Clarkbad5ad72017-08-03 17:14:08 -04005422#Param picture recorded drawing commands to play ##
5423#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
5424#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005425
5426#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005427void draw(SkCanvas* canvas) {
5428 SkPaint paint;
5429 SkPictureRecorder recorder;
5430 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5431 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5432 paint.setColor(color);
5433 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5434 recordingCanvas->translate(10, 10);
5435 recordingCanvas->scale(1.2f, 1.4f);
5436 }
5437 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5438 const SkPicture* playbackPtr = playback.get();
5439 SkMatrix matrix;
5440 matrix.reset();
5441 for (auto alpha : { 70, 140, 210 } ) {
5442 paint.setAlpha(alpha);
5443 canvas->drawPicture(playbackPtr, &matrix, &paint);
5444 matrix.preTranslate(70, 70);
5445 }
Cary Clark8032b982017-07-28 11:04:54 -04005446}
5447##
5448
5449#ToDo incomplete ##
5450
5451##
5452
5453# ------------------------------------------------------------------------------
5454
5455#Method void drawPicture(const sk_sp<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 SkMatrix matrix;
5481 matrix.reset();
5482 for (auto alpha : { 70, 140, 210 } ) {
5483 paint.setAlpha(alpha);
5484 canvas->drawPicture(playback, &matrix, &paint);
5485 matrix.preTranslate(70, 70);
5486 }
Cary Clark8032b982017-07-28 11:04:54 -04005487}
5488##
5489
5490#ToDo incomplete ##
5491
5492##
5493
5494# ------------------------------------------------------------------------------
5495
5496#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
5497
5498Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005499If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
5500contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
Cary Clark8032b982017-07-28 11:04:54 -04005501
Cary Clarkbad5ad72017-08-03 17:14:08 -04005502#Param vertices triangle mesh to draw ##
5503#Param mode combines Vertices_Colors with Shader, if both are present ##
5504#Param paint specifies the Shader, used as Vertices texture; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005505
5506#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005507void draw(SkCanvas* canvas) {
5508 SkPaint paint;
5509 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5510 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5511 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5512 SK_ARRAY_COUNT(points), points, nullptr, colors);
5513 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
5514}
Cary Clark8032b982017-07-28 11:04:54 -04005515##
5516
5517#ToDo incomplete ##
5518
5519##
5520
5521# ------------------------------------------------------------------------------
5522
5523#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
5524
5525Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005526If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
5527contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
Cary Clark8032b982017-07-28 11:04:54 -04005528
Cary Clarkbad5ad72017-08-03 17:14:08 -04005529#Param vertices triangle mesh to draw ##
5530#Param mode combines Vertices_Colors with Shader, if both are present ##
5531#Param paint specifies the Shader, used as Vertices texture, may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005532
5533#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005534void draw(SkCanvas* canvas) {
5535 SkPaint paint;
5536 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5537 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
5538 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5539 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
5540 SkShader::kClamp_TileMode));
5541 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5542 SK_ARRAY_COUNT(points), points, texs, colors);
5543 canvas->drawVertices(vertices.get(), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005544}
5545##
5546
5547#ToDo incomplete ##
5548
5549##
5550
5551# ------------------------------------------------------------------------------
5552
5553#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5554 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
5555
5556Draw a cubic Coons patch: the interpolation of four cubics with shared corners,
5557associating a color, and optionally a texture coordinate, with each corner.
5558
Cary Clarkbad5ad72017-08-03 17:14:08 -04005559The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter,
5560Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
5561as the Coons patch texture; Blend_Mode mode combines Color colors and Shader if
5562both are provided.
Cary Clark8032b982017-07-28 11:04:54 -04005563
Cary Clarkbad5ad72017-08-03 17:14:08 -04005564Point array cubics specifies four cubics starting at the top left corner,
5565in clockwise order, sharing every fourth point. The last cubic ends at the
5566first point.
Cary Clark8032b982017-07-28 11:04:54 -04005567
Cary Clarkbad5ad72017-08-03 17:14:08 -04005568Color array color associates colors with corners in top left, top right,
5569bottom right, bottom left order.
5570
5571If paint contains Shader, Point array texCoords maps Shader as texture to
5572corners in top left, top right, bottom right, bottom left order.
5573
Cary Clarka523d2d2017-08-30 08:58:10 -04005574#Param cubics Path_Cubic array, sharing common points ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005575#Param colors Color array, one for each corner ##
5576#Param texCoords Point array of texure coordinates, mapping Shader to corners;
5577 may be nullptr
Cary Clark579985c2017-07-31 11:48:27 -04005578#Param ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005579#Param mode Blend_Mode for colors, and for Shader if paint has one ##
5580#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005581
5582#Example
5583#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04005584void draw(SkCanvas* canvas) {
5585 // SkBitmap source = cmbkygk;
5586 SkPaint paint;
5587 paint.setFilterQuality(kLow_SkFilterQuality);
5588 paint.setAntiAlias(true);
5589 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5590 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5591 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5592 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5593 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
5594 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
5595 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5596 SkShader::kClamp_TileMode, nullptr));
5597 canvas->scale(15, 15);
5598 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
5599 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
5600 canvas->translate(4, 4);
5601 }
Cary Clark8032b982017-07-28 11:04:54 -04005602}
5603##
5604
Cary Clarkbad5ad72017-08-03 17:14:08 -04005605#ToDo incomplete; can patch use image filter? ##
Cary Clark8032b982017-07-28 11:04:54 -04005606
5607##
5608
5609# ------------------------------------------------------------------------------
5610
5611#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5612 const SkPoint texCoords[4], const SkPaint& paint)
5613
5614Draw a cubic Coons patch: the interpolation of four cubics with shared corners,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005615associating a color, and optionally a texture coordinate, with each corner.
Cary Clark8032b982017-07-28 11:04:54 -04005616
Cary Clarkbad5ad72017-08-03 17:14:08 -04005617The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter,
5618Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
5619as the Coons patch texture; Blend_Mode mode combines Color colors and Shader if
5620both are provided.
Cary Clark8032b982017-07-28 11:04:54 -04005621
Cary Clarkbad5ad72017-08-03 17:14:08 -04005622Point array cubics specifies four cubics starting at the top left corner,
5623in clockwise order, sharing every fourth point. The last cubic ends at the
5624first point.
5625
5626Color array color associates colors with corners in top left, top right,
5627bottom right, bottom left order.
5628
5629If paint contains Shader, Point array texCoords maps Shader as texture to
5630corners in top left, top right, bottom right, bottom left order.
5631
Cary Clarka523d2d2017-08-30 08:58:10 -04005632#Param cubics Path_Cubic array, sharing common points ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005633#Param colors Color array, one for each corner ##
5634#Param texCoords Point array of texure coordinates, mapping Shader to corners;
5635 may be nullptr
Cary Clark579985c2017-07-31 11:48:27 -04005636#Param ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005637#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005638
5639#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005640void draw(SkCanvas* canvas) {
5641 SkPaint paint;
5642 paint.setAntiAlias(true);
5643 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5644 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5645 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5646 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5647 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5648 canvas->scale(30, 30);
5649 canvas->drawPatch(cubics, colors, nullptr, paint);
5650 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
5651 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
5652 {0.5f,3.2f} };
5653 paint.setTextSize(18.f / 30);
5654 paint.setTextAlign(SkPaint::kCenter_Align);
5655 for (int i = 0; i< 10; ++i) {
5656 char digit = '0' + i;
5657 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
5658 }
5659 canvas->drawString("10", text[10].fX, text[10].fY, paint);
5660 canvas->drawString("11", text[11].fX, text[11].fY, paint);
5661 paint.setStyle(SkPaint::kStroke_Style);
5662 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
5663 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005664}
5665##
5666
5667#Example
5668#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04005669void draw(SkCanvas* canvas) {
5670 // SkBitmap source = checkerboard;
5671 SkPaint paint;
5672 paint.setFilterQuality(kLow_SkFilterQuality);
5673 paint.setAntiAlias(true);
5674 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5675 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5676 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5677 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5678 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
5679 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5680 SkShader::kClamp_TileMode, nullptr));
5681 canvas->scale(30, 30);
5682 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005683}
5684##
5685
Cary Clarkbad5ad72017-08-03 17:14:08 -04005686#ToDo incomplete; can patch use image filter? ##
Cary Clark8032b982017-07-28 11:04:54 -04005687
5688##
5689
5690# ------------------------------------------------------------------------------
5691
5692#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
5693 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5694 const SkPaint* paint)
5695
5696Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005697paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5698to draw, if present. For each entry in the array, Rect tex locates sprite in
5699atlas, and RSXform xform transforms it into destination space.
5700
Cary Clark8032b982017-07-28 11:04:54 -04005701xform, text, and colors if present, must contain count entries.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005702Optional colors are applied for each sprite using Blend_Mode.
Cary Clark8032b982017-07-28 11:04:54 -04005703Optional cullRect is a conservative bounds of all transformed sprites.
5704If cullrect is outside of Clip, canvas can skip drawing.
5705
Cary Clarkbad5ad72017-08-03 17:14:08 -04005706#Param atlas Image containing sprites ##
5707#Param xform RSXform mappings for sprites in atlas ##
5708#Param tex Rect locations of sprites in atlas ##
5709#Param colors Color, one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
5710#Param count number of sprites to draw ##
5711#Param mode Blend_Mode combining colors and sprites ##
5712#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5713#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005714
5715#Example
5716#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005717void draw(SkCanvas* canvas) {
5718 // SkBitmap source = mandrill;
5719 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5720 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5721 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5722 const SkImage* imagePtr = image.get();
5723 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005724}
5725##
5726
5727#ToDo incomplete ##
5728
5729##
5730
5731# ------------------------------------------------------------------------------
5732
5733#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5734 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5735 const SkPaint* paint)
5736
5737Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005738paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5739to draw, if present. For each entry in the array, Rect tex locates sprite in
5740atlas, and RSXform xform transforms it into destination space.
5741
Cary Clark8032b982017-07-28 11:04:54 -04005742xform, text, and colors if present, must contain count entries.
5743Optional colors is applied for each sprite using Blend_Mode.
5744Optional cullRect is a conservative bounds of all transformed sprites.
5745If cullrect is outside of Clip, canvas can skip drawing.
5746
Cary Clarkbad5ad72017-08-03 17:14:08 -04005747#Param atlas Image containing sprites ##
5748#Param xform RSXform mappings for sprites in atlas ##
5749#Param tex Rect locations of sprites in atlas ##
5750#Param colors Color, one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
5751#Param count number of sprites to draw ##
5752#Param mode Blend_Mode combining colors and sprites ##
5753#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5754#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005755
5756#Example
5757#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005758void draw(SkCanvas* canvas) {
5759 // SkBitmap source = mandrill;
5760 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5761 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5762 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5763 SkPaint paint;
5764 paint.setAlpha(127);
5765 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04005766}
5767##
5768
5769#ToDo bug in example on cpu side, gpu looks ok ##
5770
5771##
5772
5773# ------------------------------------------------------------------------------
5774
5775#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
5776 const SkRect* cullRect, const SkPaint* paint)
5777
5778Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005779paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5780to draw, if present. For each entry in the array, Rect tex locates sprite in
5781atlas, and RSXform xform transforms it into destination space.
5782
Cary Clark8032b982017-07-28 11:04:54 -04005783xform and text must contain count entries.
5784Optional cullRect is a conservative bounds of all transformed sprites.
5785If cullrect is outside of Clip, canvas can skip drawing.
5786
Cary Clarkbad5ad72017-08-03 17:14:08 -04005787#Param atlas Image containing sprites ##
5788#Param xform RSXform mappings for sprites in atlas ##
5789#Param tex Rect locations of sprites in atlas ##
5790#Param count number of sprites to draw ##
5791#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5792#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005793
5794#Example
5795#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005796void draw(SkCanvas* canvas) {
5797 // sk_sp<SkImage> image = mandrill;
5798 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5799 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5800 const SkImage* imagePtr = image.get();
5801 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005802}
5803##
5804
5805#ToDo incomplete ##
5806
5807##
5808
5809# ------------------------------------------------------------------------------
5810
5811#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5812 int count, const SkRect* cullRect, const SkPaint* paint)
5813
5814Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005815paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5816to draw, if present. For each entry in the array, Rect tex locates sprite in
5817atlas, and RSXform xform transforms it into destination space.
5818
Cary Clark8032b982017-07-28 11:04:54 -04005819xform and text must contain count entries.
5820Optional cullRect is a conservative bounds of all transformed sprites.
5821If cullrect is outside of Clip, canvas can skip drawing.
5822
Cary Clarkbad5ad72017-08-03 17:14:08 -04005823#Param atlas Image containing sprites ##
5824#Param xform RSXform mappings for sprites in atlas ##
5825#Param tex Rect locations of sprites in atlas ##
5826#Param count number of sprites to draw ##
5827#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5828#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005829
5830#Example
5831#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005832void draw(SkCanvas* canvas) {
5833 // sk_sp<SkImage> image = mandrill;
5834 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
5835 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
5836 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005837}
5838##
5839
5840#ToDo incomplete ##
5841
5842##
5843
5844# ------------------------------------------------------------------------------
5845
Cary Clark73fa9722017-08-29 17:36:51 -04005846#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04005847
5848Draw Drawable drawable using Clip and Matrix, concatenated with
5849optional matrix.
5850
5851If Canvas has an asynchronous implementation, as is the case
5852when it is recording into Picture, then drawable will be referenced,
5853so that SkDrawable::draw() can be called when the operation is finalized. To force
5854immediate drawing, call SkDrawable::draw() instead.
5855
Cary Clarkbad5ad72017-08-03 17:14:08 -04005856#Param drawable custom struct encapsulating drawing commands ##
5857#Param matrix transformation applied to drawing; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005858
5859#Example
5860#Height 100
5861#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04005862struct MyDrawable : public SkDrawable {
5863 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5864
5865 void onDraw(SkCanvas* canvas) override {
5866 SkPath path;
5867 path.conicTo(10, 90, 50, 90, 0.9f);
5868 SkPaint paint;
5869 paint.setColor(SK_ColorBLUE);
5870 canvas->drawRect(path.getBounds(), paint);
5871 paint.setAntiAlias(true);
5872 paint.setColor(SK_ColorWHITE);
5873 canvas->drawPath(path, paint);
5874 }
5875};
5876
5877#Function ##
5878void draw(SkCanvas* canvas) {
5879 sk_sp<SkDrawable> drawable(new MyDrawable);
5880 SkMatrix matrix;
5881 matrix.setTranslate(10, 10);
5882 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04005883}
5884##
5885
5886#ToDo incomplete ##
5887
5888##
5889
5890# ------------------------------------------------------------------------------
5891
5892#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
5893
5894Draw Drawable drawable using Clip and Matrix, offset by (x, y).
5895
5896If Canvas has an asynchronous implementation, as is the case
5897when it is recording into Picture, then drawable will be referenced,
5898so that SkDrawable::draw() can be called when the operation is finalized. To force
5899immediate drawing, call SkDrawable::draw() instead.
5900
Cary Clarkbad5ad72017-08-03 17:14:08 -04005901#Param drawable custom struct encapsulating drawing commands ##
5902#Param x offset into Canvas writable pixels in x ##
5903#Param y offset into Canvas writable pixels in y ##
Cary Clark8032b982017-07-28 11:04:54 -04005904
5905#Example
5906#Height 100
5907#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04005908struct MyDrawable : public SkDrawable {
5909 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5910
5911 void onDraw(SkCanvas* canvas) override {
5912 SkPath path;
5913 path.conicTo(10, 90, 50, 90, 0.9f);
5914 SkPaint paint;
5915 paint.setColor(SK_ColorBLUE);
5916 canvas->drawRect(path.getBounds(), paint);
5917 paint.setAntiAlias(true);
5918 paint.setColor(SK_ColorWHITE);
5919 canvas->drawPath(path, paint);
5920 }
5921};
5922
5923#Function ##
5924void draw(SkCanvas* canvas) {
5925 sk_sp<SkDrawable> drawable(new MyDrawable);
5926 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04005927}
5928##
5929
5930#ToDo incomplete ##
5931
5932##
5933
5934# ------------------------------------------------------------------------------
5935
5936#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
5937
5938Associate Rect on Canvas when an annotation; a key-value pair, where the key is
5939a null-terminated utf8 string, and optional value is stored as Data.
5940
5941Only some canvas implementations, such as recording to Picture, or drawing to
5942Document_PDF, use annotations.
5943
Cary Clarkbad5ad72017-08-03 17:14:08 -04005944#Param rect Rect extent of canvas to annotate ##
5945#Param key string used for lookup ##
5946#Param value data holding value stored in annotation ##
Cary Clark8032b982017-07-28 11:04:54 -04005947
5948#Example
5949 #Height 1
5950 const char text[] = "Click this link!";
5951 SkRect bounds;
5952 SkPaint paint;
5953 paint.setTextSize(40);
5954 (void)paint.measureText(text, strlen(text), &bounds);
5955 const char url[] = "https://www.google.com/";
5956 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
5957 canvas->drawAnnotation(bounds, "url_key", urlData.get());
5958##
5959
5960#ToDo incomplete ##
5961
5962##
5963
5964# ------------------------------------------------------------------------------
5965
5966#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
5967
5968Associate Rect on Canvas when an annotation; a key-value pair, where the key is
5969a null-terminated utf8 string, and optional value is stored as Data.
5970
5971Only some canvas implementations, such as recording to Picture, or drawing to
5972Document_PDF, use annotations.
5973
Cary Clarkbad5ad72017-08-03 17:14:08 -04005974#Param rect Rect extent of canvas to annotate ##
5975#Param key string used for lookup ##
5976#Param value data holding value stored in annotation ##
Cary Clark8032b982017-07-28 11:04:54 -04005977
5978#Example
5979#Height 1
5980 const char text[] = "Click this link!";
5981 SkRect bounds;
5982 SkPaint paint;
5983 paint.setTextSize(40);
5984 (void)paint.measureText(text, strlen(text), &bounds);
5985 const char url[] = "https://www.google.com/";
5986 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
5987 canvas->drawAnnotation(bounds, "url_key", urlData.get());
5988##
5989
5990#ToDo incomplete ##
5991
5992##
5993
5994#Method SkDrawFilter* getDrawFilter() const
5995
5996Legacy call to be deprecated.
5997
5998#Deprecated
5999##
6000
6001##
6002
6003#Method virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter)
6004
6005Legacy call to be deprecated.
6006
6007#Deprecated
6008##
6009
6010##
6011
6012# ------------------------------------------------------------------------------
6013
6014#Method virtual bool isClipEmpty() const
6015
6016Returns true if Clip is empty; that is, nothing will draw.
6017
Cary Clarkbad5ad72017-08-03 17:14:08 -04006018May do work when called; it should not be called
Cary Clark8032b982017-07-28 11:04:54 -04006019more often than needed. However, once called, subsequent calls perform no
6020work until Clip changes.
6021
Cary Clarkbad5ad72017-08-03 17:14:08 -04006022#Return true if Clip is empty ##
Cary Clark8032b982017-07-28 11:04:54 -04006023
6024#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04006025 void draw(SkCanvas* canvas) {
6026 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
6027 SkPath path;
6028 canvas->clipPath(path);
6029 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04006030 }
6031 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04006032 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04006033 clip is empty
6034 ##
6035##
6036
6037#ToDo incomplete ##
6038
6039##
6040
6041# ------------------------------------------------------------------------------
6042
6043#Method virtual bool isClipRect() const
6044
6045Returns true if Clip is Rect and not empty.
6046Returns false if the clip is empty, or if it is not Rect.
6047
Cary Clarkbad5ad72017-08-03 17:14:08 -04006048#Return true if Clip is Rect and not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04006049
6050#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04006051 void draw(SkCanvas* canvas) {
6052 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
6053 canvas->clipRect({0, 0, 0, 0});
6054 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04006055 }
6056 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04006057 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04006058 clip is not rect
6059 ##
6060##
6061
6062#ToDo incomplete ##
6063
6064##
6065
6066#Class SkCanvas ##
6067#Topic Canvas ##