blob: ae351421a51bcce3003c801f7017de1430150900 [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.
Cary Clarkce101242017-09-01 15:51:02 -040019Document based Canvas and other Canvas Subclasses reference Device describing the
Cary Clarkbad5ad72017-08-03 17:14:08 -040020destination.
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. ##
Cary Clarkce101242017-09-01 15:51:02 -040056# SaveLayerRec # Contains state to create Layer. ##
Cary Clark8032b982017-07-28 11:04:54 -040057#Table ##
58#Subtopic ##
59
60#Subtopic Constructors
61
62Create the desired type of Surface to obtain its Canvas when possible. Constructors are useful
63when no Surface is required, and some helpers implicitly create Raster_Surface.
64
65#Table
66#Legend
67# # description ##
68#Legend ##
69# SkCanvas() # No Surface, no dimensions. ##
Cary Clark73fa9722017-08-29 17:36:51 -040070# SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr) # No Surface, set dimensions, Surface_Properties. ##
Cary Clark8032b982017-07-28 11:04:54 -040071# SkCanvas(SkBaseDevice* device) # Existing Device. (SkBaseDevice is private.) ##
72# SkCanvas(const SkBitmap& bitmap) # Uses existing Bitmap. ##
73# SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) # Uses existing Bitmap and Surface_Properties. ##
74# MakeRasterDirect # Creates from SkImageInfo and Pixel_Storage. ##
75# MakeRasterDirectN32 # Creates from image data and Pixel_Storage. ##
76#ToDo incomplete ##
77#Table ##
78#Subtopic ##
79
80#Subtopic Member_Functions
81#Table
82#Legend
83# function # description ##
84#Legend ##
85# accessTopLayerPixels # Returns writable pixel access if available. ##
86# accessTopRasterHandle # Returns context that tracks Clip and Matrix. ##
87# clear() # Fills Clip with Color. ##
88# clipPath # Combines Clip with Path. ##
89# clipRRect # Combines Clip with Round_Rect. ##
90# clipRect # Combines Clip with Rect. ##
91# clipRegion # Combines Clip with Region. ##
92# concat() # Multiplies Matrix by Matrix. ##
93# discard() # Makes Canvas contents undefined. ##
94# drawAnnotation # Associates a Rect with a key-value pair.##
95# drawArc # Draws Arc using Clip, Matrix, and Paint.##
96# drawAtlas # Draws sprites using Clip, Matrix, and Paint.##
97# drawBitmap # Draws Bitmap at (x, y) position. ##
Cary Clarkd0530ba2017-09-14 11:25:39 -040098# drawBitmapLattice # Draws proportionally stretched Bitmap. ##
Cary Clark8032b982017-07-28 11:04:54 -040099# drawBitmapNine # Draws Nine_Patch Bitmap. ##
100# drawBitmapRect # Draws Bitmap, source Rect to destination Rect. ##
101# drawCircle # Draws Circle using Clip, Matrix, and Paint. ##
102# drawColor # Fills Clip with Color and Blend_Mode. ##
103# drawDRRect # Draws double Round_Rect stroked or filled. ##
104# drawDrawable # Draws Drawable, encapsulated drawing commands. ##
105# drawIRect # Draws IRect using Clip, Matrix, and Paint. ##
106# drawImage # Draws Image at (x, y) position. ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400107# drawImageLattice # Draws proportionally stretched Image. ##
Cary Clark8032b982017-07-28 11:04:54 -0400108# drawImageNine # Draws Nine_Patch Image. ##
109# drawImageRect # Draws Image, source Rect to destination Rect. ##
110# drawLine # Draws line segment between two points.##
111# drawOval # Draws Oval using Clip, Matrix, and Paint. ##
112# drawPaint # Fills Clip with Paint. ##
Cary Clarkce101242017-09-01 15:51:02 -0400113# drawPatch # Draws Coons patch. ##
Cary Clark8032b982017-07-28 11:04:54 -0400114# drawPath # Draws Path using Clip, Matrix, and Paint. ##
115# drawPicture # Draws Picture using Clip and Matrix. ##
116# drawPoint # Draws point at (x, y) position. ##
117# drawPoints # Draws array as points, lines, polygon. ##
118# drawPosText # Draws text at array of (x, y) positions. ##
119# drawPosTextH # Draws text at x positions with common baseline. ##
120# drawRRect # Draws Round_Rect using Clip, Matrix, and Paint. ##
121# drawRect # Draws Rect using Clip, Matrix, and Paint. ##
122# drawRegion # Draws Region using Clip, Matrix, and Paint. ##
123# drawRoundRect # Draws Round_Rect using Clip, Matrix, and Paint. ##
124# drawText # Draws text at (x, y), using font advance. ##
125# drawTextBlob # Draws text with arrays of positions and Paint. ##
126# drawTextOnPath # Draws text following Path contour. ##
127# drawTextOnPathHV # Draws text following Path with offsets. ##
128# drawTextRSXform # Draws text with array of RSXform. ##
129# drawString # Draws null terminated string at (x, y) using font advance. ##
130# drawVertices # Draws Vertices, a triangle mesh. ##
131# flush() # Triggers execution of all pending draw operations. ##
Cary Clarkce101242017-09-01 15:51:02 -0400132# getBaseLayerSize # Gets size of base Layer in global coordinates. ##
Cary Clark8032b982017-07-28 11:04:54 -0400133# getDeviceClipBounds # Returns IRect bounds of Clip. ##
134# getDrawFilter # Legacy; to be deprecated. ##
135# getGrContext # Returns GPU_Context of the GPU_Surface. ##
136# getLocalClipBounds # Returns Clip bounds in source coordinates. ##
137# getMetaData # Associates additional data with the canvas. ##
138# getProps # Copies Surface_Properties if available. ##
139# getSaveCount # Returns depth of stack containing Clip and Matrix. ##
140# getTotalMatrix # Returns Matrix. ##
141# imageInfo # Returns Image_Info for Canvas. ##
142# isClipEmpty # Returns if Clip is empty. ##
143# isClipRect # Returns if Clip is Rect and not empty. ##
144# MakeRasterDirect # Creates Canvas from SkImageInfo and pixel data. ##
145# MakeRasterDirectN32 # Creates Canvas from image specifications and pixel data. ##
146# makeSurface # Creates Surface matching SkImageInfo and SkSurfaceProps. ##
147# peekPixels # Returns if Canvas has direct access to its pixels. ##
148# quickReject # Returns if Rect is outside Clip. ##
149# readPixels # Copies and converts rectangle of pixels from Canvas. ##
150# resetMatrix # Resets Matrix to identity. ##
151# restore() # Restores changes to Clip and Matrix, pops save stack. ##
152# restoreToCount # Restores changes to Clip and Matrix to given depth. ##
153# rotate() # Rotates Matrix. ##
154# save() # Saves Clip and Matrix on stack. ##
Cary Clarkce101242017-09-01 15:51:02 -0400155# saveLayer # Saves Clip and Matrix on stack; creates Layer. ##
156# saveLayerAlpha # Saves Clip and Matrix on stack; creates Layer; sets opacity. ##
157# saveLayerPreserveLCDTextRequests # Saves Clip and Matrix on stack; creates Layer for LCD text. ##
Cary Clark8032b982017-07-28 11:04:54 -0400158# scale() # Scales Matrix. ##
159# setAllowSimplifyClip # Experimental. ##
160# setDrawFilter # Legacy; to be deprecated. ##
161# setMatrix # Sets Matrix. ##
162# skew() # Skews Matrix. #
163# translate() # Translates Matrix. ##
164# writePixels # Copies and converts rectangle of pixels to Canvas. ##
165#Table ##
166#Subtopic ##
167
168#Topic Overview ##
169
170# ------------------------------------------------------------------------------
171
172#Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info,
173 void* pixels, size_t rowBytes)
174
Cary Clarkbad5ad72017-08-03 17:14:08 -0400175Allocates raster Canvas that will draw directly into pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400176To access pixels after drawing, call flush() or peekPixels.
177
Cary Clarkbad5ad72017-08-03 17:14:08 -0400178Canvas is returned if all parameters are valid.
179Valid parameters include:
180info dimensions are zero or positive;
181info contains Image_Color_Type and Image_Alpha_Type supported by Raster_Surface;
182pixels is not nullptr;
183rowBytes is zero or large enough to contain info width pixels of Image_Color_Type.
184
Cary Clarkf05bdda2017-08-24 12:59:48 -0400185Pass zero for rowBytes to compute rowBytes from info width and size of pixel.
186If rowBytes is greater than zero, it must be equal to or greater than
187info width times bytes required for Image_Color_Type.
188
189Pixel buffer size should be info height times computed rowBytes.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400190
191#Param info width, height, Image_Color_Type, Image_Alpha_Type, Color_Space, of Raster_Surface;
192 width, or height, or both, may be zero
Cary Clark8032b982017-07-28 11:04:54 -0400193##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400194#Param pixels pointer to destination pixels buffer
Cary Clark8032b982017-07-28 11:04:54 -0400195##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400196#Param rowBytes interval from one Surface row to the next, or zero
Cary Clark8032b982017-07-28 11:04:54 -0400197##
198
Cary Clarkbad5ad72017-08-03 17:14:08 -0400199#Return Canvas if all parameters are valid; otherwise, nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -0400200
201#Example
202 #Description
203 Allocates a three by three bitmap, clears it to white, and draws a black pixel
204 in the center.
205 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400206void draw(SkCanvas* ) {
Cary Clarkce101242017-09-01 15:51:02 -0400207 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied
Cary Clarkbad5ad72017-08-03 17:14:08 -0400208 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row
209 const size_t size = info.getSafeSize(minRowBytes); // bytes used by all rows
210 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels
211 SkPMColor* pixels = storage.get(); // get pointer to allocated storage
212 // create a SkCanvas backed by a raster device, and delete it when the
213 // function goes out of scope.
214 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
Cary Clarkce101242017-09-01 15:51:02 -0400215 canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clarkbad5ad72017-08-03 17:14:08 -0400216 canvas->flush(); // ensure that pixels are cleared
Cary Clarkce101242017-09-01 15:51:02 -0400217 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clarkbad5ad72017-08-03 17:14:08 -0400218 SkPaint paint; // by default, draws black
219 canvas->drawPoint(1, 1, paint); // draw in the center
220 canvas->flush(); // ensure that point was drawn
221 for (int y = 0; y < info.height(); ++y) {
222 for (int x = 0; x < info.width(); ++x) {
223 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
224 }
225 SkDebugf("\n");
226 }
Cary Clark8032b982017-07-28 11:04:54 -0400227}
228 #StdOut
229 ---
230 -x-
231 ---
232 ##
233##
234
235#ToDo incomplete ##
236
237#SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
238##
239
240# ------------------------------------------------------------------------------
241
242#Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
243 size_t rowBytes)
244
Cary Clarkbad5ad72017-08-03 17:14:08 -0400245Allocates raster Canvas specified by inline image specification. Subsequent Canvas
246calls draw into pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400247Image_Color_Type is set to kN32_SkColorType.
248Image_Alpha_Type is set to kPremul_SkAlphaType.
249To access pixels after drawing, call flush() or peekPixels.
250
Cary Clarkbad5ad72017-08-03 17:14:08 -0400251Canvas is returned if all parameters are valid.
252Valid parameters include:
Cary Clarkf05bdda2017-08-24 12:59:48 -0400253width and height are zero or positive;
Cary Clarkbad5ad72017-08-03 17:14:08 -0400254pixels is not nullptr;
Cary Clarkf05bdda2017-08-24 12:59:48 -0400255rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400256
Cary Clarkce101242017-09-01 15:51:02 -0400257Pass zero for rowBytes to compute rowBytes from width and size of pixel.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400258If rowBytes is greater than zero, it must be equal to or greater than
259width times bytes required for Image_Color_Type.
260
261Pixel buffer size should be height times rowBytes.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400262
263#Param width pixel column count on Raster_Surface created; must be zero or greater ##
264#Param height pixel row count on Raster_Surface created.; must be zero or greater ##
265#Param pixels pointer to destination pixels buffer; buffer size should be height
Cary Clarkf05bdda2017-08-24 12:59:48 -0400266 times rowBytes
Cary Clark8032b982017-07-28 11:04:54 -0400267##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400268#Param rowBytes interval from one Surface row to the next, or zero
Cary Clark8032b982017-07-28 11:04:54 -0400269##
270
Cary Clarkbad5ad72017-08-03 17:14:08 -0400271#Return Canvas if all parameters are valid; otherwise, nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -0400272
273#Example
274 #Description
275 Allocates a three by three bitmap, clears it to white, and draws a black pixel
276 in the center.
277 ##
278void draw(SkCanvas* ) {
279 const int width = 3;
280 const int height = 3;
Cary Clarkce101242017-09-01 15:51:02 -0400281 SkPMColor pixels[height][width]; // allocate a 3x3 Premultiplied bitmap on the stack
Cary Clark8032b982017-07-28 11:04:54 -0400282 // create a SkCanvas backed by a raster device, and delete it when the
283 // function goes out of scope.
284 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
285 width,
286 height,
287 pixels[0], // top left of the bitmap
288 sizeof(pixels[0])); // byte width of the each row
Cary Clarkce101242017-09-01 15:51:02 -0400289 // write a premultiplied value for white into all pixels in the bitmap
Cary Clark8032b982017-07-28 11:04:54 -0400290 canvas->clear(SK_ColorWHITE);
Cary Clarkce101242017-09-01 15:51:02 -0400291 SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400292 SkPaint paint; // by default, draws black
293 canvas->drawPoint(1, 1, paint); // draw in the center
294 canvas->flush(); // ensure that pixels is ready to be read
295 for (int y = 0; y < height; ++y) {
296 for (int x = 0; x < width; ++x) {
297 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
298 }
299 SkDebugf("\n");
300 }
301}
302 #StdOut
303 ---
304 -x-
305 ---
306 ##
307##
308
309#ToDo incomplete ##
310
311##
312
313# ------------------------------------------------------------------------------
314
315#Method SkCanvas()
316
Cary Clarkd0530ba2017-09-14 11:25:39 -0400317Creates an empty Canvas with no backing device or pixels, with
Cary Clarkf05bdda2017-08-24 12:59:48 -0400318a width and height of zero.
Cary Clark8032b982017-07-28 11:04:54 -0400319
Cary Clarkd0530ba2017-09-14 11:25:39 -0400320#Return empty Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400321
322#Example
323
324#Description
325Passes a placeholder to a function that requires one.
326##
327
328#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -0400329// Returns true if either the canvas rotates the text by 90 degrees, or the paint does.
330static void check_for_up_and_down_text(const SkCanvas* canvas, const SkPaint& paint) {
331 bool paintHasVertical = paint.isVerticalText();
332 const SkMatrix& matrix = canvas->getTotalMatrix();
333 bool matrixIsVertical = matrix.preservesRightAngles() && !matrix.isScaleTranslate();
334 SkDebugf("paint draws text %s\n", paintHasVertical != matrixIsVertical ?
335 "top to bottom" : "left to right");
336}
337
338static void check_for_up_and_down_text(const SkPaint& paint) {
339 SkCanvas canvas; // placeholder only, does not have an associated device
340 check_for_up_and_down_text(&canvas, paint);
341}
342
Cary Clark8032b982017-07-28 11:04:54 -0400343##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400344void draw(SkCanvas* canvas) {
345 SkPaint paint;
346 check_for_up_and_down_text(paint); // paint draws text left to right
347 paint.setVerticalText(true);
348 check_for_up_and_down_text(paint); // paint draws text top to bottom
349 paint.setVerticalText(false);
350 canvas->rotate(90);
351 check_for_up_and_down_text(canvas, paint); // paint draws text top to bottom
352}
Cary Clark8032b982017-07-28 11:04:54 -0400353
354 #StdOut
355 paint draws text left to right
356 paint draws text top to bottom
357 paint draws text top to bottom
358 ##
359##
360
361#ToDo incomplete ##
362
363##
364
365# ------------------------------------------------------------------------------
366
Cary Clark73fa9722017-08-29 17:36:51 -0400367#Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -0400368
369Creates Canvas of the specified dimensions without a Surface.
Cary Clarkce101242017-09-01 15:51:02 -0400370Used by Subclasses with custom implementations for draw methods.
Cary Clark8032b982017-07-28 11:04:54 -0400371
Cary Clarkd0530ba2017-09-14 11:25:39 -0400372If props equals nullptr, Surface_Properties are created with
373Surface_Properties_Legacy_Font_Host settings, which choose the pixel striping
374direction and order. Since a platform may dynamically change its direction when
375the device is rotated, and since a platform may have multiple monitors with
376different characteristics, it is best not to rely on this legacy behavior.
Cary Clark8032b982017-07-28 11:04:54 -0400377
Cary Clarkbad5ad72017-08-03 17:14:08 -0400378#Param width zero or greater ##
379#Param height zero or greater ##
380#Param props LCD striping orientation and setting for device independent fonts;
381 may be nullptr
382##
383
384#Return Canvas placeholder with dimensions ##
Cary Clark8032b982017-07-28 11:04:54 -0400385
386#Example
387 SkCanvas canvas(10, 20); // 10 units wide, 20 units high
388 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device
389 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
390
391 #StdOut
392 canvas is empty
393 ##
394##
395
Cary Clarkbad5ad72017-08-03 17:14:08 -0400396#SeeAlso SkSurfaceProps SkPixelGeometry
Cary Clark8032b982017-07-28 11:04:54 -0400397
398##
399
400# ------------------------------------------------------------------------------
401
402#Method explicit SkCanvas(SkBaseDevice* device)
403
404Construct a canvas that draws into device.
405Used by child classes of SkCanvas.
406
407#ToDo Since SkBaseDevice is private, shouldn't this be private also? ##
408
Cary Clarkbad5ad72017-08-03 17:14:08 -0400409#Param device specifies a device for the canvas to draw into ##
Cary Clark8032b982017-07-28 11:04:54 -0400410
Cary Clarkbad5ad72017-08-03 17:14:08 -0400411#Return Canvas that can be used to draw into device ##
Cary Clark8032b982017-07-28 11:04:54 -0400412
413#Example
414#Error "Unsure how to create a meaningful example."
415 SkPDFCanvas::SkPDFCanvas(const sk_sp<SkPDFDevice>& dev)
416 : SkCanvas(dev.get()) {}
417##
418
419#ToDo either remove doc of figure out a way to fiddle it ##
420
421##
422
423# ------------------------------------------------------------------------------
424
425#Method explicit SkCanvas(const SkBitmap& bitmap)
426
427Construct a canvas that draws into bitmap.
428Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed Surface.
429
Cary Clarkbad5ad72017-08-03 17:14:08 -0400430Bitmap is copied so that subsequently editing bitmap will not affect
431constructed Canvas.
432
433May be deprecated in the future.
434
Cary Clark8032b982017-07-28 11:04:54 -0400435#ToDo Should be deprecated? ##
436
Cary Clarkbad5ad72017-08-03 17:14:08 -0400437#Param bitmap width, height, Image_Color_Type, Image_Alpha_Type, and pixel
438 storage of Raster_Surface
Cary Clark8032b982017-07-28 11:04:54 -0400439##
440
Cary Clarkbad5ad72017-08-03 17:14:08 -0400441#Return Canvas that can be used to draw into bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -0400442
443#Example
444#Description
445The actual output depends on the installed fonts.
446##
447 SkBitmap bitmap;
448 // create a bitmap 5 wide and 11 high
449 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
450 SkCanvas canvas(bitmap);
Cary Clarkce101242017-09-01 15:51:02 -0400451 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400452 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
453 if (!canvas.peekPixels(&pixmap)) {
454 SkDebugf("peekPixels should never fail.\n");
455 }
456 const SkPMColor* pixels = pixmap.addr32(); // points to top left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400457 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400458 SkPaint paint; // by default, draws black, 12 point text
459 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
460 for (int y = 0; y < bitmap.height(); ++y) {
461 for (int x = 0; x < bitmap.width(); ++x) {
462 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
463 }
464 SkDebugf("\n");
465 }
466
467 #StdOut
Cary Clarkd0530ba2017-09-14 11:25:39 -0400468 -----
469 ---x-
470 ---x-
471 ---x-
472 ---x-
473 ---x-
474 ---x-
475 -----
476 ---x-
477 ---x-
Cary Clark8032b982017-07-28 11:04:54 -0400478 -----
479 #StdOut ##
480##
481
482#ToDo incomplete ##
483
484##
485
Cary Clarkbad5ad72017-08-03 17:14:08 -0400486#EnumClass ColorBehavior
Cary Clark8032b982017-07-28 11:04:54 -0400487
488#Private
489Android framework only.
490##
491
492#Code
493 enum class ColorBehavior {
494 kLegacy,
495 };
496##
497#Const kLegacy 0
Cary Clarkbad5ad72017-08-03 17:14:08 -0400498 Is a placeholder to allow specialized constructor; has no meaning.
Cary Clark8032b982017-07-28 11:04:54 -0400499##
500##
501
Cary Clarkbad5ad72017-08-03 17:14:08 -0400502#Method SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior)
503
504#Private
505Android framework only.
506##
507
508#Param bitmap specifies a bitmap for the canvas to draw into ##
509#Param behavior specializes this constructor; value is unused ##
510#Return Canvas that can be used to draw into bitmap ##
511
512#NoExample
513##
514##
Cary Clark8032b982017-07-28 11:04:54 -0400515
516# ------------------------------------------------------------------------------
517
518#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
519
520Construct a canvas that draws into bitmap.
521Use props to match the device characteristics, like LCD striping.
522
Cary Clarkbad5ad72017-08-03 17:14:08 -0400523bitmap is copied so that subsequently editing bitmap will not affect
524constructed Canvas.
525
526#Param bitmap width, height, Image_Color_Type, Image_Alpha_Type,
527 and pixel storage of Raster_Surface
Cary Clark8032b982017-07-28 11:04:54 -0400528##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400529#Param props order and orientation of RGB striping; and whether to use
530 device independent fonts
Cary Clark8032b982017-07-28 11:04:54 -0400531##
532
Cary Clarkbad5ad72017-08-03 17:14:08 -0400533#Return Canvas that can be used to draw into bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -0400534
535#Example
536#Description
537The actual output depends on the installed fonts.
538##
539 SkBitmap bitmap;
540 // create a bitmap 5 wide and 11 high
541 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
542 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
Cary Clarkce101242017-09-01 15:51:02 -0400543 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400544 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
545 if (!canvas.peekPixels(&pixmap)) {
546 SkDebugf("peekPixels should never fail.\n");
547 }
548 const SkPMColor* pixels = pixmap.addr32(); // points to top left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400549 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400550 SkPaint paint; // by default, draws black, 12 point text
551 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
552 for (int y = 0; y < bitmap.height(); ++y) {
553 for (int x = 0; x < bitmap.width(); ++x) {
554 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
555 }
556 SkDebugf("\n");
557 }
558
559 #StdOut
560 -----
561 ---x-
562 ---x-
563 ---x-
564 ---x-
565 ---x-
566 ---x-
567 -----
568 ---x-
569 ---x-
570 -----
571 #StdOut ##
572##
573
574#ToDo incomplete ##
575
576##
577
578# ------------------------------------------------------------------------------
579
580#Method virtual ~SkCanvas()
581
Cary Clarkce101242017-09-01 15:51:02 -0400582Draw saved Layers, if any.
Cary Clark8032b982017-07-28 11:04:54 -0400583Free up resources used by Canvas.
584
585#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -0400586#Description
Cary Clarkce101242017-09-01 15:51:02 -0400587Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
588drawing surface that blends with the bitmap. When Layer goes out of
589scope, Layer Destructor is called. The saved Layer is restored, drawing
Cary Clarkbad5ad72017-08-03 17:14:08 -0400590transparent letters.
591##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400592void draw(SkCanvas* canvas) {
593 SkBitmap bitmap;
594 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
595 {
596 SkCanvas offscreen(bitmap);
597 SkPaint paint;
598 paint.setTextSize(100);
599 offscreen.drawString("ABC", 20, 160, paint);
600 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
601 offscreen.saveLayerAlpha(&layerBounds, 128);
602 offscreen.clear(SK_ColorWHITE);
603 offscreen.drawString("DEF", 20, 160, paint);
604 }
605 canvas->drawBitmap(bitmap, 0, 0, nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400606}
Cary Clark8032b982017-07-28 11:04:54 -0400607##
608
Cary Clarkbad5ad72017-08-03 17:14:08 -0400609#SeeAlso State_Stack
Cary Clark8032b982017-07-28 11:04:54 -0400610
611##
612
613# ------------------------------------------------------------------------------
614
615#Method SkMetaData& getMetaData()
616
Cary Clarkf05bdda2017-08-24 12:59:48 -0400617Returns storage to associate additional data with the canvas.
Cary Clark8032b982017-07-28 11:04:54 -0400618The storage is freed when Canvas is deleted.
619
Cary Clarkbad5ad72017-08-03 17:14:08 -0400620#Return storage that can be read from and written to ##
Cary Clark8032b982017-07-28 11:04:54 -0400621
622#Example
623 const char* kHelloMetaData = "HelloMetaData";
624 SkCanvas canvas;
625 SkMetaData& metaData = canvas.getMetaData();
626 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
627 metaData.setString(kHelloMetaData, "Hello!");
628 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
629 metaData.removeString(kHelloMetaData);
630 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
631
632 #StdOut
633 before: (null)
634 during: Hello!
635 after: (null)
636 #StdOut ##
637##
638
639#ToDo incomplete ##
640
641##
642
643# ------------------------------------------------------------------------------
644
645#Method SkImageInfo imageInfo() const
646
647Returns Image_Info for Canvas. If Canvas is not associated with Raster_Surface or
Cary Clarkbad5ad72017-08-03 17:14:08 -0400648GPU_Surface, returned Image_Color_Type is set to kUnknown_SkColorType.
Cary Clark8032b982017-07-28 11:04:54 -0400649
Cary Clarkbad5ad72017-08-03 17:14:08 -0400650#Return dimensions and Image_Color_Type of Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400651
652#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400653 SkCanvas emptyCanvas;
654 SkImageInfo canvasInfo = emptyCanvas.imageInfo();
655 SkImageInfo emptyInfo;
656 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
657
658 #StdOut
659 emptyInfo == canvasInfo
660 ##
Cary Clark8032b982017-07-28 11:04:54 -0400661##
662
663#ToDo incomplete ##
664
665##
666
667# ------------------------------------------------------------------------------
668
669#Method bool getProps(SkSurfaceProps* props) const
670
671If Canvas is associated with Raster_Surface or
672GPU_Surface, copies Surface_Properties and returns true. Otherwise,
673return false and leave props unchanged.
674
Cary Clarkbad5ad72017-08-03 17:14:08 -0400675#Param props storage for writable SkSurfaceProps ##
Cary Clark8032b982017-07-28 11:04:54 -0400676
Cary Clarkbad5ad72017-08-03 17:14:08 -0400677#Return true if Surface_Properties was copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400678
679#ToDo This seems old style. Deprecate? ##
680
681#Example
682 SkBitmap bitmap;
683 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
684 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
685 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
686 if (!canvas.getProps(&surfaceProps)) {
687 SkDebugf("getProps failed unexpectedly.\n");
688 }
689 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
690
691 #StdOut
692 isRGB:0
693 isRGB:1
694 #StdOut ##
695##
696
697#ToDo incomplete ##
698
699##
700
701# ------------------------------------------------------------------------------
702
703#Method void flush()
704
705Triggers the immediate execution of all pending draw operations.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400706If Canvas is associated with GPU_Surface, resolves all pending GPU operations.
Cary Clark8032b982017-07-28 11:04:54 -0400707
708#Example
709#Error "haven't thought of a useful example to put here"
710##
711
712#ToDo incomplete ##
713
714##
715
716# ------------------------------------------------------------------------------
717
718#Method virtual SkISize getBaseLayerSize() const
719
Cary Clarkce101242017-09-01 15:51:02 -0400720Gets the size of the base or root Layer in global canvas coordinates. The
721origin of the base Layer is always (0,0). The area available for drawing may be
Cary Clark8032b982017-07-28 11:04:54 -0400722smaller (due to clipping or saveLayer).
723
Cary Clarkce101242017-09-01 15:51:02 -0400724#Return integral width and height of base Layer ##
Cary Clark8032b982017-07-28 11:04:54 -0400725
726#Example
727 SkBitmap bitmap;
728 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
729 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
730 canvas.clipRect(SkRect::MakeWH(10, 40));
731 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
732 if (clipDeviceBounds.isEmpty()) {
733 SkDebugf("Empty clip bounds is unexpected!\n");
734 }
735 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
736 SkISize baseLayerSize = canvas.getBaseLayerSize();
737 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
738
739 #StdOut
740 clip=10,30
741 size=20,30
742 ##
743##
744
745#ToDo is this the same as the width and height of surface? ##
746
747##
748
749# ------------------------------------------------------------------------------
750
751#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
752
753Creates Surface matching info and props, and associates it with Canvas.
Cary Clarkbad5ad72017-08-03 17:14:08 -0400754Returns nullptr if no match found.
Cary Clark8032b982017-07-28 11:04:54 -0400755
Cary Clarkbad5ad72017-08-03 17:14:08 -0400756If props is nullptr, matches Surface_Properties in Canvas. If props is nullptr and Canvas
757does not have Surface_Properties, creates Surface with default Surface_Properties.
Cary Clark8032b982017-07-28 11:04:54 -0400758
Cary Clarkbad5ad72017-08-03 17:14:08 -0400759#Param info width, height, Image_Color_Type, Image_Alpha_Type, and Color_Space ##
760#Param props Surface_Properties to match; may be nullptr to match Canvas ##
761
762#Return Surface matching info and props, or nullptr if no match is available ##
Cary Clark8032b982017-07-28 11:04:54 -0400763
764#Example
765 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
766 SkCanvas* smallCanvas = surface->getCanvas();
767 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
768 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
769 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
770 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
771
772 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -0400773 compatible != nullptr
Cary Clark8032b982017-07-28 11:04:54 -0400774 size = 3, 4
775 ##
776##
777
778#ToDo incomplete ##
779
780##
781
782# ------------------------------------------------------------------------------
783
784#Method virtual GrContext* getGrContext()
785
786Returns GPU_Context of the GPU_Surface associated with Canvas.
787
Cary Clarkbad5ad72017-08-03 17:14:08 -0400788#Return GPU_Context, if available; nullptr otherwise ##
Cary Clark8032b982017-07-28 11:04:54 -0400789
790#Example
791void draw(SkCanvas* canvas) {
792 if (canvas->getGrContext()) {
793 canvas->clear(SK_ColorRED);
794 } else {
795 canvas->clear(SK_ColorBLUE);
796 }
797}
798##
799
800#ToDo fiddle should show both CPU and GPU out ##
801
802##
803
804# ------------------------------------------------------------------------------
805
Cary Clark73fa9722017-08-29 17:36:51 -0400806#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -0400807
808Returns the pixel base address, Image_Info, rowBytes, and origin if the pixels
Cary Clarkbad5ad72017-08-03 17:14:08 -0400809can be read directly. The returned address is only valid
Cary Clark8032b982017-07-28 11:04:54 -0400810while Canvas is in scope and unchanged. Any Canvas call or Surface call
811may invalidate the returned address and other returned values.
812
813If pixels are inaccessible, info, rowBytes, and origin are unchanged.
814
Cary Clarkbad5ad72017-08-03 17:14:08 -0400815#Param info storage for writable pixels' Image_Info; may be nullptr ##
816#Param rowBytes storage for writable pixels' row bytes; may be nullptr ##
Cary Clarkce101242017-09-01 15:51:02 -0400817#Param origin storage for Canvas top Layer origin, its top left corner;
Cary Clarkbad5ad72017-08-03 17:14:08 -0400818 may be nullptr
819##
Cary Clark8032b982017-07-28 11:04:54 -0400820
Cary Clarka523d2d2017-08-30 08:58:10 -0400821#Return address of pixels, or nullptr if inaccessible ##
Cary Clark8032b982017-07-28 11:04:54 -0400822
823#Example
824void draw(SkCanvas* canvas) {
825 if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
826 canvas->clear(SK_ColorRED);
827 } else {
828 canvas->clear(SK_ColorBLUE);
829 }
830}
831##
832
833#Example
834#Description
Cary Clarkce101242017-09-01 15:51:02 -0400835Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
836Layer to add a large dotted "DEF". Finally blends Layer with the
Cary Clark8032b982017-07-28 11:04:54 -0400837device.
838
Cary Clarkce101242017-09-01 15:51:02 -0400839The Layer and blended result appear on the CPU and GPU but the large dotted
Cary Clark8032b982017-07-28 11:04:54 -0400840"DEF" appear only on the CPU.
841##
842void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400843 SkPaint paint;
844 paint.setTextSize(100);
845 canvas->drawString("ABC", 20, 160, paint);
846 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
847 canvas->saveLayerAlpha(&layerBounds, 128);
848 canvas->clear(SK_ColorWHITE);
849 canvas->drawString("DEF", 20, 160, paint);
850 SkImageInfo imageInfo;
851 size_t rowBytes;
852 SkIPoint origin;
853 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
854 if (access) {
855 int h = imageInfo.height();
856 int v = imageInfo.width();
857 int rowWords = rowBytes / sizeof(uint32_t);
858 for (int y = 0; y < h; ++y) {
859 int newY = (y - h / 2) * 2 + h / 2;
860 if (newY < 0 || newY >= h) {
861 continue;
862 }
863 for (int x = 0; x < v; ++x) {
864 int newX = (x - v / 2) * 2 + v / 2;
865 if (newX < 0 || newX >= v) {
866 continue;
867 }
868 if (access[y * rowWords + x] == SK_ColorBLACK) {
869 access[newY * rowWords + newX] = SK_ColorGRAY;
870 }
871 }
872 }
873
874 }
Cary Clark8032b982017-07-28 11:04:54 -0400875 canvas->restore();
876}
877##
878
879#ToDo there are no callers of this that I can find. Deprecate? ##
880#ToDo fiddle should show both CPU and GPU out ##
881
882##
883
884# ------------------------------------------------------------------------------
885
886#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
887
888Returns custom context that tracks the Matrix and Clip.
889
890Use Raster_Handle_Allocator to blend Skia drawing with custom drawing, typically performed
Cary Clarkce101242017-09-01 15:51:02 -0400891by the host platform's user interface. The custom context returned is generated by
Cary Clarkbad5ad72017-08-03 17:14:08 -0400892SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
Cary Clark8032b982017-07-28 11:04:54 -0400893the drawing destination.
894
Cary Clarkce101242017-09-01 15:51:02 -0400895#Return context of custom allocation ##
Cary Clark8032b982017-07-28 11:04:54 -0400896
897#Example
898#Description
899#ToDo ##
900##
901#Function
902 static void DeleteCallback(void*, void* context) {
903 delete (char*) context;
904 }
905
906 class CustomAllocator : public SkRasterHandleAllocator {
907 public:
908 bool allocHandle(const SkImageInfo& info, Rec* rec) override {
909 char* context = new char[4]{'s', 'k', 'i', 'a'};
910 rec->fReleaseProc = DeleteCallback;
911 rec->fReleaseCtx = context;
912 rec->fHandle = context;
913 rec->fPixels = context;
914 rec->fRowBytes = 4;
915 return true;
916 }
917
918 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
919 // apply canvas matrix and clip to custom environment
920 }
921 };
922
923##
924 void draw(SkCanvas* canvas) {
925 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
926 std::unique_ptr<SkCanvas> c2 =
927 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
928 new CustomAllocator()), info);
929 char* context = (char*) c2->accessTopRasterHandle();
930 SkDebugf("context = %.4s\n", context);
931
932 }
933 #StdOut
934 context = skia
935 ##
936 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
937##
938
939#SeeAlso SkRasterHandleAllocator
940
941##
942
943# ------------------------------------------------------------------------------
944
945#Method bool peekPixels(SkPixmap* pixmap)
946
947Returns true if Canvas has direct access to its pixels.
948
Cary Clarkf05bdda2017-08-24 12:59:48 -0400949Pixels are readable when Device is raster. Pixels are not readable when Canvas
Cary Clarkbad5ad72017-08-03 17:14:08 -0400950is returned from GPU_Surface, returned by SkDocument::beginPage, returned by
Cary Clarkf05bdda2017-08-24 12:59:48 -0400951SkPictureRecorder::beginRecording, or Canvas is the base of a utility class
Cary Clarkbad5ad72017-08-03 17:14:08 -0400952like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400953
Cary Clarkf05bdda2017-08-24 12:59:48 -0400954pixmap is valid only while Canvas is in scope and unchanged. Any
Cary Clarkbad5ad72017-08-03 17:14:08 -0400955Canvas or Surface call may invalidate the pixmap values.
Cary Clark8032b982017-07-28 11:04:54 -0400956
Cary Clarkbad5ad72017-08-03 17:14:08 -0400957#Param pixmap storage for Canvas pixel state if Canvas pixels are readable;
958 otherwise, ignored
959##
Cary Clark8032b982017-07-28 11:04:54 -0400960
Cary Clarkbad5ad72017-08-03 17:14:08 -0400961#Return true if Canvas has direct access to pixels ##
Cary Clark8032b982017-07-28 11:04:54 -0400962
963#Example
964 SkPixmap pixmap;
965 if (canvas->peekPixels(&pixmap)) {
966 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
967 }
968 #StdOut
969 width=256 height=256
970 ##
971##
972
973##
974
975# ------------------------------------------------------------------------------
976
977#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
978 int srcX, int srcY)
979
Cary Clarkf05bdda2017-08-24 12:59:48 -0400980Copies rectangle of pixels from Canvas into dstPixels. Matrix and Clip are
981ignored. Source rectangle corners are (srcX, srcY) and
Cary Clarkce101242017-09-01 15:51:02 -0400982#Formula
983(this->imageInfo.width(), this->imageInfo.height())
984##
985. Destination rectangle corners are (0, 0) and
986#Formula
987(dstInfo.width(), dstInfo.height())
988##
989. Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400990converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400991
Cary Clarkf05bdda2017-08-24 12:59:48 -0400992Pixels are readable when Device is raster, or backed by a GPU.
993Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
994returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
995class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400996
Cary Clarkf05bdda2017-08-24 12:59:48 -0400997The destination pixel storage must be allocated by the caller.
Cary Clark8032b982017-07-28 11:04:54 -0400998
Cary Clarkf05bdda2017-08-24 12:59:48 -0400999Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1000do not match. Only pixels within both source and destination rectangles
1001are copied. dstPixels contents outside the rectangle intersection are unchanged.
1002
1003Pass negative values for srcX or srcY to offset pixels across or down destination.
Cary Clark8032b982017-07-28 11:04:54 -04001004
1005Does not copy, and returns false if:
1006
1007#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001008# Source and destination rectangles do not intersect. ##
1009# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
1010# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001011# dstRowBytes is too small to contain one row of pixels. ##
1012##
1013
Cary Clarkf05bdda2017-08-24 12:59:48 -04001014#Param dstInfo width, height, Image_Color_Type, and Image_Alpha_Type of dstPixels ##
1015#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
1016#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
1017#Param srcX offset into readable pixels in x; may be negative ##
1018#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001019
Cary Clarkbad5ad72017-08-03 17:14:08 -04001020#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001021
1022#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001023#Width 64
1024#Height 64
1025#Description
1026 A black circle drawn on a blue background provides an image to copy.
1027 readPixels copies one quarter of the canvas into each of the four corners.
Cary Clarkce101242017-09-01 15:51:02 -04001028 The Layer draws over the image.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001029##
1030 canvas->clear(SK_ColorBLUE);
1031 SkPaint paint;
1032 canvas->drawCircle(32, 32, 28, paint);
1033 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
1034 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
1035 sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
1036 for (int x : { 32, -32 } ) {
1037 for (int y : { 32, -32 } ) {
1038 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
1039 }
1040 }
1041 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
1042 canvas->drawImage(image, 0, 0);
1043##
1044
1045#Example
Cary Clark8032b982017-07-28 11:04:54 -04001046#Description
Cary Clarkce101242017-09-01 15:51:02 -04001047 Canvas returned by Raster_Surface has Premultiplied pixel values.
1048 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
1049 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha
1050 to generate Premultiplied value 0x802B5580. readPixels converts pixel back
1051 to Unpremultiplied value 0x8056A9FF, introducing error.
Cary Clark8032b982017-07-28 11:04:54 -04001052##
1053 canvas->clear(0x8055aaff);
1054 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
1055 uint32_t pixel = 0;
1056 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
1057 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
1058 SkDebugf("pixel = %08x\n", pixel);
1059 }
1060 }
1061
1062 #StdOut
1063 pixel = 802b5580
1064 pixel = 8056a9ff
1065 ##
1066##
1067
Cary Clarkf05bdda2017-08-24 12:59:48 -04001068#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001069
1070##
1071
1072# ------------------------------------------------------------------------------
1073
1074#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
1075
Cary Clarkf05bdda2017-08-24 12:59:48 -04001076Copies rectangle of pixels from Canvas into pixmap. Matrix and Clip are
1077ignored. Source rectangle corners are (srcX, srcY) and
Cary Clarkce101242017-09-01 15:51:02 -04001078#Formula
1079(this->imageInfo.width(), this->imageInfo.height())
1080##
1081. Destination rectangle are (0, 0) and
1082#Formula
1083(pixmap.width(), pixmap.height())
1084##
1085. Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -04001086converting to pixmap.colorType() and pixmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001087
Cary Clarkf05bdda2017-08-24 12:59:48 -04001088Pixels are readable when Device is raster, or backed by a GPU.
1089Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
1090returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1091class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001092
Cary Clarkf05bdda2017-08-24 12:59:48 -04001093Allocates pixel storage in pixmap if needed.
Cary Clark8032b982017-07-28 11:04:54 -04001094
Cary Clarkf05bdda2017-08-24 12:59:48 -04001095Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1096do not match. Only pixels within both source and destination rectangles
1097are copied. pixmap pixels contents outside the rectangle intersection are unchanged.
1098
1099Pass negative values for srcX or srcY to offset pixels across or down pixmap.
Cary Clark8032b982017-07-28 11:04:54 -04001100
1101Does not copy, and returns false if:
1102
1103#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001104# Source and destination rectangles do not intersect. ##
1105# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
1106# Canvas pixels are not readable; for instance, Canvas is document-based. ##
1107# Pixmap pixels could not be allocated. ##
1108# pixmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -04001109##
1110
Cary Clarkbad5ad72017-08-03 17:14:08 -04001111#Param pixmap storage for pixels copied from Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001112#Param srcX offset into readable pixels in x; may be negative ##
1113#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001114
Cary Clarkbad5ad72017-08-03 17:14:08 -04001115#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001116
1117#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001118 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001119 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
1120 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha
1121 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001122 ##
1123 void draw(SkCanvas* canvas) {
1124 canvas->clear(0x8055aaff);
1125 uint32_t pixels[1] = { 0 };
1126 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
1127 canvas->readPixels(pixmap, 0, 0);
1128 SkDebugf("pixel = %08x\n", pixels[0]);
1129 }
Cary Clark8032b982017-07-28 11:04:54 -04001130 #StdOut
1131 pixel = 802b5580
1132 ##
1133##
1134
Cary Clarkf05bdda2017-08-24 12:59:48 -04001135#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001136
1137##
1138
1139# ------------------------------------------------------------------------------
1140
1141#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
1142
Cary Clarkf05bdda2017-08-24 12:59:48 -04001143Copies rectangle of pixels from Canvas into bitmap. Matrix and Clip are
1144ignored. Source rectangle corners are (srcX, srcY) and
Cary Clarkce101242017-09-01 15:51:02 -04001145#Formula
1146(this->imageInfo.width(), this->imageInfo.height())
1147##
1148. Destination rectangle corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clarkf05bdda2017-08-24 12:59:48 -04001149Copies each readable pixel intersecting both rectangles, without scaling,
1150converting to bitmap.colorType() and bitmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -04001151
Cary Clarkf05bdda2017-08-24 12:59:48 -04001152Pixels are readable when Device is raster, or backed by a GPU.
1153Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
1154returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1155class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001156
Cary Clarkf05bdda2017-08-24 12:59:48 -04001157Allocates pixel storage in bitmap if needed.
1158
1159Bitmap values are converted only if Image_Color_Type and Image_Alpha_Type
1160do not match. Only pixels within both source and destination rectangles
1161are copied. Bitmap pixels outside the rectangle intersection are unchanged.
1162
1163Pass negative values for srcX or srcY to offset pixels across or down bitmap.
Cary Clark8032b982017-07-28 11:04:54 -04001164
1165Does not copy, and returns false if:
1166
1167#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001168# Source and destination rectangles do not intersect. ##
1169# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
1170# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001171# bitmap pixels could not be allocated. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001172# bitmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -04001173##
1174
Cary Clarkbad5ad72017-08-03 17:14:08 -04001175#Param bitmap storage for pixels copied from Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001176#Param srcX offset into readable pixels in x; may be negative ##
1177#Param srcY offset into readable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001178
Cary Clarkbad5ad72017-08-03 17:14:08 -04001179#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -04001180
1181#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -04001182 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001183 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
1184 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multiplied by Color_Alpha
1185 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001186 ##
Cary Clark8032b982017-07-28 11:04:54 -04001187void draw(SkCanvas* canvas) {
1188 canvas->clear(0x8055aaff);
1189 SkBitmap bitmap;
1190 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
1191 canvas->readPixels(bitmap, 0, 0);
1192 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
1193}
1194 #StdOut
1195 pixel = 802b5580
1196 ##
1197##
1198
Cary Clarkf05bdda2017-08-24 12:59:48 -04001199#SeeAlso peekPixels writePixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001200
1201##
1202
1203# ------------------------------------------------------------------------------
1204
1205#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
1206
Cary Clarkf05bdda2017-08-24 12:59:48 -04001207Copies rectangle from pixels to Canvas. Matrix and Clip are ignored.
1208Source rectangle corners are (0, 0) and (info.width(), info.height()).
1209Destination rectangle corners are (x, y) and
Cary Clarkce101242017-09-01 15:51:02 -04001210#Formula
1211(this->imageInfo.width(), this->imageInfo.height())
1212##
1213. Copies each readable pixel
Cary Clarkf05bdda2017-08-24 12:59:48 -04001214intersecting both rectangles, without scaling, converting to
Cary Clarkce101242017-09-01 15:51:02 -04001215#Formula
1216this->imageInfo.colorType()
1217##
1218and
1219#Formula
1220this->imageInfo.alphaType()
1221##
1222if required.
Cary Clark8032b982017-07-28 11:04:54 -04001223
Cary Clarkf05bdda2017-08-24 12:59:48 -04001224Pixels are writable when Device is raster, or backed by a GPU.
1225Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
1226returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1227class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001228
Cary Clarkf05bdda2017-08-24 12:59:48 -04001229Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1230do not match. Only pixels within both source and destination rectangles
1231are copied. Canvas pixels outside the rectangle intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -04001232
Cary Clarkf05bdda2017-08-24 12:59:48 -04001233Pass negative values for x or y to offset pixels to the left or
1234above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001235
1236Does not copy, and returns false if:
1237
1238#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001239# Source and destination rectangles do not intersect. ##
Cary Clarkce101242017-09-01 15:51:02 -04001240# pixels could not be converted to
1241#Formula
1242this->imageInfo.colorType()
1243##
1244or
1245#Formula
1246this->imageInfo.alphaType()
1247##
1248. ##
Cary Clark8032b982017-07-28 11:04:54 -04001249# Canvas pixels are not writable; for instance, Canvas is document-based. ##
1250# rowBytes is too small to contain one row of pixels. ##
1251##
1252
Cary Clarkf05bdda2017-08-24 12:59:48 -04001253#Param info width, height, Image_Color_Type, and Image_Alpha_Type of pixels ##
1254#Param pixels pixels to copy, of size info.height() times rowBytes, or larger ##
Cary Clarkd0530ba2017-09-14 11:25:39 -04001255#Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001256#Param x offset into Canvas writable pixels in x; may be negative ##
1257#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001258
Cary Clarkbad5ad72017-08-03 17:14:08 -04001259#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001260
1261#Example
1262 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
1263 for (int y = 0; y < 256; ++y) {
1264 uint32_t pixels[256];
1265 for (int x = 0; x < 256; ++x) {
1266 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
1267 }
1268 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
1269 }
1270##
1271
Cary Clarkf05bdda2017-08-24 12:59:48 -04001272#SeeAlso readPixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001273
1274##
1275
1276# ------------------------------------------------------------------------------
1277
1278#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
1279
Cary Clarkf05bdda2017-08-24 12:59:48 -04001280Copies rectangle from pixels to Canvas. Matrix and Clip are ignored.
Cary Clarkce101242017-09-01 15:51:02 -04001281Source rectangle corners are (0, 0) and
1282#Formula
1283(bitmap.width(), bitmap.height())
1284##
1285.
Cary Clarkf05bdda2017-08-24 12:59:48 -04001286Destination rectangle corners are (x, y) and
Cary Clarkce101242017-09-01 15:51:02 -04001287#Formula
1288(this->imageInfo.width(), this->imageInfo.height())
1289##
1290. Copies each readable pixel
Cary Clarkf05bdda2017-08-24 12:59:48 -04001291intersecting both rectangles, without scaling, converting to
Cary Clarkce101242017-09-01 15:51:02 -04001292#Formula
1293this->imageInfo.colorType()
1294##
1295and
1296#Formula
1297this->imageInfo.alphaType()
1298##
1299if required.
Cary Clark8032b982017-07-28 11:04:54 -04001300
Cary Clarkf05bdda2017-08-24 12:59:48 -04001301Pixels are writable when Device is raster, or backed by a GPU.
1302Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
1303returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
1304class like SkDumpCanvas.
Cary Clark8032b982017-07-28 11:04:54 -04001305
Cary Clarkf05bdda2017-08-24 12:59:48 -04001306Pixel values are converted only if Image_Color_Type and Image_Alpha_Type
1307do not match. Only pixels within both source and destination rectangles
1308are copied. Canvas pixels outside the rectangle intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -04001309
Cary Clarkf05bdda2017-08-24 12:59:48 -04001310Pass negative values for x or y to offset pixels to the left or
1311above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -04001312
1313Does not copy, and returns false if:
1314
1315#List
Cary Clarkf05bdda2017-08-24 12:59:48 -04001316# Source and destination rectangles do not intersect. ##
Cary Clark8032b982017-07-28 11:04:54 -04001317# bitmap does not have allocated pixels. ##
Cary Clarkce101242017-09-01 15:51:02 -04001318# bitmap pixels could not be converted to
1319#Formula
1320this->imageInfo.colorType()
1321##
1322or
1323#Formula
1324this->imageInfo.alphaType()
1325##
1326. ##
1327# Canvas pixels are not writable; for instance, Canvas is document based. ##
Cary Clark8032b982017-07-28 11:04:54 -04001328# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
1329##
1330
Cary Clarkbad5ad72017-08-03 17:14:08 -04001331#Param bitmap contains pixels copied to Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -04001332#Param x offset into Canvas writable pixels in x; may be negative ##
1333#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001334
Cary Clarkbad5ad72017-08-03 17:14:08 -04001335#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001336
1337#Example
1338void draw(SkCanvas* canvas) {
1339 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
1340 SkBitmap bitmap;
1341 bitmap.setInfo(imageInfo);
1342 uint32_t pixels[4];
1343 bitmap.setPixels(pixels);
1344 for (int y = 0; y < 256; y += 2) {
1345 for (int x = 0; x < 256; x += 2) {
1346 pixels[0] = SkColorSetRGB(x, y, x | y);
1347 pixels[1] = SkColorSetRGB(x ^ y, y, x);
1348 pixels[2] = SkColorSetRGB(x, x & y, y);
1349 pixels[3] = SkColorSetRGB(~x, ~y, x);
1350 canvas->writePixels(bitmap, x, y);
1351 }
1352 }
1353}
1354##
1355
Cary Clarkf05bdda2017-08-24 12:59:48 -04001356#SeeAlso readPixels drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04001357
1358##
1359
1360# ------------------------------------------------------------------------------
1361#Topic State_Stack
1362
1363Canvas maintains a stack of state that allows hierarchical drawing, commonly used
Cary Clarkbad5ad72017-08-03 17:14:08 -04001364to implement windows and views. The initial state has an identity matrix and and
1365an infinite clip. Even with a wide-open clip, drawing is constrained by the
1366bounds of the Canvas Surface or Device.
Cary Clark8032b982017-07-28 11:04:54 -04001367
1368Canvas savable state consists of Clip, Matrix, and Draw_Filter.
1369Clip describes the area that may be drawn to.
1370Matrix transforms the geometry.
1371Draw_Filter (deprecated on most platforms) modifies the paint before drawing.
1372
1373save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
1374save state and return the depth of the stack.
1375
Cary Clarkbad5ad72017-08-03 17:14:08 -04001376restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
Cary Clark8032b982017-07-28 11:04:54 -04001377
1378Each state on the stack intersects Clip with the previous Clip,
1379and concatenates Matrix with the previous Matrix.
1380The intersected Clip makes the drawing area the same or smaller;
1381the concatenated Matrix may move the origin and potentially scale or rotate
1382the coordinate space.
1383
1384Canvas does not require balancing the state stack but it is a good idea
1385to do so. Calling save() without restore() will eventually cause Skia to fail;
1386mismatched save() and restore() create hard to find bugs.
1387
1388It is not possible to use state to draw outside of the clip defined by the
1389previous state.
1390
1391#Example
1392#Description
1393Draw to ever smaller clips; then restore drawing to full canvas.
1394Note that the second clipRect is not permitted to enlarge Clip.
1395##
1396#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001397void draw(SkCanvas* canvas) {
1398 SkPaint paint;
1399 canvas->save(); // records stack depth to restore
1400 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
1401 canvas->clear(SK_ColorRED); // draws to limit of clip
1402 canvas->save(); // records stack depth to restore
1403 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
1404 canvas->clear(SK_ColorBLUE); // draws to smaller clip
1405 canvas->restore(); // enlarges clip
1406 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
1407 canvas->restore(); // enlarges clip
1408 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
Cary Clark8032b982017-07-28 11:04:54 -04001409}
1410##
1411
1412Each Clip uses the current Matrix for its coordinates.
1413
1414#Example
1415#Description
1416While clipRect is given the same rectangle twice, Matrix makes the second
1417clipRect draw at half the size of the first.
1418##
1419#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001420void draw(SkCanvas* canvas) {
1421 canvas->clipRect(SkRect::MakeWH(100, 100));
1422 canvas->clear(SK_ColorRED);
1423 canvas->scale(.5, .5);
1424 canvas->clipRect(SkRect::MakeWH(100, 100));
1425 canvas->clear(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001426}
1427##
1428
1429#SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
1430
1431#Method int save()
1432
1433Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms).
1434Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1435restoring the Matrix, Clip, and Draw_Filter to their state when save() was called.
1436
Cary Clarkbad5ad72017-08-03 17:14:08 -04001437Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix,
1438and resetMatrix. Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
Cary Clark8032b982017-07-28 11:04:54 -04001439
Cary Clarkbad5ad72017-08-03 17:14:08 -04001440Saved Canvas state is put on a stack; multiple calls to save() should be balance
1441by an equal number of calls to restore().
Cary Clark8032b982017-07-28 11:04:54 -04001442
1443Call restoreToCount with result to restore this and subsequent saves.
1444
Cary Clarkbad5ad72017-08-03 17:14:08 -04001445#Return depth of saved stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001446
1447#Example
1448#Description
1449The black square is translated 50 pixels down and to the right.
1450Restoring Canvas state removes translate() from Canvas stack;
1451the red square is not translated, and is drawn at the origin.
1452##
1453#Height 100
1454void draw(SkCanvas* canvas) {
1455 SkPaint paint;
1456 SkRect rect = { 0, 0, 25, 25 };
1457 canvas->drawRect(rect, paint);
1458 canvas->save();
1459 canvas->translate(50, 50);
1460 canvas->drawRect(rect, paint);
1461 canvas->restore();
1462 paint.setColor(SK_ColorRED);
1463 canvas->drawRect(rect, paint);
1464}
1465##
1466
1467#ToDo incomplete ##
1468
1469##
1470
1471# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001472
1473#Method void restore()
1474
1475Removes changes to Matrix, Clip, and Draw_Filter since Canvas state was
1476last saved. The state is removed from the stack.
1477
1478Does nothing if the stack is empty.
1479
1480#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001481void draw(SkCanvas* canvas) {
1482 SkCanvas simple;
1483 SkDebugf("depth = %d\n", simple.getSaveCount());
1484 simple.restore();
1485 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001486}
1487##
1488
1489##
1490
1491# ------------------------------------------------------------------------------
1492
1493#Method int getSaveCount() const
1494
1495Returns the number of saved states, each containing: Matrix, Clip, and Draw_Filter.
1496Equals the number of save() calls less the number of restore() calls plus one.
1497The save count of a new canvas is one.
1498
Cary Clarkbad5ad72017-08-03 17:14:08 -04001499#Return depth of save state stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001500
1501#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001502void draw(SkCanvas* canvas) {
1503 SkCanvas simple;
1504 SkDebugf("depth = %d\n", simple.getSaveCount());
1505 simple.save();
1506 SkDebugf("depth = %d\n", simple.getSaveCount());
1507 simple.restore();
1508 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001509}
1510#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001511depth = 1
1512depth = 2
Cary Clark8032b982017-07-28 11:04:54 -04001513depth = 1
1514##
1515##
1516
1517##
1518
1519# ------------------------------------------------------------------------------
1520
1521#Method void restoreToCount(int saveCount)
1522
Cary Clarkbad5ad72017-08-03 17:14:08 -04001523Restores state to Matrix, Clip, and Draw_Filter values when save(), saveLayer,
1524saveLayerPreserveLCDTextRequests, or saveLayerAlpha returned saveCount.
Cary Clark8032b982017-07-28 11:04:54 -04001525
1526Does nothing if saveCount is greater than state stack count.
1527Restores state to initial values if saveCount is less than or equal to one.
1528
Cary Clarkbad5ad72017-08-03 17:14:08 -04001529#Param saveCount depth of state stack to restore ##
Cary Clark8032b982017-07-28 11:04:54 -04001530
1531#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001532void draw(SkCanvas* canvas) {
1533 SkDebugf("depth = %d\n", canvas->getSaveCount());
1534 canvas->save();
1535 canvas->save();
1536 SkDebugf("depth = %d\n", canvas->getSaveCount());
1537 canvas->restoreToCount(0);
1538 SkDebugf("depth = %d\n", canvas->getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001539}
1540#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001541depth = 1
1542depth = 3
Cary Clark8032b982017-07-28 11:04:54 -04001543depth = 1
1544##
1545##
1546
1547##
1548
1549#Topic State_Stack ##
1550
1551# ------------------------------------------------------------------------------
Cary Clarkce101242017-09-01 15:51:02 -04001552
1553#Topic Layer
Cary Clarkd0530ba2017-09-14 11:25:39 -04001554#Substitute layer
Cary Clarkce101242017-09-01 15:51:02 -04001555#Alias Layers
1556
1557Layer allocates a temporary Bitmap to draw into. When the drawing is
1558complete, the Bitmap is drawn into the Canvas.
1559
1560Layer is saved in a stack along with other saved state. When state with a Layer
1561is restored, the Bitmap is drawn into the previous Layer.
1562
1563Layer may be initialized with the contents of the previous Layer. When Layer is
1564restored, its Bitmap can be modified by Paint passed to Layer to apply
1565Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
1566
1567#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1568
1569Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1570and allocates a Bitmap for subsequent drawing.
1571Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1572and draws the Bitmap.
1573
1574Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1575setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1576clipPath, clipRegion.
1577
1578Rect bounds suggests but does not define the Bitmap size. To clip drawing to
1579a specific rectangle, use clipRect.
1580
1581Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1582Blend_Mode when restore() is called.
1583
1584Call restoreToCount with returned value to restore this and subsequent saves.
1585
1586#Param bounds hint to limit the size of the Layer; may be nullptr ##
1587#Param paint graphics state for Layer; may be nullptr ##
1588
1589#Return depth of saved stack ##
1590
1591#Example
1592#Description
1593Rectangles are blurred by Image_Filter when restore() draws Layer to main
1594Canvas.
1595##
1596#Height 128
1597void draw(SkCanvas* canvas) {
1598 SkPaint paint, blur;
1599 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1600 canvas->saveLayer(nullptr, &blur);
1601 SkRect rect = { 25, 25, 50, 50};
1602 canvas->drawRect(rect, paint);
1603 canvas->translate(50, 50);
1604 paint.setColor(SK_ColorRED);
1605 canvas->drawRect(rect, paint);
1606 canvas->restore();
1607}
1608##
1609
1610#ToDo incomplete ##
1611
1612##
1613
1614#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
1615
1616Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1617and allocates a Bitmap for subsequent drawing.
1618Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1619and draws the Bitmap.
1620
1621Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1622setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1623clipPath, clipRegion.
1624
1625Rect bounds suggests but does not define the Layer size. To clip drawing to
1626a specific rectangle, use clipRect.
1627
1628Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1629Blend_Mode when restore() is called.
1630
1631Call restoreToCount with returned value to restore this and subsequent saves.
1632
1633#Param bounds hint to limit the size of Layer; may be nullptr ##
1634#Param paint graphics state for Layer; may be nullptr ##
1635
1636#Return depth of saved stack ##
1637
1638#Example
1639#Description
1640Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
1641The red rectangle is clipped; it does not fully fit on Layer.
1642Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
1643##
1644#Height 128
1645void draw(SkCanvas* canvas) {
1646 SkPaint paint, blur;
1647 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1648 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1649 SkRect rect = { 25, 25, 50, 50};
1650 canvas->drawRect(rect, paint);
1651 canvas->translate(50, 50);
1652 paint.setColor(SK_ColorRED);
1653 canvas->drawRect(rect, paint);
1654 canvas->restore();
1655}
1656##
1657
1658#ToDo incomplete ##
1659
1660##
1661
1662#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
1663
1664Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1665and allocates a Bitmap for subsequent drawing.
1666LCD_Text is preserved when the Layer is drawn to the prior Layer.
1667
1668Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1669and draws Layer.
1670
1671Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1672setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1673clipPath, clipRegion.
1674
1675Rect bounds suggests but does not define the Layer size. To clip drawing to
1676a specific rectangle, use clipRect.
1677
1678Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
1679Blend_Mode when restore() is called.
1680
1681Call restoreToCount with returned value to restore this and subsequent saves.
1682
1683Draw text on an opaque background so that LCD_Text blends correctly with the
1684prior Layer. LCD_Text drawn on a background with transparency may result in
1685incorrect banding.
1686
1687#Param bounds hint to limit the size of Layer; may be nullptr ##
1688#Param paint graphics state for Layer; may be nullptr ##
1689
1690#Return depth of saved stack ##
1691
1692#Example
1693 SkPaint paint;
1694 paint.setAntiAlias(true);
1695 paint.setLCDRenderText(true);
1696 paint.setTextSize(20);
1697 for (auto preserve : { false, true } ) {
1698 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
1699 : canvas->saveLayer(nullptr, nullptr);
1700 SkPaint p;
1701 p.setColor(SK_ColorWHITE);
1702 // Comment out the next line to draw on a non-opaque background.
1703 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
1704 canvas->drawString("Hamburgefons", 30, 60, paint);
1705
1706 p.setColor(0xFFCCCCCC);
1707 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
1708 canvas->drawString("Hamburgefons", 30, 90, paint);
1709
1710 canvas->restore();
1711 canvas->translate(0, 80);
1712 }
1713 ##
1714
1715#ToDo incomplete ##
1716
1717##
1718
1719#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1720
1721Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1722and allocates Bitmap for subsequent drawing.
1723
1724Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1725and blends Layer with alpha opacity onto prior Layer.
1726
1727Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
1728setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
1729clipPath, clipRegion.
1730
1731Rect bounds suggests but does not define Layer size. To clip drawing to
1732a specific rectangle, use clipRect.
1733
1734alpha of zero is fully transparent, 255 is fully opaque.
1735
1736Call restoreToCount with returned value to restore this and subsequent saves.
1737
1738#Param bounds hint to limit the size of Layer; may be nullptr ##
1739#Param alpha opacity of Layer ##
1740
1741#Return depth of saved stack ##
1742
1743#Example
1744 SkPaint paint;
1745 paint.setColor(SK_ColorRED);
1746 canvas->drawCircle(50, 50, 50, paint);
1747 canvas->saveLayerAlpha(nullptr, 128);
1748 paint.setColor(SK_ColorBLUE);
1749 canvas->drawCircle(100, 50, 50, paint);
1750 paint.setColor(SK_ColorGREEN);
1751 paint.setAlpha(128);
1752 canvas->drawCircle(75, 90, 50, paint);
1753 canvas->restore();
1754##
1755
1756#ToDo incomplete ##
1757
1758##
1759
1760#Enum
1761
1762#Code
1763 enum {
1764 kIsOpaque_SaveLayerFlag = 1 << 0,
1765 kPreserveLCDText_SaveLayerFlag = 1 << 1,
1766 kInitWithPrevious_SaveLayerFlag = 1 << 2,
1767 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
1768 };
1769
1770 typedef uint32_t SaveLayerFlags;
1771##
1772
1773SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
1774defining how Layer allocated by saveLayer operates.
1775
1776#Const kIsOpaque_SaveLayerFlag 1
1777 Creates Layer without transparency. Flag is ignored if Layer Paint contains
1778 Image_Filter or Color_Filter.
1779##
1780
1781#Const kPreserveLCDText_SaveLayerFlag 2
1782 Creates Layer for LCD text. Flag is ignored if Layer Paint contains
1783 Image_Filter or Color_Filter.
1784##
1785
1786#Const kInitWithPrevious_SaveLayerFlag 4
1787 Initializes Layer with the contents of the previous Layer.
1788##
1789
1790#Const kDontClipToLayer_Legacy_SaveLayerFlag 0x80000000
1791#Private
1792 to be deprecated: bug.skia.org/2440
1793##
1794 Only present on Android.
1795 Skips setting a clip to the Layer bounds.
1796##
1797
1798#Example
1799#Height 160
1800#Description
1801Canvas Layer captures red and blue circles scaled up by four.
1802scalePaint blends Layer back with transparency.
1803##
1804void draw(SkCanvas* canvas) {
1805 SkPaint redPaint, bluePaint, scalePaint;
1806 redPaint.setColor(SK_ColorRED);
1807 canvas->drawCircle(21, 21, 8, redPaint);
1808 bluePaint.setColor(SK_ColorBLUE);
1809 canvas->drawCircle(31, 21, 8, bluePaint);
1810 SkMatrix matrix;
1811 matrix.setScale(4, 4);
1812 scalePaint.setAlpha(0x40);
1813 scalePaint.setImageFilter(
1814 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1815 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
1816 SkCanvas::kInitWithPrevious_SaveLayerFlag);
1817 canvas->saveLayer(saveLayerRec);
1818 canvas->restore();
1819}
1820##
1821
1822#ToDo incomplete ##
1823
1824#Enum ##
1825
1826#Struct SaveLayerRec
1827
1828#Code
1829 struct SaveLayerRec {
1830 SaveLayerRec*(...
1831
1832 const SkRect* fBounds;
1833 const SkPaint* fPaint;
1834 const SkImageFilter* fBackdrop;
1835 SaveLayerFlags fSaveLayerFlags;
1836 };
1837##
1838
1839SaveLayerRec contains the state used to create the Layer.
1840
1841#Member const SkRect* fBounds
1842 fBounds is used as a hint to limit the size of Layer; may be nullptr.
1843 fBounds suggests but does not define Layer size. To clip drawing to
1844 a specific rectangle, use clipRect.
1845##
1846
1847#Member const SkPaint* fPaint
1848 fPaint modifies how Layer overlays the prior Layer; may be nullptr.
1849 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1850 Mask_Filter affect Layer draw.
1851##
1852
1853#Member const SkImageFilter* fBackdrop
1854 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
1855 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1856 prior Layer without an Image_Filter.
1857##
1858
1859#Member const SkImage* fClipMask
1860 restore() clips Layer by the Color_Alpha channel of fClipMask when
1861 Layer is copied to Device. fClipMask may be nullptr. .
1862##
1863
1864#Member const SkMatrix* fClipMatrix
1865 fClipMatrix transforms fClipMask before it clips Layer. If
1866 fClipMask describes a translucent gradient, it may be scaled and rotated
1867 without introducing artifacts. fClipMatrix may be nullptr.
1868##
1869
1870#Member SaveLayerFlags fSaveLayerFlags
1871 fSaveLayerFlags are used to create Layer without transparency,
1872 create Layer for LCD text, and to create Layer with the
1873 contents of the previous Layer.
1874##
1875
1876#Example
1877#Height 160
1878#Description
1879Canvas Layer captures a red Anti-aliased circle and a blue Aliased circle scaled
1880up by four. After drawing another red circle without scaling on top, the Layer is
1881transferred to the main canvas.
1882##
1883void draw(SkCanvas* canvas) {
1884 SkPaint redPaint, bluePaint;
1885 redPaint.setAntiAlias(true);
1886 redPaint.setColor(SK_ColorRED);
1887 canvas->drawCircle(21, 21, 8, redPaint);
1888 bluePaint.setColor(SK_ColorBLUE);
1889 canvas->drawCircle(31, 21, 8, bluePaint);
1890 SkMatrix matrix;
1891 matrix.setScale(4, 4);
1892 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
1893 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
1894 canvas->saveLayer(saveLayerRec);
1895 canvas->drawCircle(125, 85, 8, redPaint);
1896 canvas->restore();
1897}
1898##
1899
1900#Method SaveLayerRec()
1901
1902Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
1903
1904#Return empty SaveLayerRec ##
1905
1906#Example
1907 SkCanvas::SaveLayerRec rec1;
1908 rec1.fSaveLayerFlags = SkCanvas::kIsOpaque_SaveLayerFlag;
1909 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kIsOpaque_SaveLayerFlag);
1910 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1911 && rec1.fPaint == rec2.fPaint
1912 && rec1.fBackdrop == rec2.fBackdrop
1913 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1914 #StdOut
1915 rec1 == rec2
1916 ##
1917##
1918
1919##
1920
1921#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
1922
1923Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
1924
1925#Param bounds Layer dimensions; may be nullptr ##
1926#Param paint applied to Layer when overlaying prior Layer; may be nullptr ##
1927#Param saveLayerFlags SaveLayerRec options to modify Layer ##
1928
1929#Return SaveLayerRec with empty backdrop ##
1930
1931#Example
1932 SkCanvas::SaveLayerRec rec1;
1933 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1934 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1935 && rec1.fPaint == rec2.fPaint
1936 && rec1.fBackdrop == rec2.fBackdrop
1937 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1938 #StdOut
1939 rec1 == rec2
1940 ##
1941##
1942
1943##
1944
1945#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1946 SaveLayerFlags saveLayerFlags)
1947
1948Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
1949
1950#Param bounds Layer dimensions; may be nullptr ##
1951#Param paint applied to Layer when overlaying prior Layer;
1952 may be nullptr
1953##
1954#Param backdrop prior Layer copied with Image_Filter; may be nullptr
1955##
1956#Param saveLayerFlags SaveLayerRec options to modify Layer ##
1957
1958#Return SaveLayerRec fully specified ##
1959
1960#Example
1961 SkCanvas::SaveLayerRec rec1;
1962 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1963 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1964 && rec1.fPaint == rec2.fPaint
1965 && rec1.fBackdrop == rec2.fBackdrop
1966 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1967 #StdOut
1968 rec1 == rec2
1969 ##
1970##
1971
1972##
1973
1974#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1975 const SkImage* clipMask, const SkMatrix* clipMatrix,
1976 SaveLayerFlags saveLayerFlags)
1977
1978#Experimental
1979Not ready for general use.
1980##
1981
1982Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
1983clipMatrix uses Color_Alpha channel of image, transformed by clipMatrix, to clip
1984Layer when drawn to Canvas.
1985
1986Implementation is incomplete; has no effect if Device is GPU-backed.
1987
1988#Param bounds Layer dimensions; may be nullptr ##
1989#Param paint graphics state applied to Layer when overlaying prior
1990 Layer; may be nullptr
1991##
1992#Param backdrop prior Layer copied with Image_Filter;
1993 may be nullptr
1994##
1995#Param clipMask clip applied to Layer; may be nullptr ##
1996#Param clipMatrix matrix applied to clipMask; may be nullptr to use
1997 identity matrix
1998##
1999#Param saveLayerFlags SaveLayerRec options to modify Layer ##
2000
2001#Return SaveLayerRec fully specified ##
2002
2003#ToDo incomplete ##
2004
2005##
2006
2007#Struct ##
2008
2009#Method int saveLayer(const SaveLayerRec& layerRec)
2010
2011Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
2012and allocates Bitmap for subsequent drawing.
2013
2014Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
2015and blends Bitmap with Color_Alpha opacity onto the prior Layer.
2016
2017Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
2018setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
2019clipPath, clipRegion.
2020
2021SaveLayerRec contains the state used to create the Layer.
2022
2023Call restoreToCount with returned value to restore this and subsequent saves.
2024
2025#Param layerRec Layer state ##
2026
2027#Return depth of save state stack ##
2028
2029#Example
2030#Description
2031The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
2032Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
2033Where Layer was cleared, the original image will draw unchanged.
2034Outside of the circle the mandrill is brightened.
2035##
2036 #Image 3
2037 // sk_sp<SkImage> image = GetResourceAsImage("mandrill_256.png");
2038 canvas->drawImage(image, 0, 0, nullptr);
2039 SkCanvas::SaveLayerRec rec;
2040 SkPaint paint;
2041 paint.setBlendMode(SkBlendMode::kPlus);
2042 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
2043 rec.fPaint = &paint;
2044 canvas->saveLayer(rec);
2045 paint.setBlendMode(SkBlendMode::kClear);
2046 canvas->drawCircle(128, 128, 96, paint);
2047 canvas->restore();
2048##
2049
2050#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
2051
2052##
2053
2054#Topic Layer ##
2055
2056# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04002057#Topic Matrix
2058
2059#Method void translate(SkScalar dx, SkScalar dy)
2060
2061Translate Matrix by dx along the x-axis and dy along the y-axis.
2062
2063Mathematically, replace Matrix with a translation matrix
Cary Clarkce101242017-09-01 15:51:02 -04002064Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002065
2066This has the effect of moving the drawing by (dx, dy) before transforming
2067the result with Matrix.
2068
Cary Clarkbad5ad72017-08-03 17:14:08 -04002069#Param dx distance to translate in x ##
2070#Param dy distance to translate in y ##
Cary Clark8032b982017-07-28 11:04:54 -04002071
2072#Example
2073#Height 128
2074#Description
2075scale() followed by translate() produces different results from translate() followed
2076by scale().
2077
2078The blue stroke follows translate of (50, 50); a black
2079fill follows scale of (2, 1/2.f). After restoring the clip, which resets
2080Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
2081follows translate of (50, 50).
2082##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002083void draw(SkCanvas* canvas) {
2084 SkPaint filledPaint;
2085 SkPaint outlinePaint;
2086 outlinePaint.setStyle(SkPaint::kStroke_Style);
2087 outlinePaint.setColor(SK_ColorBLUE);
2088 canvas->save();
2089 canvas->translate(50, 50);
2090 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
2091 canvas->scale(2, 1/2.f);
2092 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
2093 canvas->restore();
2094 filledPaint.setColor(SK_ColorGRAY);
2095 outlinePaint.setColor(SK_ColorRED);
2096 canvas->scale(2, 1/2.f);
2097 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
2098 canvas->translate(50, 50);
2099 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04002100}
2101##
2102
2103#ToDo incomplete ##
2104
2105##
2106
2107# ------------------------------------------------------------------------------
2108
2109#Method void scale(SkScalar sx, SkScalar sy)
2110
2111Scale Matrix by sx on the x-axis and sy on the y-axis.
2112
2113Mathematically, replace Matrix with a scale matrix
Cary Clarkce101242017-09-01 15:51:02 -04002114Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002115
2116This has the effect of scaling the drawing by (sx, sy) before transforming
2117the result with Matrix.
2118
Cary Clarkbad5ad72017-08-03 17:14:08 -04002119#Param sx amount to scale in x ##
2120#Param sy amount to scale in y ##
Cary Clark8032b982017-07-28 11:04:54 -04002121
2122#Example
2123#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04002124void draw(SkCanvas* canvas) {
2125 SkPaint paint;
2126 SkRect rect = { 10, 20, 60, 120 };
2127 canvas->translate(20, 20);
2128 canvas->drawRect(rect, paint);
2129 canvas->scale(2, .5f);
2130 paint.setColor(SK_ColorGRAY);
2131 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002132}
2133##
2134
2135#ToDo incomplete ##
2136
2137##
2138
2139# ------------------------------------------------------------------------------
2140
2141#Method void rotate(SkScalar degrees)
2142
2143Rotate Matrix by degrees. Positive degrees rotates clockwise.
2144
2145Mathematically, replace Matrix with a rotation matrix
Cary Clarkce101242017-09-01 15:51:02 -04002146Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002147
2148This has the effect of rotating the drawing by degrees before transforming
2149the result with Matrix.
2150
Cary Clarkbad5ad72017-08-03 17:14:08 -04002151#Param degrees amount to rotate, in degrees ##
Cary Clark8032b982017-07-28 11:04:54 -04002152
2153#Example
2154#Description
2155Draw clock hands at time 5:10. The hour hand and minute hand point up and
2156are rotated clockwise.
2157##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002158void draw(SkCanvas* canvas) {
2159 SkPaint paint;
2160 paint.setStyle(SkPaint::kStroke_Style);
2161 canvas->translate(128, 128);
2162 canvas->drawCircle(0, 0, 60, paint);
2163 canvas->save();
2164 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
2165 canvas->drawLine(0, 0, 0, -50, paint);
2166 canvas->restore();
2167 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
2168 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002169}
2170##
2171
2172#ToDo incomplete ##
2173
2174##
2175
2176# ------------------------------------------------------------------------------
2177
2178#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
2179
Cary Clarkbad5ad72017-08-03 17:14:08 -04002180Rotate Matrix by degrees about a point at (px, py). Positive degrees rotates
2181clockwise.
Cary Clark8032b982017-07-28 11:04:54 -04002182
Cary Clarkce101242017-09-01 15:51:02 -04002183Mathematically, construct a rotation matrix. Premultiply the rotation matrix by
Cary Clark8032b982017-07-28 11:04:54 -04002184a translation matrix, then replace Matrix with the resulting matrix
Cary Clarkce101242017-09-01 15:51:02 -04002185Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002186
Cary Clarkbad5ad72017-08-03 17:14:08 -04002187This has the effect of rotating the drawing about a given point before
2188transforming the result with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002189
Cary Clarkbad5ad72017-08-03 17:14:08 -04002190#Param degrees amount to rotate, in degrees ##
2191#Param px x-coordinate of the point to rotate about ##
2192#Param py y-coordinate of the point to rotate about ##
Cary Clark8032b982017-07-28 11:04:54 -04002193
2194#Example
2195#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04002196void draw(SkCanvas* canvas) {
2197 SkPaint paint;
2198 paint.setTextSize(96);
2199 canvas->drawString("A1", 130, 100, paint);
2200 canvas->rotate(180, 130, 100);
2201 canvas->drawString("A1", 130, 100, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002202}
2203##
2204
2205#ToDo incomplete ##
2206
2207##
2208
2209# ------------------------------------------------------------------------------
2210
2211#Method void skew(SkScalar sx, SkScalar sy)
2212
Cary Clarkbad5ad72017-08-03 17:14:08 -04002213Skew Matrix by sx on the x-axis and sy on the y-axis. A positive value of sx
2214skews the drawing right as y increases; a positive value of sy skews the drawing
2215down as x increases.
Cary Clark8032b982017-07-28 11:04:54 -04002216
Cary Clarkce101242017-09-01 15:51:02 -04002217Mathematically, replace Matrix with a skew matrix Premultiplied with Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002218
Cary Clarkbad5ad72017-08-03 17:14:08 -04002219This has the effect of skewing the drawing by (sx, sy) before transforming
Cary Clark8032b982017-07-28 11:04:54 -04002220the result with Matrix.
2221
Cary Clarkbad5ad72017-08-03 17:14:08 -04002222#Param sx amount to skew in x ##
2223#Param sy amount to skew in y ##
2224
Cary Clark8032b982017-07-28 11:04:54 -04002225#Example
2226 #Description
2227 Black text mimics an oblique text style by using a negative skew in x that
2228 shifts the geometry to the right as the y values decrease.
2229 Red text uses a positive skew in y to shift the geometry down as the x values
2230 increase.
2231 Blue text combines x and y skew to rotate and scale.
2232 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002233 SkPaint paint;
2234 paint.setTextSize(128);
2235 canvas->translate(30, 130);
2236 canvas->save();
2237 canvas->skew(-.5, 0);
2238 canvas->drawString("A1", 0, 0, paint);
2239 canvas->restore();
2240 canvas->save();
2241 canvas->skew(0, .5);
2242 paint.setColor(SK_ColorRED);
2243 canvas->drawString("A1", 0, 0, paint);
2244 canvas->restore();
2245 canvas->skew(-.5, .5);
2246 paint.setColor(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04002247 canvas->drawString("A1", 0, 0, paint);
2248##
2249
2250#ToDo incomplete ##
2251
2252##
2253
2254# ------------------------------------------------------------------------------
2255
2256#Method void concat(const SkMatrix& matrix)
2257
Cary Clarkce101242017-09-01 15:51:02 -04002258Replace Matrix with matrix Premultiplied with existing Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002259
Cary Clarkbad5ad72017-08-03 17:14:08 -04002260This has the effect of transforming the drawn geometry by matrix, before
2261transforming the result with existing Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04002262
Cary Clarkce101242017-09-01 15:51:02 -04002263#Param matrix matrix to Premultiply with existing Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04002264
2265#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002266void draw(SkCanvas* canvas) {
2267 SkPaint paint;
2268 paint.setTextSize(80);
2269 paint.setTextScaleX(.3);
2270 SkMatrix matrix;
2271 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
2272 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
2273 canvas->drawRect(rect[0], paint);
2274 canvas->drawRect(rect[1], paint);
2275 paint.setColor(SK_ColorWHITE);
2276 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
2277 canvas->concat(matrix);
2278 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002279}
2280##
2281
2282#ToDo incomplete ##
2283
2284##
2285
2286# ------------------------------------------------------------------------------
2287
2288#Method void setMatrix(const SkMatrix& matrix)
2289
2290Replace Matrix with matrix.
2291Unlike concat(), any prior matrix state is overwritten.
2292
Cary Clarkbad5ad72017-08-03 17:14:08 -04002293#Param matrix matrix to copy, replacing existing Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04002294
2295#Example
2296#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002297void draw(SkCanvas* canvas) {
2298 SkPaint paint;
2299 canvas->scale(4, 6);
2300 canvas->drawString("truth", 2, 10, paint);
2301 SkMatrix matrix;
2302 matrix.setScale(2.8f, 6);
2303 canvas->setMatrix(matrix);
2304 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002305}
2306##
2307
2308#ToDo incomplete ##
2309
2310##
2311
2312# ------------------------------------------------------------------------------
2313
2314#Method void resetMatrix()
2315
2316Sets Matrix to the identity matrix.
2317Any prior matrix state is overwritten.
2318
2319#Example
2320#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002321void draw(SkCanvas* canvas) {
2322 SkPaint paint;
2323 canvas->scale(4, 6);
2324 canvas->drawString("truth", 2, 10, paint);
2325 canvas->resetMatrix();
2326 canvas->scale(2.8f, 6);
2327 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002328}
2329##
2330
2331#ToDo incomplete ##
2332
2333##
2334
2335# ------------------------------------------------------------------------------
2336
2337#Method const SkMatrix& getTotalMatrix() const
2338
2339Returns Matrix.
2340This does not account for translation by Device or Surface.
2341
Cary Clarkbad5ad72017-08-03 17:14:08 -04002342#Return Matrix in Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04002343
2344#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002345 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
2346 #StdOut
2347 isIdentity true
2348 ##
Cary Clark8032b982017-07-28 11:04:54 -04002349##
2350
2351#ToDo incomplete ##
2352
2353##
2354
2355#Topic Matrix ##
2356
2357# ------------------------------------------------------------------------------
2358#Topic Clip
2359
2360Clip is built from a stack of clipping paths. Each Path in the
2361stack can be constructed from one or more Path_Contour elements. The
2362Path_Contour may be composed of any number of Path_Verb segments. Each
2363Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
2364by Path_Contour.
2365
2366Clip stack of Path elements successfully restrict the Path area. Each
2367Path is transformed by Matrix, then intersected with or subtracted from the
2368prior Clip to form the replacement Clip. Use SkClipOp::kDifference
2369to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
2370with Clip.
2371
Cary Clarkce101242017-09-01 15:51:02 -04002372A clipping Path may be Anti-aliased; if Path, after transformation, is
Cary Clark8032b982017-07-28 11:04:54 -04002373composed of horizontal and vertical lines, clearing Anti-alias allows whole pixels
Cary Clarkce101242017-09-01 15:51:02 -04002374to either be inside or outside the clip. The fastest drawing has a Aliased,
2375rectangular clip.
Cary Clark8032b982017-07-28 11:04:54 -04002376
2377If clipping Path has Anti-alias set, clip may partially clip a pixel, requiring
2378that drawing blend partially with the destination along the edge. A rotated
Cary Clarkce101242017-09-01 15:51:02 -04002379rectangular Anti-aliased clip looks smoother but draws slower.
Cary Clark8032b982017-07-28 11:04:54 -04002380
2381Clip can combine with Rect and Round_Rect primitives; like
2382Path, these are transformed by Matrix before they are combined with Clip.
2383
2384Clip can combine with Region. Region is assumed to be in Device coordinates
2385and is unaffected by Matrix.
2386
2387#Example
2388#Height 90
2389 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002390 Draw a red circle with an Aliased clip and an Anti-aliased clip.
Cary Clark8032b982017-07-28 11:04:54 -04002391 Use an image filter to zoom into the pixels drawn.
Cary Clarkce101242017-09-01 15:51:02 -04002392 The edge of the Aliased clip fully draws pixels in the red circle.
2393 The edge of the Anti-aliased clip partially draws pixels in the red circle.
Cary Clark8032b982017-07-28 11:04:54 -04002394 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002395 SkPaint redPaint, scalePaint;
2396 redPaint.setAntiAlias(true);
2397 redPaint.setColor(SK_ColorRED);
2398 canvas->save();
2399 for (bool antialias : { false, true } ) {
2400 canvas->save();
2401 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
2402 canvas->drawCircle(17, 11, 8, redPaint);
2403 canvas->restore();
2404 canvas->translate(16, 0);
2405 }
2406 canvas->restore();
2407 SkMatrix matrix;
2408 matrix.setScale(6, 6);
2409 scalePaint.setImageFilter(
2410 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
2411 SkCanvas::SaveLayerRec saveLayerRec(
2412 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
2413 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04002414 canvas->restore();
2415##
2416
2417#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
2418
2419Replace Clip with the intersection or difference of Clip and rect,
Cary Clarkce101242017-09-01 15:51:02 -04002420with an Aliased or Anti-aliased clip edge. rect is transformed by Matrix
Cary Clark8032b982017-07-28 11:04:54 -04002421before it is combined with Clip.
2422
Cary Clarka523d2d2017-08-30 08:58:10 -04002423#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002424#Param op Clip_Op to apply to Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002425#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002426
2427#Example
2428#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002429void draw(SkCanvas* canvas) {
2430 canvas->rotate(10);
2431 SkPaint paint;
2432 paint.setAntiAlias(true);
2433 for (auto alias: { false, true } ) {
2434 canvas->save();
2435 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
2436 canvas->drawCircle(100, 60, 60, paint);
2437 canvas->restore();
2438 canvas->translate(80, 0);
2439 }
Cary Clark8032b982017-07-28 11:04:54 -04002440}
2441##
2442
2443#ToDo incomplete ##
2444
2445##
2446
2447#Method void clipRect(const SkRect& rect, SkClipOp op)
2448
2449Replace Clip with the intersection or difference of Clip and rect.
Cary Clarkce101242017-09-01 15:51:02 -04002450Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002451rect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002452
Cary Clarka523d2d2017-08-30 08:58:10 -04002453#Param rect Rect to combine with Clip ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002454#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002455
2456#Example
2457#Height 192
2458#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04002459void draw(SkCanvas* canvas) {
2460 SkPaint paint;
2461 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
2462 canvas->save();
2463 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
2464 canvas->drawCircle(100, 100, 60, paint);
2465 canvas->restore();
2466 canvas->translate(80, 0);
2467 }
Cary Clark8032b982017-07-28 11:04:54 -04002468}
2469##
2470
2471#ToDo incomplete ##
2472
2473##
2474
2475#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
2476
2477Replace Clip with the intersection of Clip and rect.
Cary Clarkce101242017-09-01 15:51:02 -04002478Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002479rect is transformed by Matrix
2480before it is combined with Clip.
2481
Cary Clarka523d2d2017-08-30 08:58:10 -04002482#Param rect Rect to combine with Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002483#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002484
2485#Example
2486#Height 133
2487 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002488 A circle drawn in pieces looks uniform when drawn Aliased.
2489 The same circle pieces blend with pixels more than once when Anti-aliased,
Cary Clark8032b982017-07-28 11:04:54 -04002490 visible as a thin pair of lines through the right circle.
2491 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002492void draw(SkCanvas* canvas) {
2493 canvas->clear(SK_ColorWHITE);
2494 SkPaint paint;
2495 paint.setAntiAlias(true);
2496 paint.setColor(0x8055aaff);
2497 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
2498 for (auto alias: { false, true } ) {
2499 canvas->save();
2500 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
2501 canvas->drawCircle(67, 67, 60, paint);
2502 canvas->restore();
2503 canvas->save();
2504 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
2505 canvas->drawCircle(67, 67, 60, paint);
2506 canvas->restore();
2507 canvas->translate(120, 0);
2508 }
Cary Clark8032b982017-07-28 11:04:54 -04002509}
2510##
2511
2512#ToDo incomplete ##
2513
2514##
2515
2516#Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect)
2517
Cary Clarkce101242017-09-01 15:51:02 -04002518Sets the maximum clip rectangle, which can be set by clipRect, clipRRect and
Cary Clark8032b982017-07-28 11:04:54 -04002519clipPath and intersect the current clip with the specified rect.
Cary Clarkce101242017-09-01 15:51:02 -04002520The maximum clip affects only future clipping operations; it is not retroactive.
Cary Clark8032b982017-07-28 11:04:54 -04002521The clip restriction is not recorded in pictures.
2522
Cary Clarkce101242017-09-01 15:51:02 -04002523Pass an empty rect to disable maximum clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002524
Cary Clark8032b982017-07-28 11:04:54 -04002525#Private
2526This is private API to be used only by Android framework.
2527##
2528
Cary Clarkbad5ad72017-08-03 17:14:08 -04002529#Param rect maximum allowed clip in device coordinates
Cary Clark579985c2017-07-31 11:48:27 -04002530#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04002531
2532##
2533
2534#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
2535
2536Replace Clip with the intersection or difference of Clip and rrect,
Cary Clarkce101242017-09-01 15:51:02 -04002537with an Aliased or Anti-aliased clip edge.
Cary Clark8032b982017-07-28 11:04:54 -04002538rrect is transformed by Matrix
2539before it is combined with Clip.
2540
Cary Clarkbad5ad72017-08-03 17:14:08 -04002541#Param rrect Round_Rect to combine with Clip ##
2542#Param op Clip_Op to apply to Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002543#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002544
2545#Example
2546#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002547void draw(SkCanvas* canvas) {
2548 canvas->clear(SK_ColorWHITE);
2549 SkPaint paint;
2550 paint.setAntiAlias(true);
2551 paint.setColor(0x8055aaff);
2552 SkRRect oval;
2553 oval.setOval({10, 20, 90, 100});
2554 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
2555 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002556}
2557##
2558
2559#ToDo incomplete ##
2560
2561##
2562
2563#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
2564
2565Replace Clip with the intersection or difference of Clip and rrect.
Cary Clarkce101242017-09-01 15:51:02 -04002566Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002567rrect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002568
Cary Clarkbad5ad72017-08-03 17:14:08 -04002569#Param rrect Round_Rect to combine with Clip ##
2570#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002571
2572#Example
2573#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002574void draw(SkCanvas* canvas) {
2575 SkPaint paint;
2576 paint.setColor(0x8055aaff);
2577 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
2578 canvas->clipRRect(oval, SkClipOp::kIntersect);
2579 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002580}
2581##
2582
2583#ToDo incomplete ##
2584
2585##
2586
2587#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
2588
2589Replace Clip with the intersection of Clip and rrect,
Cary Clarkce101242017-09-01 15:51:02 -04002590with an Aliased or Anti-aliased clip edge.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002591rrect is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002592
Cary Clarkbad5ad72017-08-03 17:14:08 -04002593#Param rrect Round_Rect to combine with Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002594#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002595
2596#Example
2597#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002598void draw(SkCanvas* canvas) {
2599 SkPaint paint;
2600 paint.setAntiAlias(true);
2601 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
2602 canvas->clipRRect(oval, true);
2603 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002604}
2605##
2606
2607#ToDo incomplete ##
2608
2609##
2610
2611#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
2612
2613Replace Clip with the intersection or difference of Clip and path,
Cary Clarkce101242017-09-01 15:51:02 -04002614with an Aliased or Anti-aliased clip edge. Path_Fill_Type determines if path
Cary Clark8032b982017-07-28 11:04:54 -04002615describes the area inside or outside its contours; and if Path_Contour overlaps
2616itself or another Path_Contour, whether the overlaps form part of the area.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002617path is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002618
Cary Clarkbad5ad72017-08-03 17:14:08 -04002619#Param path Path to combine with Clip ##
2620#Param op Clip_Op to apply to Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002621#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002622
2623#Example
2624#Description
2625Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
2626area outside clip is subtracted from circle.
2627
2628Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
2629area inside clip is intersected with circle.
2630##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002631void draw(SkCanvas* canvas) {
2632 SkPaint paint;
2633 paint.setAntiAlias(true);
2634 SkPath path;
2635 path.addRect({20, 30, 100, 110});
2636 path.setFillType(SkPath::kInverseWinding_FillType);
2637 canvas->save();
2638 canvas->clipPath(path, SkClipOp::kDifference, false);
2639 canvas->drawCircle(70, 100, 60, paint);
2640 canvas->restore();
2641 canvas->translate(100, 100);
2642 path.setFillType(SkPath::kWinding_FillType);
2643 canvas->clipPath(path, SkClipOp::kIntersect, false);
2644 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002645}
2646##
2647
2648#ToDo incomplete ##
2649
2650##
2651
2652#Method void clipPath(const SkPath& path, SkClipOp op)
2653
2654Replace Clip with the intersection or difference of Clip and path.
Cary Clarkce101242017-09-01 15:51:02 -04002655Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002656Path_Fill_Type determines if path
2657describes the area inside or outside its contours; and if Path_Contour overlaps
2658itself or another Path_Contour, whether the overlaps form part of the area.
2659path is transformed by Matrix
2660before it is combined with Clip.
2661
Cary Clarkbad5ad72017-08-03 17:14:08 -04002662#Param path Path to combine with Clip ##
2663#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002664
2665#Example
2666#Description
2667Overlapping Rects form a clip. When clip's Path_Fill_Type is set to
2668SkPath::kWinding_FillType, the overlap is included. Set to
2669SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2670##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002671void draw(SkCanvas* canvas) {
2672 SkPaint paint;
2673 paint.setAntiAlias(true);
2674 SkPath path;
2675 path.addRect({20, 15, 100, 95});
2676 path.addRect({50, 65, 130, 135});
2677 path.setFillType(SkPath::kWinding_FillType);
2678 canvas->save();
2679 canvas->clipPath(path, SkClipOp::kIntersect);
2680 canvas->drawCircle(70, 85, 60, paint);
2681 canvas->restore();
2682 canvas->translate(100, 100);
2683 path.setFillType(SkPath::kEvenOdd_FillType);
2684 canvas->clipPath(path, SkClipOp::kIntersect);
2685 canvas->drawCircle(70, 85, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002686}
2687##
2688
2689#ToDo incomplete ##
2690
2691##
2692
2693#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
2694
2695Replace Clip with the intersection of Clip and path.
Cary Clarkce101242017-09-01 15:51:02 -04002696Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002697Path_Fill_Type determines if path
2698describes the area inside or outside its contours; and if Path_Contour overlaps
2699itself or another Path_Contour, whether the overlaps form part of the area.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002700path is transformed by Matrix before it is combined with Clip.
Cary Clark8032b982017-07-28 11:04:54 -04002701
Cary Clarkbad5ad72017-08-03 17:14:08 -04002702#Param path Path to combine with Clip ##
Cary Clarkce101242017-09-01 15:51:02 -04002703#Param doAntiAlias true if Clip is to be Anti-aliased ##
Cary Clark8032b982017-07-28 11:04:54 -04002704
2705#Example
2706#Height 212
2707#Description
2708Clip loops over itself covering its center twice. When clip's Path_Fill_Type
2709is set to SkPath::kWinding_FillType, the overlap is included. Set to
2710SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2711##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002712void draw(SkCanvas* canvas) {
2713 SkPaint paint;
2714 paint.setAntiAlias(true);
2715 SkPath path;
2716 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2717 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2718 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2719 path.setFillType(SkPath::kWinding_FillType);
2720 canvas->save();
2721 canvas->clipPath(path, SkClipOp::kIntersect);
2722 canvas->drawCircle(50, 50, 45, paint);
2723 canvas->restore();
2724 canvas->translate(100, 100);
2725 path.setFillType(SkPath::kEvenOdd_FillType);
2726 canvas->clipPath(path, SkClipOp::kIntersect);
2727 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002728}
2729##
2730
2731#ToDo incomplete ##
2732
2733##
2734
2735# ------------------------------------------------------------------------------
2736
2737#Method void setAllowSimplifyClip(bool allow)
2738
2739#Experimental
2740Only used for testing.
2741##
2742
Cary Clarkce101242017-09-01 15:51:02 -04002743Set to simplify clip stack using PathOps.
Cary Clark8032b982017-07-28 11:04:54 -04002744
2745##
2746
2747# ------------------------------------------------------------------------------
2748
2749#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2750
2751Replace Clip with the intersection or difference of Clip and Region deviceRgn.
Cary Clarkce101242017-09-01 15:51:02 -04002752Resulting Clip is Aliased; pixels are fully contained by the clip.
Cary Clark8032b982017-07-28 11:04:54 -04002753deviceRgn is unaffected by Matrix.
2754
Cary Clarkbad5ad72017-08-03 17:14:08 -04002755#Param deviceRgn Region to combine with Clip ##
2756#Param op Clip_Op to apply to Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002757
2758#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002759#Description
Cary Clarkce101242017-09-01 15:51:02 -04002760 region is unaffected by canvas rotation; iRect is affected by canvas rotation.
2761 Both clips are Aliased; this is not noticeable on Region clip because it
Cary Clarkbad5ad72017-08-03 17:14:08 -04002762 aligns to pixel boundaries.
2763##
2764void draw(SkCanvas* canvas) {
2765 SkPaint paint;
2766 paint.setAntiAlias(true);
2767 SkIRect iRect = {30, 40, 120, 130 };
2768 SkRegion region(iRect);
2769 canvas->rotate(10);
2770 canvas->save();
2771 canvas->clipRegion(region, SkClipOp::kIntersect);
2772 canvas->drawCircle(50, 50, 45, paint);
2773 canvas->restore();
2774 canvas->translate(100, 100);
2775 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2776 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002777}
2778##
2779
2780#ToDo incomplete ##
2781
2782##
2783
2784#Method bool quickReject(const SkRect& rect) const
2785
2786Return true if Rect rect, transformed by Matrix, can be quickly determined to be
2787outside of Clip. May return false even though rect is outside of Clip.
2788
2789Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2790
Cary Clarkbad5ad72017-08-03 17:14:08 -04002791#Param rect Rect to compare with Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002792
Cary Clarkbad5ad72017-08-03 17:14:08 -04002793#Return true if rect, transformed by Matrix, does not intersect Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002794
2795#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002796void draw(SkCanvas* canvas) {
2797 SkRect testRect = {30, 30, 120, 129 };
2798 SkRect clipRect = {30, 130, 120, 230 };
2799 canvas->save();
2800 canvas->clipRect(clipRect);
2801 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2802 canvas->restore();
2803 canvas->rotate(10);
2804 canvas->clipRect(clipRect);
2805 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002806}
2807 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002808 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002809 quickReject false
2810 ##
2811##
2812
2813#ToDo incomplete ##
2814
2815##
2816
2817#Method bool quickReject(const SkPath& path) const
2818
2819Return true if path, transformed by Matrix, can be quickly determined to be
2820outside of Clip. May return false even though path is outside of Clip.
2821
2822Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2823
Cary Clarkbad5ad72017-08-03 17:14:08 -04002824#Param path Path to compare with Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002825
Cary Clarkbad5ad72017-08-03 17:14:08 -04002826#Return true if path, transformed by Matrix, does not intersect Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002827
2828#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002829void draw(SkCanvas* canvas) {
2830 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2831 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2832 SkPath testPath, clipPath;
2833 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2834 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2835 canvas->save();
2836 canvas->clipPath(clipPath);
2837 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2838 canvas->restore();
2839 canvas->rotate(10);
2840 canvas->clipPath(clipPath);
2841 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002842 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002843 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002844 quickReject false
2845 ##
2846}
2847##
2848
2849#ToDo incomplete ##
2850
2851##
2852
2853#Method SkRect getLocalClipBounds() const
2854
2855Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2856return SkRect::MakeEmpty, where all Rect sides equal zero.
2857
2858Rect returned is outset by one to account for partial pixel coverage if Clip
Cary Clarkce101242017-09-01 15:51:02 -04002859is Anti-aliased.
Cary Clark8032b982017-07-28 11:04:54 -04002860
Cary Clarkbad5ad72017-08-03 17:14:08 -04002861#Return bounds of Clip in local coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002862
2863#Example
2864 #Description
2865 Initial bounds is device bounds outset by 1 on all sides.
2866 Clipped bounds is clipPath bounds outset by 1 on all sides.
2867 Scaling the canvas by two in x and y scales the local bounds by 1/2 in x and y.
2868 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002869 SkCanvas local(256, 256);
2870 canvas = &local;
2871 SkRect bounds = canvas->getLocalClipBounds();
2872 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2873 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2874 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2875 SkPath clipPath;
2876 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2877 canvas->clipPath(clipPath);
2878 bounds = canvas->getLocalClipBounds();
2879 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2880 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2881 canvas->scale(2, 2);
2882 bounds = canvas->getLocalClipBounds();
2883 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2884 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2885 #StdOut
2886 left:-1 top:-1 right:257 bottom:257
2887 left:29 top:129 right:121 bottom:231
2888 left:14.5 top:64.5 right:60.5 bottom:115.5
2889 ##
Cary Clark8032b982017-07-28 11:04:54 -04002890##
2891
2892# local canvas in example works around bug in fiddle ##
2893#Bug 6524 ##
2894
2895##
2896
2897#Method bool getLocalClipBounds(SkRect* bounds) const
2898
2899Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2900return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2901
2902bounds is outset by one to account for partial pixel coverage if Clip
Cary Clarkce101242017-09-01 15:51:02 -04002903is Anti-aliased.
Cary Clark8032b982017-07-28 11:04:54 -04002904
Cary Clarkbad5ad72017-08-03 17:14:08 -04002905#Param bounds Rect of Clip in local coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002906
Cary Clarkbad5ad72017-08-03 17:14:08 -04002907#Return true if Clip bounds is not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04002908
2909#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002910 void draw(SkCanvas* canvas) {
2911 SkCanvas local(256, 256);
2912 canvas = &local;
2913 SkRect bounds;
2914 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2915 ? "false" : "true");
2916 SkPath path;
2917 canvas->clipPath(path);
2918 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2919 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002920 }
2921 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002922 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002923 local bounds empty = true
2924 ##
2925##
2926
2927# local canvas in example works around bug in fiddle ##
2928#Bug 6524 ##
2929
2930##
2931
2932#Method SkIRect getDeviceClipBounds() const
2933
2934Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2935return SkRect::MakeEmpty, where all Rect sides equal zero.
2936
2937Unlike getLocalClipBounds, returned IRect is not outset.
2938
Cary Clarkbad5ad72017-08-03 17:14:08 -04002939#Return bounds of Clip in Device coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002940
2941#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002942void draw(SkCanvas* canvas) {
2943 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002944 Initial bounds is device bounds, not outset.
2945 Clipped bounds is clipPath bounds, not outset.
2946 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 -04002947 ##
2948 SkCanvas device(256, 256);
2949 canvas = &device;
2950 SkIRect bounds = canvas->getDeviceClipBounds();
2951 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2952 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2953 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2954 SkPath clipPath;
2955 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2956 canvas->save();
2957 canvas->clipPath(clipPath);
2958 bounds = canvas->getDeviceClipBounds();
2959 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2960 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2961 canvas->restore();
2962 canvas->scale(1.f/2, 1.f/2);
2963 canvas->clipPath(clipPath);
2964 bounds = canvas->getDeviceClipBounds();
2965 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2966 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002967 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002968 left:0 top:0 right:256 bottom:256
2969 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002970 left:15 top:65 right:60 bottom:115
2971 ##
2972}
2973##
2974
2975#ToDo some confusion on why with an identity Matrix local and device are different ##
2976
2977# device canvas in example works around bug in fiddle ##
2978#Bug 6524 ##
2979
2980##
2981
2982#Method bool getDeviceClipBounds(SkIRect* bounds) const
2983
2984Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2985return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2986
2987Unlike getLocalClipBounds, bounds is not outset.
2988
Cary Clarkbad5ad72017-08-03 17:14:08 -04002989#Param bounds Rect of Clip in device coordinates ##
Cary Clark8032b982017-07-28 11:04:54 -04002990
Cary Clarkbad5ad72017-08-03 17:14:08 -04002991#Return true if Clip bounds is not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04002992
2993#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002994 void draw(SkCanvas* canvas) {
2995 SkIRect bounds;
2996 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2997 ? "false" : "true");
2998 SkPath path;
2999 canvas->clipPath(path);
3000 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
3001 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04003002 }
3003 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04003004 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04003005 device bounds empty = true
3006 ##
3007##
3008
3009#ToDo incomplete ##
3010
3011##
3012
3013#Topic Clip ##
3014
3015# ------------------------------------------------------------------------------
3016
3017#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
3018
3019Fill Clip with Color color.
3020mode determines how Color_ARGB is combined with destination.
3021
Cary Clarkbad5ad72017-08-03 17:14:08 -04003022#Param color Unpremultiplied Color_ARGB ##
3023#Param mode SkBlendMode used to combine source color and destination ##
Cary Clark8032b982017-07-28 11:04:54 -04003024
3025#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003026 canvas->drawColor(SK_ColorRED);
3027 canvas->clipRect(SkRect::MakeWH(150, 150));
3028 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
3029 canvas->clipRect(SkRect::MakeWH(75, 75));
3030 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04003031##
3032
3033#ToDo incomplete ##
3034
3035##
3036
3037# ------------------------------------------------------------------------------
3038
3039#Method void clear(SkColor color)
3040
3041Fill Clip with Color color using SkBlendMode::kSrc.
3042This has the effect of replacing all pixels contained by Clip with color.
3043
Cary Clarkbad5ad72017-08-03 17:14:08 -04003044#Param color Unpremultiplied Color_ARGB ##
Cary Clark8032b982017-07-28 11:04:54 -04003045
3046#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003047void draw(SkCanvas* canvas) {
3048 canvas->save();
3049 canvas->clipRect(SkRect::MakeWH(256, 128));
3050 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
3051 canvas->restore();
3052 canvas->save();
3053 canvas->clipRect(SkRect::MakeWH(150, 192));
3054 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
3055 canvas->restore();
3056 canvas->clipRect(SkRect::MakeWH(75, 256));
3057 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04003058}
3059##
3060
3061#ToDo incomplete ##
3062
3063##
3064
3065# ------------------------------------------------------------------------------
3066
3067#Method void discard()
3068
3069Make Canvas contents undefined. Subsequent calls that read Canvas pixels,
3070such as drawing with SkBlendMode, return undefined results. discard() does
3071not change Clip or Matrix.
3072
3073discard() may do nothing, depending on the implementation of Surface or Device
3074that created Canvas.
3075
3076discard() allows optimized performance on subsequent draws by removing
3077cached data associated with Surface or Device.
3078It is not necessary to call discard() once done with Canvas;
3079any cached data is deleted when owning Surface or Device is deleted.
3080
3081#ToDo example? not sure how to make this meaningful w/o more implementation detail ##
3082
3083#NoExample
3084##
3085
3086##
3087
3088# ------------------------------------------------------------------------------
3089
3090#Method void drawPaint(const SkPaint& paint)
3091
Cary Clarkbad5ad72017-08-03 17:14:08 -04003092Fill Clip with Paint paint. Paint components Rasterizer, Mask_Filter, Shader,
3093Color_Filter, Image_Filter, and Blend_Mode affect drawing;
3094Path_Effect in paint is ignored.
Cary Clark8032b982017-07-28 11:04:54 -04003095
3096# can Path_Effect in paint ever alter drawPaint?
3097
Cary Clarkbad5ad72017-08-03 17:14:08 -04003098#Param paint graphics state used to fill Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04003099
3100#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003101void draw(SkCanvas* canvas) {
3102 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
3103 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
3104 SkPaint paint;
3105 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
3106 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04003107}
3108##
3109
3110#ToDo incomplete ##
3111
3112##
3113
3114# ------------------------------------------------------------------------------
3115
3116#Enum PointMode
3117
3118#Code
3119 enum PointMode {
3120 kPoints_PointMode,
3121 kLines_PointMode,
Cary Clarkd0530ba2017-09-14 11:25:39 -04003122 kPolygon_PointMode,
Cary Clark8032b982017-07-28 11:04:54 -04003123 };
3124##
3125
3126Selects if an array of points are drawn as discrete points, as lines, or as
3127an open polygon.
3128
3129#Const kPoints_PointMode 0
3130 Draw each point separately.
3131##
3132
3133#Const kLines_PointMode 1
3134 Draw each pair of points as a line segment.
3135##
3136
3137#Const kPolygon_PointMode 2
3138 Draw the array of points as a open polygon.
3139##
3140
3141#Example
3142 #Description
3143 The upper left corner shows three squares when drawn as points.
3144 The upper right corner shows one line; when drawn as lines, two points are required per line.
3145 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
3146 The lower left corner shows two lines with a miter when path contains polygon.
3147 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003148void draw(SkCanvas* canvas) {
3149 SkPaint paint;
3150 paint.setStyle(SkPaint::kStroke_Style);
3151 paint.setStrokeWidth(10);
3152 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
3153 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
3154 canvas->translate(128, 0);
3155 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
3156 canvas->translate(0, 128);
3157 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
3158 SkPath path;
3159 path.addPoly(points, 3, false);
3160 canvas->translate(-128, 0);
3161 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003162}
3163##
3164
3165#ToDo incomplete ##
3166
3167##
3168
3169# ------------------------------------------------------------------------------
3170
3171#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
3172
3173Draw pts using Clip, Matrix and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003174count is the number of points; if count is less than one, has no effect.
Cary Clark8032b982017-07-28 11:04:54 -04003175mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
3176
Cary Clarkbad5ad72017-08-03 17:14:08 -04003177If mode is kPoints_PointMode, the shape of point drawn depends on paint
3178Paint_Stroke_Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
3179circle of diameter Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap
3180or SkPaint::kButt_Cap, each point draws a square of width and height
3181Paint_Stroke_Width.
Cary Clark8032b982017-07-28 11:04:54 -04003182
3183If mode is kLines_PointMode, each pair of points draws a line segment.
3184One line is drawn for every two points; each point is used once. If count is odd,
3185the final point is ignored.
3186
3187If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
3188count minus one lines are drawn; the first and last point are used once.
3189
3190Each line segment respects paint Paint_Stroke_Cap and Paint_Stroke_Width.
3191Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3192
Cary Clarkbad5ad72017-08-03 17:14:08 -04003193Always draws each element one at a time; is not affected by
3194Paint_Stroke_Join, and unlike drawPath, does not create a mask from all points
3195and lines before drawing.
Cary Clark8032b982017-07-28 11:04:54 -04003196
Cary Clarka523d2d2017-08-30 08:58:10 -04003197#Param mode whether pts draws points or lines ##
3198#Param count number of points in the array ##
3199#Param pts array of points to draw ##
3200#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003201
3202#Example
3203#Height 200
3204 #Description
3205 #List
3206 # The first column draws points. ##
3207 # The second column draws points as lines. ##
3208 # The third column draws points as a polygon. ##
3209 # The fourth column draws points as a polygonal path. ##
3210 # The first row uses a round cap and round join. ##
3211 # The second row uses a square cap and a miter join. ##
3212 # The third row uses a butt cap and a bevel join. ##
3213 ##
3214 The transparent color makes multiple line draws visible;
3215 the path is drawn all at once.
3216 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003217void draw(SkCanvas* canvas) {
3218 SkPaint paint;
3219 paint.setAntiAlias(true);
3220 paint.setStyle(SkPaint::kStroke_Style);
3221 paint.setStrokeWidth(10);
3222 paint.setColor(0x80349a45);
3223 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
3224 const SkPaint::Join join[] = { SkPaint::kRound_Join,
3225 SkPaint::kMiter_Join,
3226 SkPaint::kBevel_Join };
3227 int joinIndex = 0;
3228 SkPath path;
3229 path.addPoly(points, 3, false);
3230 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
3231 paint.setStrokeCap(cap);
3232 paint.setStrokeJoin(join[joinIndex++]);
3233 for (const auto mode : { SkCanvas::kPoints_PointMode,
3234 SkCanvas::kLines_PointMode,
3235 SkCanvas::kPolygon_PointMode } ) {
3236 canvas->drawPoints(mode, 3, points, paint);
3237 canvas->translate(64, 0);
3238 }
3239 canvas->drawPath(path, paint);
3240 canvas->translate(-192, 64);
3241 }
Cary Clark8032b982017-07-28 11:04:54 -04003242}
3243##
3244
3245#ToDo incomplete ##
3246
3247##
3248
3249# ------------------------------------------------------------------------------
3250
3251#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
3252
3253Draw point at (x, y) using Clip, Matrix and Paint paint.
3254
3255The shape of point drawn depends on paint Paint_Stroke_Cap.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003256If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
3257Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
Cary Clark8032b982017-07-28 11:04:54 -04003258draw a square of width and height Paint_Stroke_Width.
3259Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3260
Cary Clarkbad5ad72017-08-03 17:14:08 -04003261#Param x left edge of circle or square ##
3262#Param y top edge of circle or square ##
3263#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003264
3265#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003266void draw(SkCanvas* canvas) {
3267 SkPaint paint;
3268 paint.setAntiAlias(true);
3269 paint.setColor(0x80349a45);
3270 paint.setStyle(SkPaint::kStroke_Style);
3271 paint.setStrokeWidth(100);
3272 paint.setStrokeCap(SkPaint::kRound_Cap);
3273 canvas->scale(1, 1.2f);
3274 canvas->drawPoint(64, 96, paint);
3275 canvas->scale(.6f, .8f);
3276 paint.setColor(SK_ColorWHITE);
3277 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003278}
3279##
3280
3281#ToDo incomplete ##
3282
3283##
3284
Cary Clarkbad5ad72017-08-03 17:14:08 -04003285#Method void drawPoint(SkPoint p, const SkPaint& paint)
3286
3287Draw point p using Clip, Matrix and Paint paint.
3288
3289The shape of point drawn depends on paint Paint_Stroke_Cap.
3290If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
3291Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
3292draw a square of width and height Paint_Stroke_Width.
3293Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3294
3295#Param p top-left edge of circle or square ##
3296#Param paint stroke, blend, color, and so on, used to draw ##
3297
3298#Example
3299void draw(SkCanvas* canvas) {
3300 SkPaint paint;
3301 paint.setAntiAlias(true);
3302 paint.setColor(0x80349a45);
3303 paint.setStyle(SkPaint::kStroke_Style);
3304 paint.setStrokeWidth(100);
3305 paint.setStrokeCap(SkPaint::kSquare_Cap);
3306 canvas->scale(1, 1.2f);
3307 canvas->drawPoint({64, 96}, paint);
3308 canvas->scale(.6f, .8f);
3309 paint.setColor(SK_ColorWHITE);
3310 canvas->drawPoint(106, 120, paint);
3311}
3312##
3313
3314#SeeAlso drawPoints drawCircle drawRect
3315
3316##
3317
Cary Clark8032b982017-07-28 11:04:54 -04003318# ------------------------------------------------------------------------------
3319
3320#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
3321
Cary Clarkbad5ad72017-08-03 17:14:08 -04003322Draws line segment from (x0, y0) to (x1, y1) using Clip, Matrix, and Paint paint.
3323In paint: Paint_Stroke_Width describes the line thickness;
3324Paint_Stroke_Cap draws the end rounded or square;
Cary Clark8032b982017-07-28 11:04:54 -04003325Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3326
Cary Clarkbad5ad72017-08-03 17:14:08 -04003327#Param x0 start of line segment on x-axis ##
3328#Param y0 start of line segment on y-axis ##
3329#Param x1 end of line segment on x-axis ##
3330#Param y1 end of line segment on y-axis ##
3331#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003332
3333#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003334 SkPaint paint;
3335 paint.setAntiAlias(true);
3336 paint.setColor(0xFF9a67be);
3337 paint.setStrokeWidth(20);
3338 canvas->skew(1, 0);
3339 canvas->drawLine(32, 96, 32, 160, paint);
3340 canvas->skew(-2, 0);
3341 canvas->drawLine(288, 96, 288, 160, paint);
3342##
3343
3344#ToDo incomplete ##
3345
3346##
3347
3348#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
3349
3350Draws line segment from p0 to p1 using Clip, Matrix, and Paint paint.
3351In paint: Paint_Stroke_Width describes the line thickness;
3352Paint_Stroke_Cap draws the end rounded or square;
3353Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3354
3355#Param p0 start of line segment ##
3356#Param p1 end of line segment ##
3357#Param paint stroke, blend, color, and so on, used to draw ##
3358
3359#Example
3360 SkPaint paint;
3361 paint.setAntiAlias(true);
3362 paint.setColor(0xFF9a67be);
3363 paint.setStrokeWidth(20);
3364 canvas->skew(1, 0);
3365 canvas->drawLine({32, 96}, {32, 160}, paint);
3366 canvas->skew(-2, 0);
3367 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003368##
3369
3370#ToDo incomplete ##
3371
3372##
3373
3374# ------------------------------------------------------------------------------
3375
3376#Method void drawRect(const SkRect& rect, const SkPaint& paint)
3377
3378Draw Rect rect using Clip, Matrix, and Paint paint.
3379In paint: Paint_Style determines if rectangle is stroked or filled;
3380if stroked, Paint_Stroke_Width describes the line thickness, and
3381Paint_Stroke_Join draws the corners rounded or square.
3382
Cary Clarkbad5ad72017-08-03 17:14:08 -04003383#Param rect rectangle to be drawn ##
3384#Param paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003385
3386#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003387void draw(SkCanvas* canvas) {
3388 SkPoint rectPts[] = { {64, 48}, {192, 160} };
3389 SkPaint paint;
3390 paint.setAntiAlias(true);
3391 paint.setStyle(SkPaint::kStroke_Style);
3392 paint.setStrokeWidth(20);
3393 paint.setStrokeJoin(SkPaint::kRound_Join);
3394 SkMatrix rotator;
3395 rotator.setRotate(30, 128, 128);
3396 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3397 paint.setColor(color);
3398 SkRect rect;
3399 rect.set(rectPts[0], rectPts[1]);
3400 canvas->drawRect(rect, paint);
3401 rotator.mapPoints(rectPts, 2);
3402 }
Cary Clark8032b982017-07-28 11:04:54 -04003403}
3404##
3405
3406#ToDo incomplete ##
3407
3408##
3409
3410# ------------------------------------------------------------------------------
3411
3412#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
3413
3414Draw IRect rect using Clip, Matrix, and Paint paint.
3415In paint: Paint_Style determines if rectangle is stroked or filled;
3416if stroked, Paint_Stroke_Width describes the line thickness, and
3417Paint_Stroke_Join draws the corners rounded or square.
3418
Cary Clarkbad5ad72017-08-03 17:14:08 -04003419#Param rect rectangle to be drawn ##
3420#Param paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003421
3422#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003423 SkIRect rect = { 64, 48, 192, 160 };
3424 SkPaint paint;
3425 paint.setAntiAlias(true);
3426 paint.setStyle(SkPaint::kStroke_Style);
3427 paint.setStrokeWidth(20);
3428 paint.setStrokeJoin(SkPaint::kRound_Join);
3429 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3430 paint.setColor(color);
3431 canvas->drawIRect(rect, paint);
3432 canvas->rotate(30, 128, 128);
3433 }
Cary Clark8032b982017-07-28 11:04:54 -04003434##
3435
3436#ToDo incomplete ##
3437
3438##
3439
3440# ------------------------------------------------------------------------------
3441
3442#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
3443
3444Draw Region region using Clip, Matrix, and Paint paint.
3445In paint: Paint_Style determines if rectangle is stroked or filled;
3446if stroked, Paint_Stroke_Width describes the line thickness, and
3447Paint_Stroke_Join draws the corners rounded or square.
3448
Cary Clarkbad5ad72017-08-03 17:14:08 -04003449#Param region region to be drawn ##
3450#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003451
3452#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003453void draw(SkCanvas* canvas) {
3454 SkRegion region;
3455 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3456 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3457 SkPaint paint;
3458 paint.setAntiAlias(true);
3459 paint.setStyle(SkPaint::kStroke_Style);
3460 paint.setStrokeWidth(20);
3461 paint.setStrokeJoin(SkPaint::kRound_Join);
3462 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003463}
3464##
3465
3466#ToDo incomplete ##
3467
3468##
3469
3470# ------------------------------------------------------------------------------
3471
3472#Method void drawOval(const SkRect& oval, const SkPaint& paint)
3473
3474Draw Oval oval using Clip, Matrix, and Paint.
3475In paint: Paint_Style determines if Oval is stroked or filled;
3476if stroked, Paint_Stroke_Width describes the line thickness.
3477
Cary Clarkbad5ad72017-08-03 17:14:08 -04003478#Param oval Rect bounds of Oval ##
3479#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003480
3481#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003482void draw(SkCanvas* canvas) {
3483 canvas->clear(0xFF3f5f9f);
3484 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
3485 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
3486 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
3487 SkScalar pos[] = { 0.2f, 1.0f };
3488 SkRect bounds = SkRect::MakeWH(80, 70);
3489 SkPaint paint;
3490 paint.setAntiAlias(true);
3491 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
3492 SkShader::kClamp_TileMode));
3493 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04003494}
3495##
3496
3497#ToDo incomplete ##
3498
3499##
3500
3501# ------------------------------------------------------------------------------
3502
3503#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
3504
3505Draw Round_Rect rrect using Clip, Matrix, and Paint paint.
3506In paint: Paint_Style determines if rrect is stroked or filled;
3507if stroked, Paint_Stroke_Width describes the line thickness.
3508
Cary Clarkbad5ad72017-08-03 17:14:08 -04003509rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
3510may have any combination of positive non-square radii for the four corners.
Cary Clark8032b982017-07-28 11:04:54 -04003511
Cary Clarkbad5ad72017-08-03 17:14:08 -04003512#Param rrect Round_Rect with up to eight corner radii to draw ##
3513#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003514
3515#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003516void draw(SkCanvas* canvas) {
3517 SkPaint paint;
3518 paint.setAntiAlias(true);
3519 SkRect outer = {30, 40, 210, 220};
3520 SkRect radii = {30, 50, 70, 90 };
3521 SkRRect rRect;
3522 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
3523 canvas->drawRRect(rRect, paint);
3524 paint.setColor(SK_ColorWHITE);
3525 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
3526 outer.fLeft + radii.fLeft, outer.fBottom, paint);
3527 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
3528 outer.fRight - radii.fRight, outer.fBottom, paint);
3529 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
3530 outer.fRight, outer.fTop + radii.fTop, paint);
3531 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
3532 outer.fRight, outer.fBottom - radii.fBottom, paint);
3533}
Cary Clark8032b982017-07-28 11:04:54 -04003534##
3535
3536#ToDo incomplete ##
3537
3538##
3539
3540# ------------------------------------------------------------------------------
3541
3542#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
3543
3544Draw Round_Rect outer and inner
3545using Clip, Matrix, and Paint paint.
3546outer must contain inner or the drawing is undefined.
Cary Clarkce101242017-09-01 15:51:02 -04003547In paint: Paint_Style determines if Round_Rect is stroked or filled;
Cary Clark8032b982017-07-28 11:04:54 -04003548if stroked, Paint_Stroke_Width describes the line thickness.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003549If stroked and Round_Rect corner has zero length radii, Paint_Stroke_Join can
3550draw corners rounded or square.
Cary Clark8032b982017-07-28 11:04:54 -04003551
Cary Clarkbad5ad72017-08-03 17:14:08 -04003552GPU-backed platforms optimize drawing when both outer and inner are
Cary Clark8032b982017-07-28 11:04:54 -04003553concave and outer contains inner. These platforms may not be able to draw
3554Path built with identical data as fast.
3555
Cary Clarkbad5ad72017-08-03 17:14:08 -04003556#Param outer Round_Rect outer bounds to draw ##
3557#Param inner Round_Rect inner bounds to draw ##
3558#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003559
3560#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003561void draw(SkCanvas* canvas) {
3562 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3563 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
3564 SkPaint paint;
3565 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003566}
3567##
3568
3569#Example
3570#Description
3571 Outer Rect has no corner radii, but stroke join is rounded.
3572 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
3573 Stroke join does not affect inner Round_Rect since it has no sharp corners.
3574##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003575void draw(SkCanvas* canvas) {
3576 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3577 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
3578 SkPaint paint;
3579 paint.setAntiAlias(true);
3580 paint.setStyle(SkPaint::kStroke_Style);
3581 paint.setStrokeWidth(20);
3582 paint.setStrokeJoin(SkPaint::kRound_Join);
3583 canvas->drawDRRect(outer, inner, paint);
3584 paint.setStrokeWidth(1);
3585 paint.setColor(SK_ColorWHITE);
3586 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04003587}
3588##
3589
3590#ToDo incomplete ##
3591
3592##
3593
3594# ------------------------------------------------------------------------------
3595
3596#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
3597
3598Draw Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint.
3599If radius is zero or less, nothing is drawn.
3600In paint: Paint_Style determines if Circle is stroked or filled;
3601if stroked, Paint_Stroke_Width describes the line thickness.
3602
Cary Clarkbad5ad72017-08-03 17:14:08 -04003603#Param cx Circle center on the x-axis ##
3604#Param cy Circle center on the y-axis ##
3605#Param radius half the diameter of Circle ##
3606#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003607
3608#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003609 void draw(SkCanvas* canvas) {
3610 SkPaint paint;
3611 paint.setAntiAlias(true);
3612 canvas->drawCircle(128, 128, 90, paint);
3613 paint.setColor(SK_ColorWHITE);
3614 canvas->drawCircle(86, 86, 20, paint);
3615 canvas->drawCircle(160, 76, 20, paint);
3616 canvas->drawCircle(140, 150, 35, paint);
3617 }
3618##
3619
3620#ToDo incomplete ##
3621
3622##
3623
3624#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
3625
Cary Clarkce101242017-09-01 15:51:02 -04003626Draw Circle at center with radius using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003627If radius is zero or less, nothing is drawn.
3628In paint: Paint_Style determines if Circle is stroked or filled;
3629if stroked, Paint_Stroke_Width describes the line thickness.
3630
3631#Param center Circle center ##
3632#Param radius half the diameter of Circle ##
3633#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
3634
3635#Example
3636 void draw(SkCanvas* canvas) {
3637 SkPaint paint;
3638 paint.setAntiAlias(true);
3639 canvas->drawCircle(128, 128, 90, paint);
3640 paint.setColor(SK_ColorWHITE);
3641 canvas->drawCircle({86, 86}, 20, paint);
3642 canvas->drawCircle({160, 76}, 20, paint);
3643 canvas->drawCircle({140, 150}, 35, paint);
3644 }
Cary Clark8032b982017-07-28 11:04:54 -04003645##
3646
3647#ToDo incomplete ##
3648
3649##
3650
3651# ------------------------------------------------------------------------------
3652
3653#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
3654 bool useCenter, const SkPaint& paint)
3655
3656Draw Arc using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003657
Cary Clark8032b982017-07-28 11:04:54 -04003658Arc is part of Oval bounded by oval, sweeping from startAngle to startAngle plus
3659sweepAngle. startAngle and sweepAngle are in degrees.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003660
Cary Clark8032b982017-07-28 11:04:54 -04003661startAngle of zero places start point at the right middle edge of oval.
3662A positive sweepAngle places Arc end point clockwise from start point;
3663a negative sweepAngle places Arc end point counterclockwise from start point.
3664sweepAngle may exceed 360 degrees, a full circle.
3665If useCenter is true, draw a wedge that includes lines from oval
3666center to Arc end points. If useCenter is false, draw Arc between end points.
3667
3668If Rect oval is empty or sweepAngle is zero, nothing is drawn.
3669
Cary Clarkbad5ad72017-08-03 17:14:08 -04003670#Param oval Rect bounds of Oval containing Arc to draw ##
3671#Param startAngle angle in degrees where Arc begins ##
3672#Param sweepAngle sweep angle in degrees; positive is clockwise ##
3673#Param useCenter if true, include the center of the oval ##
3674#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003675
3676#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04003677 void draw(SkCanvas* canvas) {
3678 SkPaint paint;
3679 paint.setAntiAlias(true);
3680 SkRect oval = { 4, 4, 60, 60};
3681 for (auto useCenter : { false, true } ) {
3682 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
3683 paint.setStyle(style);
3684 for (auto degrees : { 45, 90, 180, 360} ) {
3685 canvas->drawArc(oval, 0, degrees , useCenter, paint);
3686 canvas->translate(64, 0);
3687 }
3688 canvas->translate(-256, 64);
3689 }
3690 }
Cary Clark8032b982017-07-28 11:04:54 -04003691 }
3692##
3693
3694#Example
3695#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003696 void draw(SkCanvas* canvas) {
3697 SkPaint paint;
3698 paint.setAntiAlias(true);
3699 paint.setStyle(SkPaint::kStroke_Style);
3700 paint.setStrokeWidth(4);
3701 SkRect oval = { 4, 4, 60, 60};
3702 float intervals[] = { 5, 5 };
3703 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
3704 for (auto degrees : { 270, 360, 540, 720 } ) {
3705 canvas->drawArc(oval, 0, degrees, false, paint);
3706 canvas->translate(64, 0);
3707 }
Cary Clark8032b982017-07-28 11:04:54 -04003708 }
3709##
3710
3711#ToDo incomplete ##
3712
3713##
3714
3715# ------------------------------------------------------------------------------
3716
3717#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
3718
Cary Clarkbad5ad72017-08-03 17:14:08 -04003719Draw Round_Rect bounded by Rect rect, with corner radii (rx, ry) using Clip,
3720Matrix, and Paint paint.
3721
Cary Clark8032b982017-07-28 11:04:54 -04003722In paint: Paint_Style determines if Round_Rect is stroked or filled;
3723if stroked, Paint_Stroke_Width describes the line thickness.
3724If rx or ry are less than zero, they are treated as if they are zero.
3725If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003726If rx and ry are zero, Round_Rect is drawn as Rect and if stroked is affected by
3727Paint_Stroke_Join.
Cary Clark8032b982017-07-28 11:04:54 -04003728
Cary Clarkbad5ad72017-08-03 17:14:08 -04003729#Param rect Rect bounds of Round_Rect to draw ##
Cary Clarkce101242017-09-01 15:51:02 -04003730#Param rx axis length in x of oval describing rounded corners ##
3731#Param ry axis length in y of oval describing rounded corners ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003732#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003733
3734#Example
3735#Description
3736 Top row has a zero radius a generates a rectangle.
3737 Second row radii sum to less than sides.
3738 Third row radii sum equals sides.
3739 Fourth row radii sum exceeds sides; radii are scaled to fit.
3740##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003741 void draw(SkCanvas* canvas) {
3742 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
3743 SkPaint paint;
3744 paint.setStrokeWidth(15);
3745 paint.setStrokeJoin(SkPaint::kRound_Join);
3746 paint.setAntiAlias(true);
3747 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
3748 paint.setStyle(style );
3749 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
3750 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
3751 canvas->translate(0, 60);
3752 }
3753 canvas->translate(80, -240);
3754 }
Cary Clark8032b982017-07-28 11:04:54 -04003755 }
3756##
3757
3758#ToDo incomplete ##
3759
3760##
3761
3762# ------------------------------------------------------------------------------
3763
3764#Method void drawPath(const SkPath& path, const SkPaint& paint)
3765
3766Draw Path path using Clip, Matrix, and Paint paint.
3767Path contains an array of Path_Contour, each of which may be open or closed.
3768
3769In paint: Paint_Style determines if Round_Rect is stroked or filled:
Cary Clarkbad5ad72017-08-03 17:14:08 -04003770if filled, Path_Fill_Type determines whether Path_Contour describes inside or
3771outside of fill; if stroked, Paint_Stroke_Width describes the line thickness,
3772Paint_Stroke_Cap describes line ends, and Paint_Stroke_Join describes how
3773corners are drawn.
Cary Clark8032b982017-07-28 11:04:54 -04003774
Cary Clarkbad5ad72017-08-03 17:14:08 -04003775#Param path Path to draw ##
3776#Param paint stroke, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003777
3778#Example
3779#Description
3780 Top rows draw stroked path with combinations of joins and caps. The open contour
3781 is affected by caps; the closed contour is affected by joins.
3782 Bottom row draws fill the same for open and closed contour.
3783 First bottom column shows winding fills overlap.
3784 Second bottom column shows even odd fills exclude overlap.
3785 Third bottom column shows inverse winding fills area outside both contours.
3786##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003787void draw(SkCanvas* canvas) {
3788 SkPath path;
3789 path.moveTo(20, 20);
3790 path.quadTo(60, 20, 60, 60);
3791 path.close();
3792 path.moveTo(60, 20);
3793 path.quadTo(60, 60, 20, 60);
3794 SkPaint paint;
3795 paint.setStrokeWidth(10);
3796 paint.setAntiAlias(true);
3797 paint.setStyle(SkPaint::kStroke_Style);
3798 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
3799 paint.setStrokeJoin(join);
3800 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
3801 paint.setStrokeCap(cap);
3802 canvas->drawPath(path, paint);
3803 canvas->translate(80, 0);
3804 }
3805 canvas->translate(-240, 60);
3806 }
3807 paint.setStyle(SkPaint::kFill_Style);
3808 for (auto fill : { SkPath::kWinding_FillType,
3809 SkPath::kEvenOdd_FillType,
3810 SkPath::kInverseWinding_FillType } ) {
3811 path.setFillType(fill);
3812 canvas->save();
3813 canvas->clipRect({0, 10, 80, 70});
3814 canvas->drawPath(path, paint);
3815 canvas->restore();
3816 canvas->translate(80, 0);
3817 }
Cary Clark8032b982017-07-28 11:04:54 -04003818}
3819##
3820
3821#ToDo incomplete ##
3822
3823##
3824
3825# ------------------------------------------------------------------------------
3826#Topic Draw_Image
3827
Cary Clarkbad5ad72017-08-03 17:14:08 -04003828drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
3829a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04003830
Cary Clark73fa9722017-08-29 17:36:51 -04003831#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04003832
3833Draw Image image, with its top-left corner at (left, top),
3834using Clip, Matrix, and optional Paint paint.
3835
Cary Clarkbad5ad72017-08-03 17:14:08 -04003836If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode,
3837and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3838If paint contains Mask_Filter, generate mask from image bounds. If generated
3839mask extends beyond image bounds, replicate image edge colors, just as Shader
3840made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
3841image's edge color when it samples outside of its bounds.
Cary Clark8032b982017-07-28 11:04:54 -04003842
Cary Clarkbad5ad72017-08-03 17:14:08 -04003843#Param image uncompressed rectangular map of pixels ##
3844#Param left left side of image ##
3845#Param top top side of image ##
3846#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3847 and so on; or nullptr
3848##
Cary Clark8032b982017-07-28 11:04:54 -04003849
3850#Example
3851#Height 64
3852#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003853void draw(SkCanvas* canvas) {
3854 // sk_sp<SkImage> image;
3855 SkImage* imagePtr = image.get();
3856 canvas->drawImage(imagePtr, 0, 0);
3857 SkPaint paint;
3858 canvas->drawImage(imagePtr, 80, 0, &paint);
3859 paint.setAlpha(0x80);
3860 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003861}
3862##
3863
3864#ToDo incomplete ##
3865
3866##
3867
3868# ------------------------------------------------------------------------------
3869
3870#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003871 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04003872
3873Draw Image image, with its top-left corner at (left, top),
3874using Clip, Matrix, and optional Paint paint.
3875
Cary Clarkbad5ad72017-08-03 17:14:08 -04003876If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3877Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3878If paint contains Mask_Filter, generate mask from image bounds. If generated
3879mask extends beyond image bounds, replicate image edge colors, just as Shader
3880made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
3881image's edge color when it samples outside of its bounds.
Cary Clark8032b982017-07-28 11:04:54 -04003882
Cary Clarkbad5ad72017-08-03 17:14:08 -04003883#Param image uncompressed rectangular map of pixels ##
3884#Param left left side of image ##
3885#Param top pop side of image ##
3886#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3887 and so on; or nullptr
3888##
Cary Clark8032b982017-07-28 11:04:54 -04003889
3890#Example
3891#Height 64
3892#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003893void draw(SkCanvas* canvas) {
3894 // sk_sp<SkImage> image;
3895 canvas->drawImage(image, 0, 0);
3896 SkPaint paint;
3897 canvas->drawImage(image, 80, 0, &paint);
3898 paint.setAlpha(0x80);
3899 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003900}
3901##
3902
3903#ToDo incomplete ##
3904
3905##
3906
3907# ------------------------------------------------------------------------------
3908
3909#Enum SrcRectConstraint
3910
3911#Code
3912 enum SrcRectConstraint {
3913 kStrict_SrcRectConstraint,
3914 kFast_SrcRectConstraint,
3915 };
3916##
3917
Cary Clarkce101242017-09-01 15:51:02 -04003918SrcRectConstraint controls the behavior at the edge of source Rect,
3919provided to drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04003920
Cary Clarkce101242017-09-01 15:51:02 -04003921Image_Filter in Paint may sample multiple pixels in the image. Source Rect
Cary Clarkbad5ad72017-08-03 17:14:08 -04003922restricts the bounds of pixels that may be read. Image_Filter may slow down if
Cary Clarkce101242017-09-01 15:51:02 -04003923it cannot read outside the bounds, when sampling near the edge of source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003924SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
Cary Clarkce101242017-09-01 15:51:02 -04003925outside source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003926
3927#Const kStrict_SrcRectConstraint
Cary Clarkce101242017-09-01 15:51:02 -04003928 Requires Image_Filter to respect source Rect,
Cary Clark8032b982017-07-28 11:04:54 -04003929 sampling only inside of its bounds, possibly with a performance penalty.
3930##
3931
3932#Const kFast_SrcRectConstraint
Cary Clarkce101242017-09-01 15:51:02 -04003933 Permits Image_Filter to sample outside of source Rect
Cary Clark8032b982017-07-28 11:04:54 -04003934 by half the width of Image_Filter, permitting it to run faster but with
3935 error at the image edges.
3936##
3937
3938#Example
3939#Height 64
3940#Description
3941 redBorder contains a black and white checkerboard bordered by red.
3942 redBorder is drawn scaled by 16 on the left.
Cary Clarkce101242017-09-01 15:51:02 -04003943 The middle and right bitmaps are filtered checkerboards.
Cary Clark8032b982017-07-28 11:04:54 -04003944 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3945 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3946##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003947void draw(SkCanvas* canvas) {
3948 SkBitmap redBorder;
3949 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3950 SkCanvas checkRed(redBorder);
3951 checkRed.clear(SK_ColorRED);
3952 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3953 { SK_ColorWHITE, SK_ColorBLACK } };
3954 checkRed.writePixels(
3955 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3956 canvas->scale(16, 16);
3957 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3958 canvas->resetMatrix();
3959 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3960 SkPaint lowPaint;
3961 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3962 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3963 SkCanvas::kFast_SrcRectConstraint } ) {
3964 canvas->translate(80, 0);
3965 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3966 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3967 }
Cary Clark8032b982017-07-28 11:04:54 -04003968}
3969##
3970
3971#ToDo incomplete ##
3972
3973##
3974
3975# ------------------------------------------------------------------------------
3976
3977#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3978 const SkPaint* paint,
3979 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3980
3981Draw Rect src of Image image, scaled and translated to fill Rect dst.
3982Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003983
Cary Clarkbad5ad72017-08-03 17:14:08 -04003984If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3985Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
3986If paint contains Mask_Filter, generate mask from image bounds.
3987
3988If generated mask extends beyond image bounds, replicate image edge colors, just
3989as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
3990replicates the image's edge color when it samples outside of its bounds.
3991
3992constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
3993sample within src; set to kFast_SrcRectConstraint allows sampling outside to
3994improve performance.
3995
3996#Param image Image containing pixels, dimensions, and format ##
3997#Param src source Rect of image to draw from ##
3998#Param dst destination Rect of image to draw to ##
3999#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4000 and so on; or nullptr
4001##
4002#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004003
4004#Example
4005#Height 64
4006#Description
4007 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
4008 its bounds; there's no bleeding with kFast_SrcRectConstraint.
4009 the middle and right bitmaps draw with kLow_SkFilterQuality; with
4010 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
4011 with kFast_SrcRectConstraint red bleeds on the edges.
4012##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004013void draw(SkCanvas* canvas) {
4014 uint32_t pixels[][4] = {
4015 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
4016 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
4017 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
4018 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
4019 SkBitmap redBorder;
4020 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
4021 (void*) pixels, sizeof(pixels[0]));
4022 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
4023 SkPaint lowPaint;
4024 for (auto constraint : {
4025 SkCanvas::kFast_SrcRectConstraint,
4026 SkCanvas::kStrict_SrcRectConstraint,
4027 SkCanvas::kFast_SrcRectConstraint } ) {
4028 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
4029 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
4030 lowPaint.setFilterQuality(kLow_SkFilterQuality);
4031 canvas->translate(80, 0);
4032 }
4033}
Cary Clark8032b982017-07-28 11:04:54 -04004034##
4035
4036#ToDo incomplete ##
4037
4038##
4039
4040# ------------------------------------------------------------------------------
4041
4042#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
4043 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4044
4045Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004046Note that isrc is on integer pixel boundaries; dst may include fractional
4047boundaries. Additionally transform draw using Clip, Matrix, and optional Paint
4048paint.
Cary Clark8032b982017-07-28 11:04:54 -04004049
Cary Clarkbad5ad72017-08-03 17:14:08 -04004050If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4051Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4052If paint contains Mask_Filter, generate mask from image bounds.
4053
4054If generated mask extends beyond image bounds, replicate image edge colors, just
4055as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4056replicates the image's edge color when it samples outside of its bounds.
4057
4058constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004059sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004060improve performance.
4061
4062#Param image Image containing pixels, dimensions, and format ##
4063#Param isrc source IRect of image to draw from ##
4064#Param dst destination Rect of image to draw to ##
4065#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4066 and so on; or nullptr
4067##
Cary Clarkce101242017-09-01 15:51:02 -04004068#Param constraint filter strictly within isrc or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004069
4070#Example
4071#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04004072void draw(SkCanvas* canvas) {
4073 // sk_sp<SkImage> image;
4074 for (auto i : { 1, 2, 4, 8 } ) {
4075 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
4076 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
4077 }
Cary Clark8032b982017-07-28 11:04:54 -04004078}
4079##
4080
4081#ToDo incomplete ##
4082
4083##
4084
4085# ------------------------------------------------------------------------------
4086
4087#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
4088 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4089
Cary Clarkbad5ad72017-08-03 17:14:08 -04004090Draw Image image, scaled and translated to fill Rect dst, using Clip, Matrix,
4091and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004092
Cary Clarkbad5ad72017-08-03 17:14:08 -04004093If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4094Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4095If paint contains Mask_Filter, generate mask from image bounds.
4096
4097If generated mask extends beyond image bounds, replicate image edge colors, just
4098as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4099replicates the image's edge color when it samples outside of its bounds.
4100
4101constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004102sample within image; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004103improve performance.
4104
4105#Param image Image containing pixels, dimensions, and format ##
4106#Param dst destination Rect of image to draw to ##
4107#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4108 and so on; or nullptr
4109##
Cary Clarkce101242017-09-01 15:51:02 -04004110#Param constraint filter strictly within image or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004111
4112#Example
4113#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04004114void draw(SkCanvas* canvas) {
4115 // sk_sp<SkImage> image;
4116 for (auto i : { 20, 40, 80, 160 } ) {
4117 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
4118 }
Cary Clark8032b982017-07-28 11:04:54 -04004119}
4120##
4121
4122#ToDo incomplete ##
4123
4124##
4125
4126# ------------------------------------------------------------------------------
4127
4128#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
4129 const SkPaint* paint,
4130 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4131
4132Draw Rect src of Image image, scaled and translated to fill Rect dst.
4133Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004134
Cary Clarkbad5ad72017-08-03 17:14:08 -04004135If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4136Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4137If paint contains Mask_Filter, generate mask from image bounds.
4138
4139If generated mask extends beyond image bounds, replicate image edge colors, just
4140as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4141replicates the image's edge color when it samples outside of its bounds.
4142
4143constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4144sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4145improve performance.
4146
4147#Param image Image containing pixels, dimensions, and format ##
4148#Param src source Rect of image to draw from ##
4149#Param dst destination Rect of image to draw to ##
4150#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4151 and so on; or nullptr
4152##
4153#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004154
4155#Example
4156#Height 64
4157#Description
4158 Canvas scales and translates; transformation from src to dst also scales.
4159 The two matrices are concatenated to create the final transformation.
4160##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004161void draw(SkCanvas* canvas) {
4162 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
4163 { SK_ColorWHITE, SK_ColorBLACK } };
4164 SkBitmap bitmap;
4165 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4166 (void*) pixels, sizeof(pixels[0]));
4167 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4168 SkPaint paint;
4169 canvas->scale(4, 4);
4170 for (auto alpha : { 50, 100, 150, 255 } ) {
4171 paint.setAlpha(alpha);
4172 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
4173 canvas->translate(8, 0);
4174 }
4175}
Cary Clark8032b982017-07-28 11:04:54 -04004176##
4177
4178#ToDo incomplete ##
4179
4180##
4181
4182# ------------------------------------------------------------------------------
4183
4184#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
4185 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4186
4187Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004188isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004189Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004190
Cary Clarkbad5ad72017-08-03 17:14:08 -04004191If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4192Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4193If paint contains Mask_Filter, generate mask from image bounds.
4194
4195If generated mask extends beyond image bounds, replicate image edge colors, just
4196as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4197replicates the image's edge color when it samples outside of its bounds.
4198
4199constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004200sample within image; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004201improve performance.
4202
4203#Param image Image containing pixels, dimensions, and format ##
4204#Param isrc source IRect of image to draw from ##
4205#Param dst destination Rect of image to draw to ##
4206#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4207 and so on; or nullptr
4208##
Cary Clarkce101242017-09-01 15:51:02 -04004209#Param constraint filter strictly within image or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004210
4211#Example
4212#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004213void draw(SkCanvas* canvas) {
4214 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
4215 { 0xAAAAAAAA, 0xFFFFFFFF} };
4216 SkBitmap bitmap;
4217 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4218 (void*) pixels, sizeof(pixels[0]));
4219 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4220 SkPaint paint;
4221 canvas->scale(4, 4);
4222 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4223 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4224 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
4225 canvas->translate(8, 0);
4226 }
Cary Clark8032b982017-07-28 11:04:54 -04004227}
4228##
4229
4230#ToDo incomplete ##
4231##
4232
4233# ------------------------------------------------------------------------------
4234
4235#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
4236 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4237
4238Draw Image image, scaled and translated to fill Rect dst,
4239using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004240
Cary Clarkbad5ad72017-08-03 17:14:08 -04004241If 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
4249constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004250sample within image; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004251improve performance.
4252
4253#Param image Image containing pixels, dimensions, and format ##
4254#Param dst destination Rect of image to draw to ##
4255#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4256 and so on; or nullptr
4257##
Cary Clarkce101242017-09-01 15:51:02 -04004258#Param constraint filter strictly within image or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004259
4260#Example
4261#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004262void draw(SkCanvas* canvas) {
4263 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4264 { 0xAAAA0000, 0xFFFF0000} };
4265 SkBitmap bitmap;
4266 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4267 (void*) pixels, sizeof(pixels[0]));
4268 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4269 SkPaint paint;
4270 canvas->scale(4, 4);
4271 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4272 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4273 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
4274 canvas->translate(8, 0);
4275 }
Cary Clark8032b982017-07-28 11:04:54 -04004276}
4277##
4278
4279#ToDo incomplete ##
4280
4281##
4282
4283# ------------------------------------------------------------------------------
4284
4285#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
4286 const SkPaint* paint = nullptr)
4287
Cary Clarkd0530ba2017-09-14 11:25:39 -04004288Draw Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004289IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04004290the center. Corners are unmodified or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04004291are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004292
Cary Clarkbad5ad72017-08-03 17:14:08 -04004293Additionally transform draw using Clip, Matrix, and optional Paint paint.
4294
4295If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4296Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4297If paint contains Mask_Filter, generate mask from image bounds.
4298
4299If generated mask extends beyond image bounds, replicate image edge colors, just
4300as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4301replicates the image's edge color when it samples outside of its bounds.
4302
4303#Param image Image containing pixels, dimensions, and format ##
4304#Param center IRect edge of image corners and sides ##
4305#Param dst destination Rect of image to draw to ##
4306#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4307 and so on; or nullptr
4308##
Cary Clark8032b982017-07-28 11:04:54 -04004309
4310#Example
4311#Height 128
4312#Description
4313 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004314 The second image equals the size of center; only corners are drawn without scaling.
4315 The remaining images are larger than center. All corners draw without scaling.
4316 The sides and center are scaled if needed to take up the remaining space.
Cary Clark8032b982017-07-28 11:04:54 -04004317##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004318void draw(SkCanvas* canvas) {
4319 SkIRect center = { 20, 10, 50, 40 };
4320 SkBitmap bitmap;
4321 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4322 SkCanvas bitCanvas(bitmap);
4323 SkPaint paint;
4324 SkColor gray = 0xFF000000;
4325 int left = 0;
4326 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4327 int top = 0;
4328 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4329 paint.setColor(gray);
4330 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4331 gray += 0x001f1f1f;
4332 top = bottom;
4333 }
4334 left = right;
4335 }
4336 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4337 SkImage* imagePtr = image.get();
4338 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4339 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4340 canvas->translate(dest + 4, 0);
4341 }
Cary Clark8032b982017-07-28 11:04:54 -04004342}
4343##
4344
4345#ToDo incomplete ##
4346
4347##
4348
4349# ------------------------------------------------------------------------------
4350
4351#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
4352 const SkPaint* paint = nullptr)
4353
Cary Clarkd0530ba2017-09-14 11:25:39 -04004354Draw Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004355IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04004356the center. Corners are not scaled, or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04004357are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004358
Cary Clarkbad5ad72017-08-03 17:14:08 -04004359Additionally transform draw using Clip, Matrix, and optional Paint paint.
4360
4361If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4362Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
4363If paint contains Mask_Filter, generate mask from image bounds.
4364
4365If generated mask extends beyond image bounds, replicate image edge colors, just
4366as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
4367replicates the image's edge color when it samples outside of its bounds.
4368
4369#Param image Image containing pixels, dimensions, and format ##
4370#Param center IRect edge of image corners and sides ##
4371#Param dst destination Rect of image to draw to ##
4372#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4373 and so on; or nullptr
4374##
Cary Clark8032b982017-07-28 11:04:54 -04004375
4376#Example
4377#Height 128
4378#Description
4379 The two leftmost images has four corners and sides to the left and right of center.
4380 The leftmost image scales the width of corners proportionately to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004381 The third and fourth image corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04004382 fill the remaining space.
4383 The rightmost image has four corners scaled vertically to fit, and uses sides above
4384 and below center to fill the remaining space.
4385##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004386void draw(SkCanvas* canvas) {
4387 SkIRect center = { 20, 10, 50, 40 };
4388 SkBitmap bitmap;
4389 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4390 SkCanvas bitCanvas(bitmap);
4391 SkPaint paint;
4392 SkColor gray = 0xFF000000;
4393 int left = 0;
4394 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4395 int top = 0;
4396 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4397 paint.setColor(gray);
4398 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4399 gray += 0x001f1f1f;
4400 top = bottom;
4401 }
4402 left = right;
4403 }
4404 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4405 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4406 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4407 canvas->translate(dest + 4, 0);
4408 }
Cary Clark8032b982017-07-28 11:04:54 -04004409}
4410##
4411
4412#ToDo incomplete ##
4413
4414##
4415
4416# ------------------------------------------------------------------------------
4417
4418#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04004419 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04004420
4421Draw Bitmap bitmap, with its top-left corner at (left, top),
4422using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004423
Cary Clarkbad5ad72017-08-03 17:14:08 -04004424If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4425Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4426If paint contains Mask_Filter, generate mask from bitmap bounds.
4427
4428If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4429just as Shader made from SkShader::MakeBitmapShader with
4430SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4431outside of its bounds.
4432
4433#Param bitmap Bitmap containing pixels, dimensions, and format ##
4434#Param left left side of bitmap ##
4435#Param top top side of bitmap ##
4436#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4437 and so on; or nullptr
4438##
Cary Clark8032b982017-07-28 11:04:54 -04004439
4440#Example
4441#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004442void draw(SkCanvas* canvas) {
4443 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4444 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4445 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4446 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4447 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4448 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4449 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
4450 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
4451 SkBitmap bitmap;
4452 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4453 (void*) pixels, sizeof(pixels[0]));
4454 SkPaint paint;
4455 canvas->scale(4, 4);
4456 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4457 paint.setColor(color);
4458 canvas->drawBitmap(bitmap, 0, 0, &paint);
4459 canvas->translate(12, 0);
4460 }
Cary Clark8032b982017-07-28 11:04:54 -04004461}
4462##
4463
4464#ToDo incomplete ##
4465
4466##
4467
4468# ------------------------------------------------------------------------------
4469
4470#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
4471 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4472
4473Draw Rect src of Bitmap bitmap, scaled and translated to fill Rect dst.
4474Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004475
Cary Clarkbad5ad72017-08-03 17:14:08 -04004476If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4477Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4478If paint contains Mask_Filter, generate mask from bitmap bounds.
4479
4480If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4481just as Shader made from SkShader::MakeBitmapShader with
4482SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4483outside of its bounds.
4484
4485constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
4486sample within src; set to kFast_SrcRectConstraint allows sampling outside to
4487improve performance.
4488
4489#Param bitmap Bitmap containing pixels, dimensions, and format ##
4490#Param src source Rect of image to draw from ##
4491#Param dst destination Rect of image to draw to ##
4492#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4493 and so on; or nullptr
4494##
4495#Param constraint filter strictly within src or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004496
4497#Example
4498#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004499void draw(SkCanvas* canvas) {
4500 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4501 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4502 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4503 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4504 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4505 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4506 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4507 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
4508 SkBitmap bitmap;
4509 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4510 (void*) pixels, sizeof(pixels[0]));
4511 SkPaint paint;
4512 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 6));
4513 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4514 paint.setColor(color);
4515 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4516 canvas->translate(48, 0);
4517 }
Cary Clark8032b982017-07-28 11:04:54 -04004518}
4519##
4520
4521#ToDo incomplete ##
4522
4523##
4524
4525# ------------------------------------------------------------------------------
4526
4527#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
4528 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4529
4530Draw IRect isrc of Bitmap bitmap, scaled and translated to fill Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004531isrc is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004532Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004533
Cary Clarkbad5ad72017-08-03 17:14:08 -04004534If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4535Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4536If paint contains Mask_Filter, generate mask from bitmap bounds.
4537
4538If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4539just as Shader made from SkShader::MakeBitmapShader with
4540SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4541outside of its bounds.
4542
4543constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004544sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004545improve performance.
4546
4547#Param bitmap Bitmap containing pixels, dimensions, and format ##
4548#Param isrc source IRect of image to draw from ##
4549#Param dst destination Rect of image to draw to ##
4550#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4551 and so on; or nullptr
4552##
Cary Clarkce101242017-09-01 15:51:02 -04004553#Param constraint sample strictly within isrc, or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004554
4555#Example
4556#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004557void draw(SkCanvas* canvas) {
4558 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4559 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4560 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4561 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4562 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
4563 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
4564 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4565 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
4566 SkBitmap bitmap;
4567 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4568 (void*) pixels, sizeof(pixels[0]));
4569 SkPaint paint;
4570 paint.setFilterQuality(kHigh_SkFilterQuality);
4571 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
4572 paint.setColor(color);
4573 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4574 canvas->translate(48.25f, 0);
4575 }
Cary Clark8032b982017-07-28 11:04:54 -04004576}
4577##
4578
4579#ToDo incomplete ##
4580
4581##
4582
4583# ------------------------------------------------------------------------------
4584
4585#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
4586 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4587
4588Draw Bitmap bitmap, scaled and translated to fill Rect dst.
Cary Clarkce101242017-09-01 15:51:02 -04004589bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries.
Cary Clark8032b982017-07-28 11:04:54 -04004590Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004591
Cary Clarkbad5ad72017-08-03 17:14:08 -04004592If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4593Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4594If paint contains Mask_Filter, generate mask from bitmap bounds.
4595
4596If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4597just as Shader made from SkShader::MakeBitmapShader with
4598SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4599outside of its bounds.
4600
4601constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
Cary Clarkce101242017-09-01 15:51:02 -04004602sample within bitmap; set to kFast_SrcRectConstraint allows sampling outside to
Cary Clarkbad5ad72017-08-03 17:14:08 -04004603improve performance.
4604
4605#Param bitmap Bitmap containing pixels, dimensions, and format ##
4606#Param dst destination Rect of image to draw to ##
4607#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4608 and so on; or nullptr
4609##
Cary Clarkce101242017-09-01 15:51:02 -04004610#Param constraint filter strictly within bitmap or draw faster ##
Cary Clark8032b982017-07-28 11:04:54 -04004611
4612#Example
4613#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04004614void draw(SkCanvas* canvas) {
4615 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4616 { 0xAAAA0000, 0xFFFF0000} };
4617 SkBitmap bitmap;
4618 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4619 (void*) pixels, sizeof(pixels[0]));
4620 SkPaint paint;
4621 canvas->scale(4, 4);
4622 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4623 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4624 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
4625 canvas->translate(8, 0);
4626 }
Cary Clark8032b982017-07-28 11:04:54 -04004627}
4628##
4629
4630#ToDo incomplete ##
4631
4632##
4633
4634# ------------------------------------------------------------------------------
4635
4636#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04004637 const SkPaint* paint = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04004638
Cary Clarkd0530ba2017-09-14 11:25:39 -04004639Draw Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004640IRect center divides the bitmap into nine sections: four sides, four corners,
Cary Clarkce101242017-09-01 15:51:02 -04004641and the center. Corners are not scaled, or scaled down proportionately if their
Cary Clarkbad5ad72017-08-03 17:14:08 -04004642sides are larger than dst; center and four sides are scaled to fit remaining
4643space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004644
Cary Clarkbad5ad72017-08-03 17:14:08 -04004645Additionally transform draw using Clip, Matrix, and optional Paint paint.
4646
4647If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4648Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4649If paint contains Mask_Filter, generate mask from bitmap bounds.
4650
4651If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4652just as Shader made from SkShader::MakeBitmapShader with
4653SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4654outside of its bounds.
4655
4656#Param bitmap Bitmap containing pixels, dimensions, and format ##
4657#Param center IRect edge of image corners and sides ##
4658#Param dst destination Rect of image to draw to ##
4659#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4660 and so on; or nullptr
4661##
Cary Clark8032b982017-07-28 11:04:54 -04004662
4663#Example
4664#Height 128
4665#Description
4666 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4667 The leftmost bitmap draw scales the width of corners proportionately to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004668 The third and fourth draw corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04004669 fill the remaining space.
4670 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4671 and below center to fill the remaining space.
4672##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004673void draw(SkCanvas* canvas) {
4674 SkIRect center = { 20, 10, 50, 40 };
4675 SkBitmap bitmap;
4676 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4677 SkCanvas bitCanvas(bitmap);
4678 SkPaint paint;
4679 SkColor gray = 0xFF000000;
4680 int left = 0;
4681 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4682 int top = 0;
4683 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4684 paint.setColor(gray);
4685 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4686 gray += 0x001f1f1f;
4687 top = bottom;
4688 }
4689 left = right;
4690 }
4691 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4692 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4693 canvas->translate(dest + 4, 0);
4694 }
Cary Clark8032b982017-07-28 11:04:54 -04004695}
4696##
4697
4698#ToDo incomplete ##
4699
4700##
4701
4702# ------------------------------------------------------------------------------
4703#Struct Lattice
4704
4705 Lattice divides Bitmap or Image into a rectangular grid.
4706 Grid entries on even columns and even rows are fixed; these entries are
4707 always drawn at their original size if the destination is large enough.
4708 If the destination side is too small to hold the fixed entries, all fixed
4709 entries are proportionately scaled down to fit.
4710 The grid entries not on even columns and rows are scaled to fit the
4711 remaining space, if any.
4712
4713#Code
4714 struct Lattice {
4715 enum Flags {...
4716
4717 const int* fXDivs;
4718 const int* fYDivs;
4719 const Flags* fFlags;
4720 int fXCount;
4721 int fYCount;
4722 const SkIRect* fBounds;
4723 };
4724##
4725
4726 #Enum Flags
4727 #Code
4728 enum Flags : uint8_t {
4729 kTransparent_Flags = 1 << 0,
4730 };
4731 ##
4732
4733 Optional setting per rectangular grid entry to make it transparent.
4734
4735 #Const kTransparent_Flags 1
4736 Set to skip lattice rectangle by making it transparent.
4737 ##
4738 ##
4739
4740 #Member const int* fXDivs
4741 Array of x-coordinates that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004742 Array entries must be unique, increasing, greater than or equal to
4743 fBounds left edge, and less than fBounds right edge.
4744 Set the first element to fBounds left to collapse the left column of
4745 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04004746 ##
4747
4748 #Member const int* fYDivs
4749 Array of y-coordinates that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004750 Array entries must be unique, increasing, greater than or equal to
4751 fBounds top edge, and less than fBounds bottom edge.
4752 Set the first element to fBounds top to collapse the top row of fixed
4753 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04004754 ##
4755
4756 #Member const Flags* fFlags
4757 Optional array of Flags, one per rectangular grid entry:
Cary Clarkbad5ad72017-08-03 17:14:08 -04004758 array length must be
4759 #Formula
4760 (fXCount + 1) * (fYCount + 1)
4761 ##
4762 .
Cary Clark8032b982017-07-28 11:04:54 -04004763 Array entries correspond to the rectangular grid entries, ascending
4764 left to right and then top to bottom.
4765 ##
4766
4767 #Member int fXCount
Cary Clarkbad5ad72017-08-03 17:14:08 -04004768 Number of entries in fXDivs array; one less than the number of
4769 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04004770 ##
4771
4772 #Member int fYCount
Cary Clarkbad5ad72017-08-03 17:14:08 -04004773 Number of entries in fYDivs array; one less than the number of vertical
4774 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04004775 ##
4776
4777 #Member const SkIRect* fBounds
4778 Optional subset IRect source to draw from.
4779 If nullptr, source bounds is dimensions of Bitmap or Image.
4780 ##
4781
4782#Struct Lattice ##
4783
4784#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
4785 const SkPaint* paint = nullptr)
4786
Cary Clarkd0530ba2017-09-14 11:25:39 -04004787Draw Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04004788
4789Lattice lattice divides bitmap into a rectangular grid.
4790Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04004791of drawBitmapNine, fixed lattice elements never scale larger than their initial
4792size and shrink proportionately when all fixed elements exceed the bitmap's
4793dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004794
4795Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004796
Cary Clarkbad5ad72017-08-03 17:14:08 -04004797If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4798Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4799If paint contains Mask_Filter, generate mask from bitmap bounds.
4800
4801If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4802just as Shader made from SkShader::MakeBitmapShader with
4803SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4804outside of its bounds.
4805
4806#Param bitmap Bitmap containing pixels, dimensions, and format ##
4807#Param lattice division of bitmap into fixed and variable rectangles ##
4808#Param dst destination Rect of image to draw to ##
4809#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4810 and so on; or nullptr
4811##
Cary Clark8032b982017-07-28 11:04:54 -04004812
4813#Example
4814#Height 128
4815#Description
4816 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4817 The leftmost bitmap draw scales the width of corners proportionately to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004818 The third and fourth draw corners are not scaled; the sides are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04004819 fill the remaining space; the center is transparent.
4820 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4821 and below center to fill the remaining space.
4822##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004823void draw(SkCanvas* canvas) {
4824 SkIRect center = { 20, 10, 50, 40 };
4825 SkBitmap bitmap;
4826 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4827 SkCanvas bitCanvas(bitmap);
4828 SkPaint paint;
4829 SkColor gray = 0xFF000000;
4830 int left = 0;
4831 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4832 int top = 0;
4833 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4834 paint.setColor(gray);
4835 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4836 gray += 0x001f1f1f;
4837 top = bottom;
4838 }
4839 left = right;
4840 }
4841 const int xDivs[] = { center.fLeft, center.fRight };
4842 const int yDivs[] = { center.fTop, center.fBottom };
4843 SkCanvas::Lattice::Flags flags[3][3];
4844 memset(flags, 0, sizeof(flags));
4845 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4846 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4847 SK_ARRAY_COUNT(yDivs), nullptr };
4848 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4849 canvas->drawBitmapLattice(bitmap, lattice , SkRect::MakeWH(dest, 110 - dest), nullptr);
4850 canvas->translate(dest + 4, 0);
4851 }
Cary Clark8032b982017-07-28 11:04:54 -04004852}
4853##
4854
4855#ToDo incomplete ##
4856
4857##
4858
4859# ------------------------------------------------------------------------------
4860
4861#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
4862 const SkPaint* paint = nullptr)
4863
Cary Clarkd0530ba2017-09-14 11:25:39 -04004864Draw Image image stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04004865
4866Lattice lattice divides image into a rectangular grid.
4867Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04004868of drawBitmapNine, fixed lattice elements never scale larger than their initial
4869size and shrink proportionately when all fixed elements exceed the bitmap's
4870dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04004871
4872Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004873
Cary Clarkbad5ad72017-08-03 17:14:08 -04004874If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
4875Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
4876If paint contains Mask_Filter, generate mask from bitmap bounds.
4877
4878If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
4879just as Shader made from SkShader::MakeBitmapShader with
4880SkShader::kClamp_TileMode set replicates the bitmap's edge color when it samples
4881outside of its bounds.
4882
4883#Param image Image containing pixels, dimensions, and format ##
4884#Param lattice division of bitmap into fixed and variable rectangles ##
4885#Param dst destination Rect of image to draw to ##
4886#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
4887 and so on; or nullptr
4888##
Cary Clark8032b982017-07-28 11:04:54 -04004889
4890#Example
4891#Height 128
4892#Description
4893 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04004894 The second image equals the size of center; only corners are drawn without scaling.
4895 The remaining images are larger than center. All corners draw without scaling. The sides
Cary Clark8032b982017-07-28 11:04:54 -04004896 are scaled if needed to take up the remaining space; the center is transparent.
4897##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004898void draw(SkCanvas* canvas) {
4899 SkIRect center = { 20, 10, 50, 40 };
4900 SkBitmap bitmap;
4901 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4902 SkCanvas bitCanvas(bitmap);
4903 SkPaint paint;
4904 SkColor gray = 0xFF000000;
4905 int left = 0;
4906 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4907 int top = 0;
4908 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4909 paint.setColor(gray);
4910 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4911 gray += 0x001f1f1f;
4912 top = bottom;
4913 }
4914 left = right;
4915 }
4916 const int xDivs[] = { center.fLeft, center.fRight };
4917 const int yDivs[] = { center.fTop, center.fBottom };
4918 SkCanvas::Lattice::Flags flags[3][3];
4919 memset(flags, 0, sizeof(flags));
4920 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4921 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4922 SK_ARRAY_COUNT(yDivs), nullptr };
4923 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4924 SkImage* imagePtr = image.get();
4925 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4926 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4927 canvas->translate(dest + 4, 0);
4928 }
Cary Clark8032b982017-07-28 11:04:54 -04004929}
4930##
4931
4932#ToDo incomplete ##
4933
4934##
4935
4936#Topic Draw_Image ##
4937
4938# ------------------------------------------------------------------------------
4939
4940#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
4941 const SkPaint& paint)
4942
4943Draw text, with origin at (x, y), using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004944
Cary Clarkbad5ad72017-08-03 17:14:08 -04004945text's meaning depends on Paint_Text_Encoding; by default, text encoding is
4946UTF-8.
Cary Clark8032b982017-07-28 11:04:54 -04004947
Cary Clarkbad5ad72017-08-03 17:14:08 -04004948x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
4949text draws left to right, positioning the first glyph's left side bearing at x
4950and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4951
4952All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
4953Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04004954filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004955
Cary Clarkce101242017-09-01 15:51:02 -04004956#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004957#Param byteLength byte length of text array ##
4958#Param x start of text on x-axis ##
4959#Param y start of text on y-axis ##
4960#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004961
4962#Example
4963#Height 200
4964#Description
4965 The same text is drawn varying Paint_Text_Size and varying
4966 Matrix.
4967##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004968void draw(SkCanvas* canvas) {
4969 SkPaint paint;
4970 paint.setAntiAlias(true);
4971 float textSizes[] = { 12, 18, 24, 36 };
4972 for (auto size: textSizes ) {
4973 paint.setTextSize(size);
4974 canvas->drawText("Aa", 2, 10, 20, paint);
4975 canvas->translate(0, size * 2);
4976 }
4977 paint.reset();
4978 paint.setAntiAlias(true);
4979 float yPos = 20;
4980 for (auto size: textSizes ) {
4981 float scale = size / 12.f;
4982 canvas->resetMatrix();
4983 canvas->translate(100, 0);
4984 canvas->scale(scale, scale);
4985 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
4986 yPos += size * 2;
4987 }
4988}
Cary Clark8032b982017-07-28 11:04:54 -04004989##
4990
4991#ToDo incomplete ##
4992
4993##
4994
4995#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
4996
Cary Clarkbad5ad72017-08-03 17:14:08 -04004997Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
4998Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04004999
Cary Clarkbad5ad72017-08-03 17:14:08 -04005000string's meaning depends on Paint_Text_Encoding; by default, string encoding is
5001UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
5002results, since zero bytes may be embedded in the string.
Cary Clark8032b982017-07-28 11:04:54 -04005003
Cary Clarkbad5ad72017-08-03 17:14:08 -04005004x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
5005string draws left to right, positioning the first glyph's left side bearing at x
5006and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
5007
5008All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5009Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005010filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005011
Cary Clarkce101242017-09-01 15:51:02 -04005012#Param string character code points or Glyphs drawn,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005013 ending with a char value of zero
5014##
5015#Param x start of string on x-axis ##
5016#Param y start of string on y-axis ##
5017#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005018
5019#Example
5020 SkPaint paint;
5021 canvas->drawString("a small hello", 20, 20, paint);
5022##
5023
5024#SeeAlso drawText
5025
5026##
5027
5028#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
5029
Cary Clarkbad5ad72017-08-03 17:14:08 -04005030Draw null terminated string, with origin at (x, y), using Clip, Matrix, and
5031Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005032
Cary Clarkbad5ad72017-08-03 17:14:08 -04005033string's meaning depends on Paint_Text_Encoding; by default, string encoding is
5034UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
5035results, since zero bytes may be embedded in the string.
Cary Clark8032b982017-07-28 11:04:54 -04005036
Cary Clarkbad5ad72017-08-03 17:14:08 -04005037x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
5038string draws left to right, positioning the first glyph's left side bearing at x
5039and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
5040
5041All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5042Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005043filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005044
Cary Clarkce101242017-09-01 15:51:02 -04005045#Param string character code points or Glyphs drawn,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005046 ending with a char value of zero
5047##
5048#Param x start of string on x-axis ##
5049#Param y start of string on y-axis ##
5050#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005051
5052#Example
5053 SkPaint paint;
5054 SkString string("a small hello");
5055 canvas->drawString(string, 20, 20, paint);
5056##
5057
5058#SeeAlso drawText
5059
5060##
5061
5062# ------------------------------------------------------------------------------
5063
5064#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
5065 const SkPaint& paint)
5066
Cary Clarkbad5ad72017-08-03 17:14:08 -04005067Draw each glyph in text with the origin in pos array, using Clip, Matrix, and
Cary Clarkce101242017-09-01 15:51:02 -04005068Paint paint. The number of entries in pos array must match the number of Glyphs
Cary Clarkbad5ad72017-08-03 17:14:08 -04005069described by byteLength of text.
Cary Clark8032b982017-07-28 11:04:54 -04005070
Cary Clarkbad5ad72017-08-03 17:14:08 -04005071text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5072UTF-8. pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text;
5073by default each glyph's left side bearing is positioned at x and its
5074baseline is positioned at y. Text size is affected by Matrix and
5075Paint_Text_Size.
Cary Clark8032b982017-07-28 11:04:54 -04005076
Cary Clarkbad5ad72017-08-03 17:14:08 -04005077All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5078Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005079filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005080
5081Layout engines such as Harfbuzz typically position each glyph
Cary Clark8032b982017-07-28 11:04:54 -04005082rather than using the font's advance widths.
5083
Cary Clarkce101242017-09-01 15:51:02 -04005084#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005085#Param byteLength byte length of text array ##
5086#Param pos array of glyph origins ##
5087#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005088
5089#Example
5090#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04005091void draw(SkCanvas* canvas) {
5092 const char hello[] = "HeLLo!";
5093 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
5094 {172, 100} };
5095 SkPaint paint;
5096 paint.setTextSize(60);
5097 canvas->drawPosText(hello, strlen(hello), pos, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005098}
5099##
5100
5101#ToDo incomplete ##
5102
5103##
5104
5105# ------------------------------------------------------------------------------
5106
5107#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
5108 const SkPaint& paint)
5109
Cary Clarkbad5ad72017-08-03 17:14:08 -04005110Draw each glyph in text with its (x, y) origin composed from xpos array and
5111constY, using Clip, Matrix, and Paint paint. The number of entries in xpos array
Cary Clarkce101242017-09-01 15:51:02 -04005112must match the number of Glyphs described by byteLength of text.
Cary Clark8032b982017-07-28 11:04:54 -04005113
Cary Clarkbad5ad72017-08-03 17:14:08 -04005114text's meaning depends on Paint_Text_Encoding; by default, text encoding is
Cary Clarkce101242017-09-01 15:51:02 -04005115UTF-8. xpos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text;
Cary Clarkbad5ad72017-08-03 17:14:08 -04005116by default each glyph's left side bearing is positioned at an xpos element and
5117its baseline is positioned at constY. Text size is affected by Matrix and
5118Paint_Text_Size.
Cary Clark8032b982017-07-28 11:04:54 -04005119
Cary Clarkbad5ad72017-08-03 17:14:08 -04005120All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5121Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005122filled 12 point black Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005123
Cary Clarkbad5ad72017-08-03 17:14:08 -04005124Layout engines such as Harfbuzz typically position each glyph
Cary Clarkce101242017-09-01 15:51:02 -04005125rather than using the font's advance widths if all Glyphs share the same
Cary Clarkbad5ad72017-08-03 17:14:08 -04005126baseline.
5127
Cary Clarkce101242017-09-01 15:51:02 -04005128#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005129#Param byteLength byte length of text array ##
5130#Param xpos array of x positions, used to position each glyph ##
5131#Param constY shared y coordinate for all of x positions ##
5132#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005133
5134#Example
5135#Height 40
Cary Clarkbad5ad72017-08-03 17:14:08 -04005136 void draw(SkCanvas* canvas) {
5137 SkScalar xpos[] = { 20, 40, 80, 160 };
5138 SkPaint paint;
5139 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
5140 }
Cary Clark8032b982017-07-28 11:04:54 -04005141##
5142
5143#ToDo incomplete ##
5144
5145##
5146
5147# ------------------------------------------------------------------------------
5148
5149#Method void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
5150 SkScalar vOffset, const SkPaint& paint)
5151
5152Draw text on Path path, using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005153
Cary Clarkbad5ad72017-08-03 17:14:08 -04005154Origin of text is at distance hOffset along the path, offset by a perpendicular
5155vector of length vOffset. If the path section corresponding the glyph advance is
5156curved, the glyph is drawn curved to match; control points in the glyph are
5157mapped to projected points parallel to the path. If the text's advance is larger
5158than the path length, the excess text is clipped.
5159
5160text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5161UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by
5162default text positions the first glyph's left side bearing at origin x and its
Cary Clark8032b982017-07-28 11:04:54 -04005163baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
5164
Cary Clarkbad5ad72017-08-03 17:14:08 -04005165All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5166Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005167filled 12 point black Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005168
Cary Clarkce101242017-09-01 15:51:02 -04005169#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005170#Param byteLength byte length of text array ##
5171#Param path Path providing text baseline ##
5172#Param hOffset distance along path to offset origin ##
5173#Param vOffset offset of text above (if negative) or below (if positive) the path ##
5174#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005175
5176#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005177 void draw(SkCanvas* canvas) {
5178 const char aero[] = "correo a" "\xC3" "\xA9" "reo";
5179 const size_t len = sizeof(aero) - 1;
5180 SkPath path;
5181 path.addOval({43-26, 43-26, 43+26, 43+26}, SkPath::kCW_Direction, 3);
5182 SkPaint paint;
5183 paint.setTextSize(24);
5184 for (auto offset : { 0, 10, 20 } ) {
5185 canvas->drawTextOnPathHV(aero, len, path, 0, -offset, paint);
5186 canvas->translate(70 + offset, 70 + offset);
5187 }
5188 }
Cary Clark8032b982017-07-28 11:04:54 -04005189##
5190
5191#ToDo incomplete ##
5192
5193##
5194
5195# ------------------------------------------------------------------------------
5196
5197#Method void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
5198 const SkMatrix* matrix, const SkPaint& paint)
5199
5200Draw text on Path path, using Clip, Matrix, and Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04005201
Cary Clarkbad5ad72017-08-03 17:14:08 -04005202Origin of text is at beginning of path offset by matrix, if provided, before it
5203is mapped to path. If the path section corresponding the glyph advance is
5204curved, the glyph is drawn curved to match; control points in the glyph are
5205mapped to projected points parallel to the path. If the text's advance is larger
5206than the path length, the excess text is clipped.
5207
5208text's meaning depends on Paint_Text_Encoding; by default, text encoding is
5209UTF-8. Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by
5210default text positions the first glyph's left side bearing at origin x and its
Cary Clark8032b982017-07-28 11:04:54 -04005211baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
5212
Cary Clarkbad5ad72017-08-03 17:14:08 -04005213All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5214Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005215filled 12 point black Glyphs.
Cary Clark8032b982017-07-28 11:04:54 -04005216
Cary Clarkce101242017-09-01 15:51:02 -04005217#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005218#Param byteLength byte length of text array ##
5219#Param path Path providing text baseline ##
Cary Clarkce101242017-09-01 15:51:02 -04005220#Param matrix transform of Glyphs before mapping to path; may be nullptr
Cary Clarka523d2d2017-08-30 08:58:10 -04005221 to use identity Matrix
Cary Clarkbad5ad72017-08-03 17:14:08 -04005222##
5223#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005224
5225#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005226 void draw(SkCanvas* canvas) {
5227 const char roller[] = "rollercoaster";
5228 const size_t len = sizeof(roller) - 1;
5229 SkPath path;
5230 path.cubicTo(40, -80, 120, 80, 160, -40);
5231 SkPaint paint;
5232 paint.setTextSize(32);
5233 paint.setStyle(SkPaint::kStroke_Style);
5234 SkMatrix matrix;
5235 matrix.setIdentity();
5236 for (int i = 0; i < 3; ++i) {
5237 canvas->translate(25, 60);
5238 canvas->drawPath(path, paint);
5239 canvas->drawTextOnPath(roller, len, path, &matrix, paint);
5240 matrix.preTranslate(0, 10);
5241 }
5242 }
Cary Clark8032b982017-07-28 11:04:54 -04005243##
5244
5245#ToDo incomplete ##
5246
5247##
5248
5249# ------------------------------------------------------------------------------
5250
5251#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
5252 const SkRect* cullRect, const SkPaint& paint)
5253
5254Draw text, transforming each glyph by the corresponding SkRSXform,
5255using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005256
Cary Clark8032b982017-07-28 11:04:54 -04005257RSXform array specifies a separate square scale, rotation, and translation for
5258each glyph.
Cary Clark8032b982017-07-28 11:04:54 -04005259
Cary Clarkbad5ad72017-08-03 17:14:08 -04005260Optional Rect cullRect is a conservative bounds of text, taking into account
Cary Clarkce101242017-09-01 15:51:02 -04005261RSXform and paint. If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005262
Cary Clarkbad5ad72017-08-03 17:14:08 -04005263All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader,
5264Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
Cary Clarkce101242017-09-01 15:51:02 -04005265filled 12 point black Glyphs.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005266
Cary Clarkce101242017-09-01 15:51:02 -04005267#Param text character code points or Glyphs drawn ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005268#Param byteLength byte length of text array ##
5269#Param xform RSXform rotates, scales, and translates each glyph individually ##
5270#Param cullRect Rect bounds of text for efficient clipping; or nullptr ##
5271#Param paint text size, blend, color, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005272
5273#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005274void draw(SkCanvas* canvas) {
5275 const int iterations = 26;
5276 SkRSXform transforms[iterations];
5277 char alphabet[iterations];
5278 SkScalar angle = 0;
5279 SkScalar scale = 1;
5280 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
5281 const SkScalar s = SkScalarSin(angle) * scale;
5282 const SkScalar c = SkScalarCos(angle) * scale;
5283 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
5284 angle += .45;
5285 scale += .2;
5286 alphabet[i] = 'A' + i;
5287 }
5288 SkPaint paint;
5289 paint.setTextAlign(SkPaint::kCenter_Align);
5290 canvas->translate(110, 138);
5291 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005292}
5293##
5294
5295#ToDo incomplete ##
5296
5297##
5298
5299# ------------------------------------------------------------------------------
5300
5301#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
5302
5303Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005304
Cary Clarkce101242017-09-01 15:51:02 -04005305blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clarkbad5ad72017-08-03 17:14:08 -04005306Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X,
5307Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold,
5308Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
5309Subpixel_Text, and Paint_Vertical_Text.
Cary Clark8032b982017-07-28 11:04:54 -04005310
5311Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
5312Image_Filter, and Draw_Looper; apply to blob.
5313
Cary Clarkce101242017-09-01 15:51:02 -04005314#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005315#Param x horizontal offset applied to blob ##
5316#Param y vertical offset applied to blob ##
5317#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005318
5319#Example
5320#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04005321 void draw(SkCanvas* canvas) {
5322 SkTextBlobBuilder textBlobBuilder;
5323 const char bunny[] = "/(^x^)\\";
5324 const int len = sizeof(bunny) - 1;
5325 uint16_t glyphs[len];
5326 SkPaint paint;
5327 paint.textToGlyphs(bunny, len, glyphs);
5328 int runs[] = { 3, 1, 3 };
5329 SkPoint textPos = { 20, 100 };
5330 int glyphIndex = 0;
5331 for (auto runLen : runs) {
5332 paint.setTextSize(1 == runLen ? 20 : 50);
5333 const SkTextBlobBuilder::RunBuffer& run =
5334 textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
5335 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
5336 textPos.fX += paint.measureText(&bunny[glyphIndex], runLen, nullptr);
5337 glyphIndex += runLen;
5338 }
5339 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5340 paint.reset();
5341 canvas->drawTextBlob(blob.get(), 0, 0, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005342 }
5343##
5344
5345#ToDo incomplete ##
5346
5347##
5348
5349# ------------------------------------------------------------------------------
5350
5351#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
5352
5353Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005354
Cary Clarkce101242017-09-01 15:51:02 -04005355blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clarkbad5ad72017-08-03 17:14:08 -04005356Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X,
5357Paint_Text_Align, Paint_Hinting, Anti-alias, Paint_Fake_Bold,
5358Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text,
5359Subpixel_Text, and Paint_Vertical_Text.
Cary Clark8032b982017-07-28 11:04:54 -04005360
5361Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
5362Image_Filter, and Draw_Looper; apply to blob.
5363
Cary Clarkce101242017-09-01 15:51:02 -04005364#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005365#Param x horizontal offset applied to blob ##
5366#Param y vertical offset applied to blob ##
5367#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005368
5369#Example
5370#Height 120
5371#Description
5372Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob.
5373Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
5374##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005375 void draw(SkCanvas* canvas) {
5376 SkTextBlobBuilder textBlobBuilder;
5377 SkPaint paint;
5378 paint.setTextSize(50);
5379 paint.setColor(SK_ColorRED);
5380 const SkTextBlobBuilder::RunBuffer& run =
5381 textBlobBuilder.allocRun(paint, 1, 20, 100);
5382 run.glyphs[0] = 20;
5383 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5384 paint.setTextSize(10);
5385 paint.setColor(SK_ColorBLUE);
5386 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5387 }
Cary Clark8032b982017-07-28 11:04:54 -04005388##
5389
5390#ToDo incomplete ##
5391
5392##
5393
5394# ------------------------------------------------------------------------------
5395
5396#Method void drawPicture(const SkPicture* picture)
5397
5398Draw Picture picture, using Clip and Matrix.
5399Clip and Matrix are unchanged by picture contents, as if
5400save() was called before and restore() was called after drawPicture.
5401
5402Picture records a series of draw commands for later playback.
5403
Cary Clarkbad5ad72017-08-03 17:14:08 -04005404#Param picture recorded drawing commands to play ##
Cary Clark8032b982017-07-28 11:04:54 -04005405
5406#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005407void draw(SkCanvas* canvas) {
5408 SkPictureRecorder recorder;
5409 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5410 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5411 SkPaint paint;
5412 paint.setColor(color);
5413 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5414 recordingCanvas->translate(10, 10);
5415 recordingCanvas->scale(1.2f, 1.4f);
5416 }
5417 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5418 const SkPicture* playbackPtr = playback.get();
5419 canvas->drawPicture(playback);
5420 canvas->scale(2, 2);
5421 canvas->translate(50, 0);
5422 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04005423}
5424##
5425
5426#ToDo incomplete ##
5427
5428##
5429
5430# ------------------------------------------------------------------------------
5431
5432#Method void drawPicture(const sk_sp<SkPicture>& picture)
5433
5434Draw Picture picture, using Clip and Matrix.
5435Clip and Matrix are unchanged by picture contents, as if
5436save() was called before and restore() was called after drawPicture.
5437
5438Picture records a series of draw commands for later playback.
5439
Cary Clarkbad5ad72017-08-03 17:14:08 -04005440#Param picture recorded drawing commands to play ##
Cary Clark8032b982017-07-28 11:04:54 -04005441
5442#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005443void draw(SkCanvas* canvas) {
5444 SkPictureRecorder recorder;
5445 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5446 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5447 SkPaint paint;
5448 paint.setColor(color);
5449 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5450 recordingCanvas->translate(10, 10);
5451 recordingCanvas->scale(1.2f, 1.4f);
5452 }
5453 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5454 canvas->drawPicture(playback);
5455 canvas->scale(2, 2);
5456 canvas->translate(50, 0);
5457 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04005458}
5459##
5460
5461#ToDo incomplete ##
5462
5463##
5464
5465# ------------------------------------------------------------------------------
5466
5467#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
5468
Cary Clarkbad5ad72017-08-03 17:14:08 -04005469Draw Picture picture, using Clip and Matrix; transforming picture with
5470Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
5471Image_Filter, and Blend_Mode, if provided.
Cary Clark8032b982017-07-28 11:04:54 -04005472
5473matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5474paint use is equivalent to: saveLayer, drawPicture, restore().
5475
Cary Clarkbad5ad72017-08-03 17:14:08 -04005476#Param picture recorded drawing commands to play ##
5477#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
5478#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005479
5480#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005481void draw(SkCanvas* canvas) {
5482 SkPaint paint;
5483 SkPictureRecorder recorder;
5484 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5485 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5486 paint.setColor(color);
5487 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5488 recordingCanvas->translate(10, 10);
5489 recordingCanvas->scale(1.2f, 1.4f);
5490 }
5491 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5492 const SkPicture* playbackPtr = playback.get();
5493 SkMatrix matrix;
5494 matrix.reset();
5495 for (auto alpha : { 70, 140, 210 } ) {
5496 paint.setAlpha(alpha);
5497 canvas->drawPicture(playbackPtr, &matrix, &paint);
5498 matrix.preTranslate(70, 70);
5499 }
Cary Clark8032b982017-07-28 11:04:54 -04005500}
5501##
5502
5503#ToDo incomplete ##
5504
5505##
5506
5507# ------------------------------------------------------------------------------
5508
5509#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
5510
Cary Clarkbad5ad72017-08-03 17:14:08 -04005511Draw Picture picture, using Clip and Matrix; transforming picture with
5512Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
5513Image_Filter, and Blend_Mode, if provided.
Cary Clark8032b982017-07-28 11:04:54 -04005514
5515matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5516paint use is equivalent to: saveLayer, drawPicture, restore().
5517
Cary Clarkbad5ad72017-08-03 17:14:08 -04005518#Param picture recorded drawing commands to play ##
5519#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
5520#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005521
5522#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005523void draw(SkCanvas* canvas) {
5524 SkPaint paint;
5525 SkPictureRecorder recorder;
5526 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5527 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5528 paint.setColor(color);
5529 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5530 recordingCanvas->translate(10, 10);
5531 recordingCanvas->scale(1.2f, 1.4f);
5532 }
5533 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5534 SkMatrix matrix;
5535 matrix.reset();
5536 for (auto alpha : { 70, 140, 210 } ) {
5537 paint.setAlpha(alpha);
5538 canvas->drawPicture(playback, &matrix, &paint);
5539 matrix.preTranslate(70, 70);
5540 }
Cary Clark8032b982017-07-28 11:04:54 -04005541}
5542##
5543
5544#ToDo incomplete ##
5545
5546##
5547
5548# ------------------------------------------------------------------------------
5549
5550#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
5551
5552Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005553If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
5554contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
Cary Clark8032b982017-07-28 11:04:54 -04005555
Cary Clarkbad5ad72017-08-03 17:14:08 -04005556#Param vertices triangle mesh to draw ##
5557#Param mode combines Vertices_Colors with Shader, if both are present ##
5558#Param paint specifies the Shader, used as Vertices texture; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005559
5560#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005561void draw(SkCanvas* canvas) {
5562 SkPaint paint;
5563 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5564 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5565 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5566 SK_ARRAY_COUNT(points), points, nullptr, colors);
5567 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
5568}
Cary Clark8032b982017-07-28 11:04:54 -04005569##
5570
5571#ToDo incomplete ##
5572
5573##
5574
5575# ------------------------------------------------------------------------------
5576
5577#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
5578
5579Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005580If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
5581contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
Cary Clark8032b982017-07-28 11:04:54 -04005582
Cary Clarkbad5ad72017-08-03 17:14:08 -04005583#Param vertices triangle mesh to draw ##
5584#Param mode combines Vertices_Colors with Shader, if both are present ##
5585#Param paint specifies the Shader, used as Vertices texture, may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005586
5587#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005588void draw(SkCanvas* canvas) {
5589 SkPaint paint;
5590 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5591 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
5592 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5593 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
5594 SkShader::kClamp_TileMode));
5595 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5596 SK_ARRAY_COUNT(points), points, texs, colors);
5597 canvas->drawVertices(vertices.get(), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005598}
5599##
5600
5601#ToDo incomplete ##
5602
5603##
5604
5605# ------------------------------------------------------------------------------
5606
5607#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5608 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
5609
Cary Clarkce101242017-09-01 15:51:02 -04005610Draws a Coons patch: the interpolation of four cubics with shared corners,
Cary Clark8032b982017-07-28 11:04:54 -04005611associating a color, and optionally a texture coordinate, with each corner.
5612
Cary Clarkbad5ad72017-08-03 17:14:08 -04005613The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter,
5614Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
5615as the Coons patch texture; Blend_Mode mode combines Color colors and Shader if
5616both are provided.
Cary Clark8032b982017-07-28 11:04:54 -04005617
Cary Clarkce101242017-09-01 15:51:02 -04005618Point array cubics specifies four Cubics starting at the top left corner,
5619in clockwise order, sharing every fourth point. The last Cubic ends at the
Cary Clarkbad5ad72017-08-03 17:14:08 -04005620first point.
Cary Clark8032b982017-07-28 11:04:54 -04005621
Cary Clarkbad5ad72017-08-03 17:14:08 -04005622Color array color associates colors with corners in top left, top right,
5623bottom right, bottom left order.
5624
5625If paint contains Shader, Point array texCoords maps Shader as texture to
5626corners in top left, top right, bottom right, bottom left order.
5627
Cary Clarka523d2d2017-08-30 08:58:10 -04005628#Param cubics Path_Cubic array, sharing common points ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005629#Param colors Color array, one for each corner ##
Cary Clarkce101242017-09-01 15:51:02 -04005630#Param texCoords Point array of texture coordinates, mapping Shader to corners;
Cary Clarkbad5ad72017-08-03 17:14:08 -04005631 may be nullptr
Cary Clark579985c2017-07-31 11:48:27 -04005632#Param ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005633#Param mode Blend_Mode for colors, and for Shader if paint has one ##
5634#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005635
5636#Example
5637#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04005638void draw(SkCanvas* canvas) {
5639 // SkBitmap source = cmbkygk;
5640 SkPaint paint;
5641 paint.setFilterQuality(kLow_SkFilterQuality);
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[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
5648 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
5649 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5650 SkShader::kClamp_TileMode, nullptr));
5651 canvas->scale(15, 15);
5652 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
5653 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
5654 canvas->translate(4, 4);
5655 }
Cary Clark8032b982017-07-28 11:04:54 -04005656}
5657##
5658
Cary Clarkbad5ad72017-08-03 17:14:08 -04005659#ToDo incomplete; can patch use image filter? ##
Cary Clark8032b982017-07-28 11:04:54 -04005660
5661##
5662
5663# ------------------------------------------------------------------------------
5664
5665#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5666 const SkPoint texCoords[4], const SkPaint& paint)
5667
Cary Clarkce101242017-09-01 15:51:02 -04005668Draws Cubic Coons patch: the interpolation of four cubics with shared corners,
Cary Clarkbad5ad72017-08-03 17:14:08 -04005669associating a color, and optionally a texture coordinate, with each corner.
Cary Clark8032b982017-07-28 11:04:54 -04005670
Cary Clarkbad5ad72017-08-03 17:14:08 -04005671The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter,
5672Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
5673as the Coons patch texture; Blend_Mode mode combines Color colors and Shader if
5674both are provided.
Cary Clark8032b982017-07-28 11:04:54 -04005675
Cary Clarkce101242017-09-01 15:51:02 -04005676Point array cubics specifies four Cubics starting at the top left corner,
5677in clockwise order, sharing every fourth point. The last Cubic ends at the
Cary Clarkbad5ad72017-08-03 17:14:08 -04005678first point.
5679
5680Color array color associates colors with corners in top left, top right,
5681bottom right, bottom left order.
5682
5683If paint contains Shader, Point array texCoords maps Shader as texture to
5684corners in top left, top right, bottom right, bottom left order.
5685
Cary Clarka523d2d2017-08-30 08:58:10 -04005686#Param cubics Path_Cubic array, sharing common points ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005687#Param colors Color array, one for each corner ##
Cary Clarkce101242017-09-01 15:51:02 -04005688#Param texCoords Point array of texture coordinates, mapping Shader to corners;
Cary Clarkbad5ad72017-08-03 17:14:08 -04005689 may be nullptr
Cary Clark579985c2017-07-31 11:48:27 -04005690#Param ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04005691#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04005692
5693#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04005694void draw(SkCanvas* canvas) {
5695 SkPaint paint;
5696 paint.setAntiAlias(true);
5697 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5698 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5699 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5700 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5701 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5702 canvas->scale(30, 30);
5703 canvas->drawPatch(cubics, colors, nullptr, paint);
5704 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
5705 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
5706 {0.5f,3.2f} };
5707 paint.setTextSize(18.f / 30);
5708 paint.setTextAlign(SkPaint::kCenter_Align);
5709 for (int i = 0; i< 10; ++i) {
5710 char digit = '0' + i;
5711 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
5712 }
5713 canvas->drawString("10", text[10].fX, text[10].fY, paint);
5714 canvas->drawString("11", text[11].fX, text[11].fY, paint);
5715 paint.setStyle(SkPaint::kStroke_Style);
5716 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
5717 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005718}
5719##
5720
5721#Example
5722#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04005723void draw(SkCanvas* canvas) {
5724 // SkBitmap source = checkerboard;
5725 SkPaint paint;
5726 paint.setFilterQuality(kLow_SkFilterQuality);
5727 paint.setAntiAlias(true);
5728 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5729 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5730 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5731 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5732 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
5733 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5734 SkShader::kClamp_TileMode, nullptr));
5735 canvas->scale(30, 30);
5736 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04005737}
5738##
5739
Cary Clarkbad5ad72017-08-03 17:14:08 -04005740#ToDo incomplete; can patch use image filter? ##
Cary Clark8032b982017-07-28 11:04:54 -04005741
5742##
5743
5744# ------------------------------------------------------------------------------
5745
5746#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
5747 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5748 const SkPaint* paint)
5749
5750Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005751paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5752to draw, if present. For each entry in the array, Rect tex locates sprite in
5753atlas, and RSXform xform transforms it into destination space.
5754
Cary Clark8032b982017-07-28 11:04:54 -04005755xform, text, and colors if present, must contain count entries.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005756Optional colors are applied for each sprite using Blend_Mode.
Cary Clark8032b982017-07-28 11:04:54 -04005757Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005758If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005759
Cary Clarkbad5ad72017-08-03 17:14:08 -04005760#Param atlas Image containing sprites ##
5761#Param xform RSXform mappings for sprites in atlas ##
5762#Param tex Rect locations of sprites in atlas ##
5763#Param colors Color, one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
5764#Param count number of sprites to draw ##
5765#Param mode Blend_Mode combining colors and sprites ##
5766#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5767#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005768
5769#Example
5770#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005771void draw(SkCanvas* canvas) {
5772 // SkBitmap source = mandrill;
5773 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5774 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5775 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5776 const SkImage* imagePtr = image.get();
5777 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005778}
5779##
5780
5781#ToDo incomplete ##
5782
5783##
5784
5785# ------------------------------------------------------------------------------
5786
5787#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5788 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5789 const SkPaint* paint)
5790
5791Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005792paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5793to draw, if present. For each entry in the array, Rect tex locates sprite in
5794atlas, and RSXform xform transforms it into destination space.
5795
Cary Clark8032b982017-07-28 11:04:54 -04005796xform, text, and colors if present, must contain count entries.
5797Optional colors is applied for each sprite using Blend_Mode.
5798Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005799If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005800
Cary Clarkbad5ad72017-08-03 17:14:08 -04005801#Param atlas Image containing sprites ##
5802#Param xform RSXform mappings for sprites in atlas ##
5803#Param tex Rect locations of sprites in atlas ##
5804#Param colors Color, one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
5805#Param count number of sprites to draw ##
5806#Param mode Blend_Mode combining colors and sprites ##
5807#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5808#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005809
5810#Example
5811#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005812void draw(SkCanvas* canvas) {
5813 // SkBitmap source = mandrill;
5814 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5815 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5816 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5817 SkPaint paint;
5818 paint.setAlpha(127);
5819 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04005820}
5821##
5822
5823#ToDo bug in example on cpu side, gpu looks ok ##
5824
5825##
5826
5827# ------------------------------------------------------------------------------
5828
5829#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
5830 const SkRect* cullRect, const SkPaint* paint)
5831
5832Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005833paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5834to draw, if present. For each entry in the array, Rect tex locates sprite in
5835atlas, and RSXform xform transforms it into destination space.
5836
Cary Clark8032b982017-07-28 11:04:54 -04005837xform and text must contain count entries.
5838Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005839If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005840
Cary Clarkbad5ad72017-08-03 17:14:08 -04005841#Param atlas Image containing sprites ##
5842#Param xform RSXform mappings for sprites in atlas ##
5843#Param tex Rect locations of sprites in atlas ##
5844#Param count number of sprites to draw ##
5845#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5846#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005847
5848#Example
5849#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005850void draw(SkCanvas* canvas) {
5851 // sk_sp<SkImage> image = mandrill;
5852 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5853 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5854 const SkImage* imagePtr = image.get();
5855 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005856}
5857##
5858
5859#ToDo incomplete ##
5860
5861##
5862
5863# ------------------------------------------------------------------------------
5864
5865#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5866 int count, const SkRect* cullRect, const SkPaint* paint)
5867
5868Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04005869paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
5870to draw, if present. For each entry in the array, Rect tex locates sprite in
5871atlas, and RSXform xform transforms it into destination space.
5872
Cary Clark8032b982017-07-28 11:04:54 -04005873xform and text must contain count entries.
5874Optional cullRect is a conservative bounds of all transformed sprites.
Cary Clarkce101242017-09-01 15:51:02 -04005875If cullRect is outside of Clip, canvas can skip drawing.
Cary Clark8032b982017-07-28 11:04:54 -04005876
Cary Clarkbad5ad72017-08-03 17:14:08 -04005877#Param atlas Image containing sprites ##
5878#Param xform RSXform mappings for sprites in atlas ##
5879#Param tex Rect locations of sprites in atlas ##
5880#Param count number of sprites to draw ##
5881#Param cullRect Rect bounds of transformed sprites for efficient clipping; may be nullptr ##
5882#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005883
5884#Example
5885#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04005886void draw(SkCanvas* canvas) {
5887 // sk_sp<SkImage> image = mandrill;
5888 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
5889 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
5890 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04005891}
5892##
5893
5894#ToDo incomplete ##
5895
5896##
5897
5898# ------------------------------------------------------------------------------
5899
Cary Clark73fa9722017-08-29 17:36:51 -04005900#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -04005901
5902Draw Drawable drawable using Clip and Matrix, concatenated with
5903optional matrix.
5904
5905If Canvas has an asynchronous implementation, as is the case
5906when it is recording into Picture, then drawable will be referenced,
5907so that SkDrawable::draw() can be called when the operation is finalized. To force
5908immediate drawing, call SkDrawable::draw() instead.
5909
Cary Clarkbad5ad72017-08-03 17:14:08 -04005910#Param drawable custom struct encapsulating drawing commands ##
5911#Param matrix transformation applied to drawing; may be nullptr ##
Cary Clark8032b982017-07-28 11:04:54 -04005912
5913#Example
5914#Height 100
5915#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04005916struct MyDrawable : public SkDrawable {
5917 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5918
5919 void onDraw(SkCanvas* canvas) override {
5920 SkPath path;
5921 path.conicTo(10, 90, 50, 90, 0.9f);
5922 SkPaint paint;
5923 paint.setColor(SK_ColorBLUE);
5924 canvas->drawRect(path.getBounds(), paint);
5925 paint.setAntiAlias(true);
5926 paint.setColor(SK_ColorWHITE);
5927 canvas->drawPath(path, paint);
5928 }
5929};
5930
5931#Function ##
5932void draw(SkCanvas* canvas) {
5933 sk_sp<SkDrawable> drawable(new MyDrawable);
5934 SkMatrix matrix;
5935 matrix.setTranslate(10, 10);
5936 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04005937}
5938##
5939
5940#ToDo incomplete ##
5941
5942##
5943
5944# ------------------------------------------------------------------------------
5945
5946#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
5947
5948Draw Drawable drawable using Clip and Matrix, offset by (x, y).
5949
5950If Canvas has an asynchronous implementation, as is the case
5951when it is recording into Picture, then drawable will be referenced,
5952so that SkDrawable::draw() can be called when the operation is finalized. To force
5953immediate drawing, call SkDrawable::draw() instead.
5954
Cary Clarkbad5ad72017-08-03 17:14:08 -04005955#Param drawable custom struct encapsulating drawing commands ##
5956#Param x offset into Canvas writable pixels in x ##
5957#Param y offset into Canvas writable pixels in y ##
Cary Clark8032b982017-07-28 11:04:54 -04005958
5959#Example
5960#Height 100
5961#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04005962struct MyDrawable : public SkDrawable {
5963 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5964
5965 void onDraw(SkCanvas* canvas) override {
5966 SkPath path;
5967 path.conicTo(10, 90, 50, 90, 0.9f);
5968 SkPaint paint;
5969 paint.setColor(SK_ColorBLUE);
5970 canvas->drawRect(path.getBounds(), paint);
5971 paint.setAntiAlias(true);
5972 paint.setColor(SK_ColorWHITE);
5973 canvas->drawPath(path, paint);
5974 }
5975};
5976
5977#Function ##
5978void draw(SkCanvas* canvas) {
5979 sk_sp<SkDrawable> drawable(new MyDrawable);
5980 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04005981}
5982##
5983
5984#ToDo incomplete ##
5985
5986##
5987
5988# ------------------------------------------------------------------------------
5989
5990#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
5991
5992Associate Rect on Canvas when an annotation; a key-value pair, where the key is
5993a null-terminated utf8 string, and optional value is stored as Data.
5994
5995Only some canvas implementations, such as recording to Picture, or drawing to
5996Document_PDF, use annotations.
5997
Cary Clarkbad5ad72017-08-03 17:14:08 -04005998#Param rect Rect extent of canvas to annotate ##
5999#Param key string used for lookup ##
6000#Param value data holding value stored in annotation ##
Cary Clark8032b982017-07-28 11:04:54 -04006001
6002#Example
6003 #Height 1
6004 const char text[] = "Click this link!";
6005 SkRect bounds;
6006 SkPaint paint;
6007 paint.setTextSize(40);
6008 (void)paint.measureText(text, strlen(text), &bounds);
6009 const char url[] = "https://www.google.com/";
6010 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
6011 canvas->drawAnnotation(bounds, "url_key", urlData.get());
6012##
6013
6014#ToDo incomplete ##
6015
6016##
6017
6018# ------------------------------------------------------------------------------
6019
6020#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
6021
6022Associate Rect on Canvas when an annotation; a key-value pair, where the key is
6023a null-terminated utf8 string, and optional value is stored as Data.
6024
6025Only some canvas implementations, such as recording to Picture, or drawing to
6026Document_PDF, use annotations.
6027
Cary Clarkbad5ad72017-08-03 17:14:08 -04006028#Param rect Rect extent of canvas to annotate ##
6029#Param key string used for lookup ##
6030#Param value data holding value stored in annotation ##
Cary Clark8032b982017-07-28 11:04:54 -04006031
6032#Example
6033#Height 1
6034 const char text[] = "Click this link!";
6035 SkRect bounds;
6036 SkPaint paint;
6037 paint.setTextSize(40);
6038 (void)paint.measureText(text, strlen(text), &bounds);
6039 const char url[] = "https://www.google.com/";
6040 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
6041 canvas->drawAnnotation(bounds, "url_key", urlData.get());
6042##
6043
6044#ToDo incomplete ##
6045
6046##
6047
6048#Method SkDrawFilter* getDrawFilter() const
6049
6050Legacy call to be deprecated.
6051
6052#Deprecated
6053##
6054
6055##
6056
6057#Method virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter)
6058
6059Legacy call to be deprecated.
6060
6061#Deprecated
6062##
6063
6064##
6065
6066# ------------------------------------------------------------------------------
6067
6068#Method virtual bool isClipEmpty() const
6069
6070Returns true if Clip is empty; that is, nothing will draw.
6071
Cary Clarkbad5ad72017-08-03 17:14:08 -04006072May do work when called; it should not be called
Cary Clark8032b982017-07-28 11:04:54 -04006073more often than needed. However, once called, subsequent calls perform no
6074work until Clip changes.
6075
Cary Clarkbad5ad72017-08-03 17:14:08 -04006076#Return true if Clip is empty ##
Cary Clark8032b982017-07-28 11:04:54 -04006077
6078#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04006079 void draw(SkCanvas* canvas) {
6080 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
6081 SkPath path;
6082 canvas->clipPath(path);
6083 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04006084 }
6085 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04006086 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04006087 clip is empty
6088 ##
6089##
6090
6091#ToDo incomplete ##
6092
6093##
6094
6095# ------------------------------------------------------------------------------
6096
6097#Method virtual bool isClipRect() const
6098
6099Returns true if Clip is Rect and not empty.
6100Returns false if the clip is empty, or if it is not Rect.
6101
Cary Clarkbad5ad72017-08-03 17:14:08 -04006102#Return true if Clip is Rect and not empty ##
Cary Clark8032b982017-07-28 11:04:54 -04006103
6104#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04006105 void draw(SkCanvas* canvas) {
6106 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
6107 canvas->clipRect({0, 0, 0, 0});
6108 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04006109 }
6110 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04006111 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04006112 clip is not rect
6113 ##
6114##
6115
6116#ToDo incomplete ##
6117
6118##
6119
6120#Class SkCanvas ##
6121#Topic Canvas ##