blob: 338f2c3f9d5aa59fd8370806fcfccd19e125f3e4 [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.
8Each Canvas draw call transforms the geometry of the object by the concatenation of all Matrix
9values in the stack.
10The transformed geometry is clipped by the intersection of all of Clip values in the stack.
11The Canvas draw calls take Paint parameter for drawing state.
12Create Paint to supply the drawing state, such as Color,
13Typeface, Paint_Text_Size, Paint_Stroke_Width, Shader and so on.
14
15To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
16Request Canvas from Surface to obtain the interface to draw.
17Canvas generated by Raster_Surface draws to memory visible to the CPU.
18Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
19
20Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
21This approach may be deprecated in the future.
22
23To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
24Document-based Canvas and other Canvas subclasses reference Device describing the destination.
25
26#Class SkCanvas
27
28#Topic Overview
29
30#Subtopic Subtopics
31#Table
32#Legend
33# topics # description ##
34#Legend ##
35#ToDo generate a TOC here ##
36#Table ##
37#Subtopic ##
38
39#Subtopic Constants
40#Table
41#Legend
42# constants # description ##
43#Legend ##
44# Lattice::Flags # Controls Lattice transparency. ##
45# PointMode # Sets drawPoints options. ##
46# SaveLayerFlags # Sets SaveLayerRec options. ##
47# SrcRectConstraint # Sets drawImageRect options. ##
48#Table ##
49#Subtopic ##
50
51#Subtopic Structs
52#Table
53#Legend
54# struct # description ##
55#Legend ##
56# Lattice # Divides Bitmap, Image into a rectangular grid. ##
57# SaveLayerRec # Contains state to create the layer offscreen. ##
58#Table ##
59#Subtopic ##
60
61#Subtopic Constructors
62
63Create the desired type of Surface to obtain its Canvas when possible. Constructors are useful
64when no Surface is required, and some helpers implicitly create Raster_Surface.
65
66#Table
67#Legend
68# # description ##
69#Legend ##
70# SkCanvas() # No Surface, no dimensions. ##
71# SkCanvas(int width, int height, const SkSurfaceProps* = NULL) # No Surface, set dimensions, Surface_Properties. ##
72# SkCanvas(SkBaseDevice* device) # Existing Device. (SkBaseDevice is private.) ##
73# SkCanvas(const SkBitmap& bitmap) # Uses existing Bitmap. ##
74# SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) # Uses existing Bitmap and Surface_Properties. ##
75# MakeRasterDirect # Creates from SkImageInfo and Pixel_Storage. ##
76# MakeRasterDirectN32 # Creates from image data and Pixel_Storage. ##
77#ToDo incomplete ##
78#Table ##
79#Subtopic ##
80
81#Subtopic Member_Functions
82#Table
83#Legend
84# function # description ##
85#Legend ##
86# accessTopLayerPixels # Returns writable pixel access if available. ##
87# accessTopRasterHandle # Returns context that tracks Clip and Matrix. ##
88# clear() # Fills Clip with Color. ##
89# clipPath # Combines Clip with Path. ##
90# clipRRect # Combines Clip with Round_Rect. ##
91# clipRect # Combines Clip with Rect. ##
92# clipRegion # Combines Clip with Region. ##
93# concat() # Multiplies Matrix by Matrix. ##
94# discard() # Makes Canvas contents undefined. ##
95# drawAnnotation # Associates a Rect with a key-value pair.##
96# drawArc # Draws Arc using Clip, Matrix, and Paint.##
97# drawAtlas # Draws sprites using Clip, Matrix, and Paint.##
98# drawBitmap # Draws Bitmap at (x, y) position. ##
99# drawBitmapLattice # Draws differentially stretched Bitmap. ##
100# drawBitmapNine # Draws Nine_Patch Bitmap. ##
101# drawBitmapRect # Draws Bitmap, source Rect to destination Rect. ##
102# drawCircle # Draws Circle using Clip, Matrix, and Paint. ##
103# drawColor # Fills Clip with Color and Blend_Mode. ##
104# drawDRRect # Draws double Round_Rect stroked or filled. ##
105# drawDrawable # Draws Drawable, encapsulated drawing commands. ##
106# drawIRect # Draws IRect using Clip, Matrix, and Paint. ##
107# drawImage # Draws Image at (x, y) position. ##
108# drawImageLattice # Draws differentially stretched Image. ##
109# drawImageNine # Draws Nine_Patch Image. ##
110# drawImageRect # Draws Image, source Rect to destination Rect. ##
111# drawLine # Draws line segment between two points.##
112# drawOval # Draws Oval using Clip, Matrix, and Paint. ##
113# drawPaint # Fills Clip with Paint. ##
114# drawPatch # Draws cubic Coons patch. ##
115# drawPath # Draws Path using Clip, Matrix, and Paint. ##
116# drawPicture # Draws Picture using Clip and Matrix. ##
117# drawPoint # Draws point at (x, y) position. ##
118# drawPoints # Draws array as points, lines, polygon. ##
119# drawPosText # Draws text at array of (x, y) positions. ##
120# drawPosTextH # Draws text at x positions with common baseline. ##
121# drawRRect # Draws Round_Rect using Clip, Matrix, and Paint. ##
122# drawRect # Draws Rect using Clip, Matrix, and Paint. ##
123# drawRegion # Draws Region using Clip, Matrix, and Paint. ##
124# drawRoundRect # Draws Round_Rect using Clip, Matrix, and Paint. ##
125# drawText # Draws text at (x, y), using font advance. ##
126# drawTextBlob # Draws text with arrays of positions and Paint. ##
127# drawTextOnPath # Draws text following Path contour. ##
128# drawTextOnPathHV # Draws text following Path with offsets. ##
129# drawTextRSXform # Draws text with array of RSXform. ##
130# drawString # Draws null terminated string at (x, y) using font advance. ##
131# drawVertices # Draws Vertices, a triangle mesh. ##
132# flush() # Triggers execution of all pending draw operations. ##
133# getBaseLayerSize # Gets size of base layer in global coordinates. ##
134# getDeviceClipBounds # Returns IRect bounds of Clip. ##
135# getDrawFilter # Legacy; to be deprecated. ##
136# getGrContext # Returns GPU_Context of the GPU_Surface. ##
137# getLocalClipBounds # Returns Clip bounds in source coordinates. ##
138# getMetaData # Associates additional data with the canvas. ##
139# getProps # Copies Surface_Properties if available. ##
140# getSaveCount # Returns depth of stack containing Clip and Matrix. ##
141# getTotalMatrix # Returns Matrix. ##
142# imageInfo # Returns Image_Info for Canvas. ##
143# isClipEmpty # Returns if Clip is empty. ##
144# isClipRect # Returns if Clip is Rect and not empty. ##
145# MakeRasterDirect # Creates Canvas from SkImageInfo and pixel data. ##
146# MakeRasterDirectN32 # Creates Canvas from image specifications and pixel data. ##
147# makeSurface # Creates Surface matching SkImageInfo and SkSurfaceProps. ##
148# peekPixels # Returns if Canvas has direct access to its pixels. ##
149# quickReject # Returns if Rect is outside Clip. ##
150# readPixels # Copies and converts rectangle of pixels from Canvas. ##
151# resetMatrix # Resets Matrix to identity. ##
152# restore() # Restores changes to Clip and Matrix, pops save stack. ##
153# restoreToCount # Restores changes to Clip and Matrix to given depth. ##
154# rotate() # Rotates Matrix. ##
155# save() # Saves Clip and Matrix on stack. ##
156# saveLayer # Saves Clip and Matrix on stack; creates offscreen. ##
157# saveLayerAlpha # Saves Clip and Matrix on stack; creates offscreen; sets opacity. ##
158# saveLayerPreserveLCDTextRequests # Saves Clip and Matrix on stack; creates offscreen for LCD text. ##
159# scale() # Scales Matrix. ##
160# setAllowSimplifyClip # Experimental. ##
161# setDrawFilter # Legacy; to be deprecated. ##
162# setMatrix # Sets Matrix. ##
163# skew() # Skews Matrix. #
164# translate() # Translates Matrix. ##
165# writePixels # Copies and converts rectangle of pixels to Canvas. ##
166#Table ##
167#Subtopic ##
168
169#Topic Overview ##
170
171# ------------------------------------------------------------------------------
172
173#Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info,
174 void* pixels, size_t rowBytes)
175
176Allocates raster canvas that will draw directly into pixels.
177To access pixels after drawing, call flush() or peekPixels.
178
179#Param info Width, height, Image_Color_Type, Image_Alpha_Type, Color_Space, of Raster_Surface.
180 Width, or height, or both, may be zero.
181##
182#Param pixels Pointer to destination pixels buffer. Buffer size should be info height
183 times rowBytes times bytes required for Image_Color_Type.
184##
185#Param rowBytes The interval from one Surface row to the next; equal to or greater than
186 info width times bytes required for Image_Color_Type.
187##
188
189#Return Canvas if all parameters are valid; otherwise, nullptr.
190 Valid parameters include: info dimensions must be zero or positive, and other checks;
191 info must contain Image_Color_Type and Image_Alpha_Type supported by Raster_Surface;
192 pixels must be not be nullptr;
193 rowBytes must be zero or large enough to contain width pixels of Image_Color_Type.
194##
195
196#Example
197 #Description
198 Allocates a three by three bitmap, clears it to white, and draws a black pixel
199 in the center.
200 ##
201void draw(SkCanvas* ) {
202 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, premultipled
203 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row
204 const size_t size = info.getSafeSize(minRowBytes); // bytes used by all rows
205 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels
206 SkPMColor* pixels = storage.get(); // get pointer to allocated storage
207 // create a SkCanvas backed by a raster device, and delete it when the
208 // function goes out of scope.
209 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
210 canvas->clear(SK_ColorWHITE); // white is unpremultiplied, in ARGB order
211 canvas->flush(); // ensure that pixels are cleared
212 SkPMColor pmWhite = pixels[0]; // the premultiplied format may vary
213 SkPaint paint; // by default, draws black
214 canvas->drawPoint(1, 1, paint); // draw in the center
215 canvas->flush(); // ensure that point was drawn
216 for (int y = 0; y < info.height(); ++y) {
217 for (int x = 0; x < info.width(); ++x) {
218 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
219 }
220 SkDebugf("\n");
221 }
222}
223 #StdOut
224 ---
225 -x-
226 ---
227 ##
228##
229
230#ToDo incomplete ##
231
232#SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
233##
234
235# ------------------------------------------------------------------------------
236
237#Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
238 size_t rowBytes)
239
240Creates Canvas with Raster_Surface with inline image specification that draws into pixels.
241Image_Color_Type is set to kN32_SkColorType.
242Image_Alpha_Type is set to kPremul_SkAlphaType.
243To access pixels after drawing, call flush() or peekPixels.
244
245#Param width Pixel column count on Raster_Surface created. Must be zero or greater. ##
246#Param height Pixel row count on Raster_Surface created. Must be zero or greater. ##
247#Param pixels Pointer to destination pixels buffer. Buffer size should be height
248 times rowBytes times four.
249##
250#Param rowBytes The interval from one Surface row to the next; equal to or greater than
251 width times four.
252##
253
254#Return Canvas if all parameters are valid; otherwise, nullptr.
255 Valid parameters include: width and height must be zero or positive;
256 pixels must be not be nullptr;
257 rowBytes must be zero or large enough to contain width pixels of Image_Color_Type.
258##
259
260#Example
261 #Description
262 Allocates a three by three bitmap, clears it to white, and draws a black pixel
263 in the center.
264 ##
265void draw(SkCanvas* ) {
266 const int width = 3;
267 const int height = 3;
268 SkPMColor pixels[height][width]; // allocate a 3x3 premultiplied bitmap on the stack
269 // create a SkCanvas backed by a raster device, and delete it when the
270 // function goes out of scope.
271 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
272 width,
273 height,
274 pixels[0], // top left of the bitmap
275 sizeof(pixels[0])); // byte width of the each row
276 // write a pre-multiplied value for white into all pixels in the bitmap
277 canvas->clear(SK_ColorWHITE);
278 SkPMColor pmWhite = pixels[0][0]; // the premultiplied format may vary
279 SkPaint paint; // by default, draws black
280 canvas->drawPoint(1, 1, paint); // draw in the center
281 canvas->flush(); // ensure that pixels is ready to be read
282 for (int y = 0; y < height; ++y) {
283 for (int x = 0; x < width; ++x) {
284 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
285 }
286 SkDebugf("\n");
287 }
288}
289 #StdOut
290 ---
291 -x-
292 ---
293 ##
294##
295
296#ToDo incomplete ##
297
298##
299
300# ------------------------------------------------------------------------------
301
302#Method SkCanvas()
303
304Creates an empty canvas with no backing device/pixels, and zero
305dimensions.
306
307#Return An empty canvas. ##
308
309#Example
310
311#Description
312Passes a placeholder to a function that requires one.
313##
314
315#Function
316// Returns true if either the canvas rotates the text by 90 degrees, or the paint does.
317static void check_for_up_and_down_text(const SkCanvas* canvas, const SkPaint& paint) {
318 bool paintHasVertical = paint.isVerticalText();
319 const SkMatrix& matrix = canvas->getTotalMatrix();
320 bool matrixIsVertical = matrix.preservesRightAngles() && !matrix.isScaleTranslate();
321 SkDebugf("paint draws text %s\n", paintHasVertical != matrixIsVertical ?
322 "top to bottom" : "left to right");
323}
324
325static void check_for_up_and_down_text(const SkPaint& paint) {
326 SkCanvas canvas; // placeholder only, does not have an associated device
327 check_for_up_and_down_text(&canvas, paint);
328}
329
330##
331void draw(SkCanvas* canvas) {
332 SkPaint paint;
333 check_for_up_and_down_text(paint); // paint draws text left to right
334 paint.setVerticalText(true);
335 check_for_up_and_down_text(paint); // paint draws text top to bottom
336 paint.setVerticalText(false);
337 canvas->rotate(90);
338 check_for_up_and_down_text(canvas, paint); // paint draws text top to bottom
339}
340
341 #StdOut
342 paint draws text left to right
343 paint draws text top to bottom
344 paint draws text top to bottom
345 ##
346##
347
348#ToDo incomplete ##
349
350##
351
352# ------------------------------------------------------------------------------
353
354#Method SkCanvas(int width, int height, const SkSurfaceProps* props = NULL)
355
356Creates Canvas of the specified dimensions without a Surface.
357Used by subclasses with custom implementations for draw methods.
358
359#Param width Zero or greater. ##
360#Param height Zero or greater. ##
361#Param props The LCD striping orientation and setting for device independent fonts.
Cary Clark579985c2017-07-31 11:48:27 -0400362 If nullptr, use Legacy_Font_Host settings.
363#Param ##
Cary Clark8032b982017-07-28 11:04:54 -0400364
365#Return Canvas placeholder with dimensions. ##
366
367#Example
368 SkCanvas canvas(10, 20); // 10 units wide, 20 units high
369 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device
370 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
371
372 #StdOut
373 canvas is empty
374 ##
375##
376
377#ToDo incomplete ##
378
379##
380
381# ------------------------------------------------------------------------------
382
383#Method explicit SkCanvas(SkBaseDevice* device)
384
385Construct a canvas that draws into device.
386Used by child classes of SkCanvas.
387
388#ToDo Since SkBaseDevice is private, shouldn't this be private also? ##
389
390#Param device Specifies a device for the canvas to draw into. ##
391
392#Return Canvas that can be used to draw into device. ##
393
394#Example
395#Error "Unsure how to create a meaningful example."
396 SkPDFCanvas::SkPDFCanvas(const sk_sp<SkPDFDevice>& dev)
397 : SkCanvas(dev.get()) {}
398##
399
400#ToDo either remove doc of figure out a way to fiddle it ##
401
402##
403
404# ------------------------------------------------------------------------------
405
406#Method explicit SkCanvas(const SkBitmap& bitmap)
407
408Construct a canvas that draws into bitmap.
409Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed Surface.
410
411#ToDo Should be deprecated? ##
412
413#Param bitmap Width, height, Image_Color_Type, Image_Alpha_Type, and pixel storage of Raster_Surface.
414 Bitmap is copied so that subsequently editing bitmap will not affect
415 constructed Canvas.
416##
417
418#Return Canvas that can be used to draw into bitmap. ##
419
420#Example
421#Description
422The actual output depends on the installed fonts.
423##
424 SkBitmap bitmap;
425 // create a bitmap 5 wide and 11 high
426 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
427 SkCanvas canvas(bitmap);
428 canvas.clear(SK_ColorWHITE); // white is unpremultiplied, in ARGB order
429 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
430 if (!canvas.peekPixels(&pixmap)) {
431 SkDebugf("peekPixels should never fail.\n");
432 }
433 const SkPMColor* pixels = pixmap.addr32(); // points to top left of bitmap
434 SkPMColor pmWhite = pixels[0]; // the premultiplied format may vary
435 SkPaint paint; // by default, draws black, 12 point text
436 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
437 for (int y = 0; y < bitmap.height(); ++y) {
438 for (int x = 0; x < bitmap.width(); ++x) {
439 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
440 }
441 SkDebugf("\n");
442 }
443
444 #StdOut
445 -----
446 --x--
447 --x--
448 --x--
449 --x--
450 --x--
451 --x--
452 -----
453 --x--
454 --x--
455 -----
456 #StdOut ##
457##
458
459#ToDo incomplete ##
460
461##
462
463#Enum ColorBehavior
464
465#ToDo exclude this during build phase
466 (use SK_BUILD_FOR_ANDROID_FRAMEWORK as exclude directive)
467##
468
469#Private
470Android framework only.
471##
472
473#Code
474 enum class ColorBehavior {
475 kLegacy,
476 };
477##
478#Const kLegacy 0
479##
480##
481
482
483# ------------------------------------------------------------------------------
484
485#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
486
487Construct a canvas that draws into bitmap.
488Use props to match the device characteristics, like LCD striping.
489
490#Param bitmap Width, height, Image_Color_Type, Image_Alpha_Type, and pixel storage of Raster_Surface.
491 Bitmap is copied so that subsequently editing bitmap will not affect
492 constructed Canvas.
493##
494#Param props The order and orientation of RGB striping; and whether to use
495 device independent fonts.
496##
497
498#Return Canvas that can be used to draw into bitmap. ##
499
500#Example
501#Description
502The actual output depends on the installed fonts.
503##
504 SkBitmap bitmap;
505 // create a bitmap 5 wide and 11 high
506 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
507 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
508 canvas.clear(SK_ColorWHITE); // white is unpremultiplied, in ARGB order
509 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
510 if (!canvas.peekPixels(&pixmap)) {
511 SkDebugf("peekPixels should never fail.\n");
512 }
513 const SkPMColor* pixels = pixmap.addr32(); // points to top left of bitmap
514 SkPMColor pmWhite = pixels[0]; // the premultiplied format may vary
515 SkPaint paint; // by default, draws black, 12 point text
516 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
517 for (int y = 0; y < bitmap.height(); ++y) {
518 for (int x = 0; x < bitmap.width(); ++x) {
519 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
520 }
521 SkDebugf("\n");
522 }
523
524 #StdOut
525 -----
526 ---x-
527 ---x-
528 ---x-
529 ---x-
530 ---x-
531 ---x-
532 -----
533 ---x-
534 ---x-
535 -----
536 #StdOut ##
537##
538
539#ToDo incomplete ##
540
541##
542
543# ------------------------------------------------------------------------------
544
545#Method virtual ~SkCanvas()
546
547Draws State_Stack_Layer, if any.
548Free up resources used by Canvas.
549
550#Example
551#Error "Haven't thought of a useful example to put here."
552##
553
554#ToDo create example to show how draw happens when canvas goes out of scope ##
555
556##
557
558# ------------------------------------------------------------------------------
559
560#Method SkMetaData& getMetaData()
561
562Associates additional data with the canvas.
563The storage is freed when Canvas is deleted.
564
565#Return storage that can be read from and written to. ##
566
567#Example
568 const char* kHelloMetaData = "HelloMetaData";
569 SkCanvas canvas;
570 SkMetaData& metaData = canvas.getMetaData();
571 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
572 metaData.setString(kHelloMetaData, "Hello!");
573 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
574 metaData.removeString(kHelloMetaData);
575 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
576
577 #StdOut
578 before: (null)
579 during: Hello!
580 after: (null)
581 #StdOut ##
582##
583
584#ToDo incomplete ##
585
586##
587
588# ------------------------------------------------------------------------------
589
590#Method SkImageInfo imageInfo() const
591
592Returns Image_Info for Canvas. If Canvas is not associated with Raster_Surface or
593GPU_Surface, returns SkImageInfo::SkImageInfo() is returned Image_Color_Type is set to kUnknown_SkColorType.
594
595#Return dimensions and Image_Color_Type of Canvas. ##
596
597#Example
598 SkCanvas canvas;
599 SkImageInfo canvasInfo = canvas.imageInfo();
600 SkImageInfo emptyInfo;
601 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
602##
603
604#ToDo incomplete ##
605
606##
607
608# ------------------------------------------------------------------------------
609
610#Method bool getProps(SkSurfaceProps* props) const
611
612If Canvas is associated with Raster_Surface or
613GPU_Surface, copies Surface_Properties and returns true. Otherwise,
614return false and leave props unchanged.
615
616#Param props Pointer to writable SkSurfaceProps. ##
617
618#Return true if Surface_Properties was copied. ##
619
620#ToDo This seems old style. Deprecate? ##
621
622#Example
623 SkBitmap bitmap;
624 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
625 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
626 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
627 if (!canvas.getProps(&surfaceProps)) {
628 SkDebugf("getProps failed unexpectedly.\n");
629 }
630 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
631
632 #StdOut
633 isRGB:0
634 isRGB:1
635 #StdOut ##
636##
637
638#ToDo incomplete ##
639
640##
641
642# ------------------------------------------------------------------------------
643
644#Method void flush()
645
646Triggers the immediate execution of all pending draw operations.
647If Canvas is associated with GPU_Surface, resolve all pending GPU operations.
648
649#Example
650#Error "haven't thought of a useful example to put here"
651##
652
653#ToDo incomplete ##
654
655##
656
657# ------------------------------------------------------------------------------
658
659#Method virtual SkISize getBaseLayerSize() const
660
661Gets the size of the base or root layer in global canvas coordinates. The
662origin of the base layer is always (0,0). The current drawable area may be
663smaller (due to clipping or saveLayer).
664
665#Return Integral width and height of base layer. ##
666
667#Example
668 SkBitmap bitmap;
669 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
670 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
671 canvas.clipRect(SkRect::MakeWH(10, 40));
672 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
673 if (clipDeviceBounds.isEmpty()) {
674 SkDebugf("Empty clip bounds is unexpected!\n");
675 }
676 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
677 SkISize baseLayerSize = canvas.getBaseLayerSize();
678 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
679
680 #StdOut
681 clip=10,30
682 size=20,30
683 ##
684##
685
686#ToDo is this the same as the width and height of surface? ##
687
688##
689
690# ------------------------------------------------------------------------------
691
692#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
693
694Creates Surface matching info and props, and associates it with Canvas.
695If Canvas is already associated with Surface, it cannot create a new Surface.
696
697#Param info Initialize Surface with width, height, Image_Color_Type, Image_Alpha_Type, and Color_Space. ##
698#Param props Use to match if provided, or use the Surface_Properties in Canvas otherwise. ##
699
700#Return Surface matching info and props, or nullptr if no match is available. ##
701
702#Example
703 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
704 SkCanvas* smallCanvas = surface->getCanvas();
705 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
706 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
707 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
708 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
709
710 #StdOut
711 compatible != nullptr
712 size = 3, 4
713 ##
714##
715
716#ToDo incomplete ##
717
718##
719
720# ------------------------------------------------------------------------------
721
722#Method virtual GrContext* getGrContext()
723
724Returns GPU_Context of the GPU_Surface associated with Canvas.
725
726#Return GPU_Context, if available; nullptr otherwise. ##
727
728#Example
729void draw(SkCanvas* canvas) {
730 if (canvas->getGrContext()) {
731 canvas->clear(SK_ColorRED);
732 } else {
733 canvas->clear(SK_ColorBLUE);
734 }
735}
736##
737
738#ToDo fiddle should show both CPU and GPU out ##
739
740##
741
742# ------------------------------------------------------------------------------
743
744#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL)
745
746Returns the pixel base address, Image_Info, rowBytes, and origin if the pixels
747can be read directly.
748The returned address is only valid
749while Canvas is in scope and unchanged. Any Canvas call or Surface call
750may invalidate the returned address and other returned values.
751
752If pixels are inaccessible, info, rowBytes, and origin are unchanged.
753
754#Param info If not nullptr, copies writable pixels' Image_Info. ##
755#Param rowBytes If not nullptr, copies writable pixels' row bytes. ##
756#Param origin If not nullptr, copies Canvas top layer origin, its top left corner. ##
757
758#Return Address of pixels, or nullptr if inaccessible. ##
759
760#Example
761void draw(SkCanvas* canvas) {
762 if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
763 canvas->clear(SK_ColorRED);
764 } else {
765 canvas->clear(SK_ColorBLUE);
766 }
767}
768##
769
770#Example
771#Description
772Draws "ABC" on the device. Then draws "DEF" in an offscreen layer, and reads the
773offscreen to add a large dotted "DEF". Finally blends the offscreen with the
774device.
775
776The offscreen and blended result appear on the CPU and GPU but the large dotted
777"DEF" appear only on the CPU.
778##
779void draw(SkCanvas* canvas) {
780 SkPaint paint;
781 paint.setTextSize(100);
782 canvas->drawString("ABC", 20, 160, paint);
783 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
784 canvas->saveLayerAlpha(&layerBounds, 128);
785 canvas->clear(SK_ColorWHITE);
786 canvas->drawString("DEF", 20, 160, paint);
787 SkImageInfo imageInfo;
788 size_t rowBytes;
789 SkIPoint origin;
790 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
791 if (access) {
792 int h = imageInfo.height();
793 int v = imageInfo.width();
794 int rowWords = rowBytes / sizeof(uint32_t);
795 for (int y = 0; y < h; ++y) {
796 int newY = (y - h / 2) * 2 + h / 2;
797 if (newY < 0 || newY >= h) {
798 continue;
799 }
800 for (int x = 0; x < v; ++x) {
801 int newX = (x - v / 2) * 2 + v / 2;
802 if (newX < 0 || newX >= v) {
803 continue;
804 }
805 if (access[y * rowWords + x] == SK_ColorBLACK) {
806 access[newY * rowWords + newX] = SK_ColorGRAY;
807 }
808 }
809 }
810
811 }
812 canvas->restore();
813}
814##
815
816#ToDo there are no callers of this that I can find. Deprecate? ##
817#ToDo fiddle should show both CPU and GPU out ##
818
819##
820
821# ------------------------------------------------------------------------------
822
823#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
824
825Returns custom context that tracks the Matrix and Clip.
826
827Use Raster_Handle_Allocator to blend Skia drawing with custom drawing, typically performed
828by the host platform's user interface. This accessor returns the custom context created
829when SkRasterHandleAllocator::MakeCanvas creates a custom canvas with raster storage for
830the drawing destination.
831
832#Return Context of custom allocator. ##
833
834#Example
835#Description
836#ToDo ##
837##
838#Function
839 static void DeleteCallback(void*, void* context) {
840 delete (char*) context;
841 }
842
843 class CustomAllocator : public SkRasterHandleAllocator {
844 public:
845 bool allocHandle(const SkImageInfo& info, Rec* rec) override {
846 char* context = new char[4]{'s', 'k', 'i', 'a'};
847 rec->fReleaseProc = DeleteCallback;
848 rec->fReleaseCtx = context;
849 rec->fHandle = context;
850 rec->fPixels = context;
851 rec->fRowBytes = 4;
852 return true;
853 }
854
855 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
856 // apply canvas matrix and clip to custom environment
857 }
858 };
859
860##
861 void draw(SkCanvas* canvas) {
862 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
863 std::unique_ptr<SkCanvas> c2 =
864 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
865 new CustomAllocator()), info);
866 char* context = (char*) c2->accessTopRasterHandle();
867 SkDebugf("context = %.4s\n", context);
868
869 }
870 #StdOut
871 context = skia
872 ##
873 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
874##
875
876#SeeAlso SkRasterHandleAllocator
877
878##
879
880# ------------------------------------------------------------------------------
881
882#Method bool peekPixels(SkPixmap* pixmap)
883
884Returns true if Canvas has direct access to its pixels.
885
886Pixels are readable when Device is raster. Pixels are not readable when SkCanvas is returned from
887GPU_Surface, returned by SkDocument::beginPage, returned by SkPictureRecorder::beginRecording,
888or SkCanvas is the base of a utility class like SkDumpCanvas.
889
890pixmap pixel address is only valid while Canvas is in scope and unchanged. Any Canvas or Surface call may
891invalidate the pixmap values.
892
893#Param pixmap storage for Canvas pixel state if Canvas pixels are readable; otherwise, ignored. ##
894
895#Return true if Canvas has direct access to pixels. ##
896
897#Example
898 SkPixmap pixmap;
899 if (canvas->peekPixels(&pixmap)) {
900 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
901 }
902 #StdOut
903 width=256 height=256
904 ##
905##
906
907##
908
909# ------------------------------------------------------------------------------
910
911#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
912 int srcX, int srcY)
913
914Copies rectangle of pixels from Canvas into dstPixels, converting their Image_Color_Type and Image_Alpha_Type.
915Pixels are readable when Device is raster. Pixels are not readable when SkCanvas is returned from
916GPU_Surface, returned by SkDocument::beginPage, returned by SkPictureRecorder::beginRecording,
917or SkCanvas is the base of a utility class like SkDumpCanvas.
918
919Pixel values are converted only if Canvas Image_Color_Type and Image_Alpha_Type does not match dstInfo.
920Only pixels within the rectangle that intersect Canvas pixels are copied.
921dstPixels outside the rectangle intersection are unchanged.
922
923#Table
924#Legend
925# source rectangle # value ##
926##
927# left # srcX ##
928# top # srcY ##
929# width # dstInfo.width() ##
930# height # dstInfo.height() ##
931##
932
933 #Table
934#Legend
935# canvas pixel bounds # value ##
936##
937# left # 0 ##
938# top # 0 ##
939# width # imageInfo().width() ##
940# height # imageInfo().height() ##
941##
942
943Does not copy, and returns false if:
944
945#List
946# Source rectangle and canvas pixel bounds do not intersect. ##
947# Canvas pixels could not be converted to dstInfo Image_Color_Type or dstInfo Image_Alpha_Type. ##
948# Canvas pixels are not readable; for instance, Canvas is not raster, or is document-based. ##
949# dstRowBytes is too small to contain one row of pixels. ##
950##
951
952#Param dstInfo Dimensions, Image_Color_Type, and Image_Alpha_Type of dstPixels. ##
953#Param dstPixels Storage for pixels, of size dstInfo.height() times dstRowBytes. ##
954#Param dstRowBytes Size of one destination row, dstInfo.width() times pixel size. ##
955#Param srcX Offset into readable pixels in x. ##
956#Param srcY Offset into readable pixels in y. ##
957
958#Return true if pixels were copied. ##
959
960#Example
961#Description
962 Canvas returned by Raster_Surface has premultiplied pixel values.
963 clear() takes unpremultiplied input with Color_Alpha equal 0x80
964 and Color_RGB equal 0x55, 0xAA, 0xFF. Color_RGB is multipled by Color_Alpha
965 to generate premultipled value 0x802B5580. readPixels converts pixel back
966 to unpremultipled value 0x8056A9FF, introducing error.
967##
968 canvas->clear(0x8055aaff);
969 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
970 uint32_t pixel = 0;
971 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
972 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
973 SkDebugf("pixel = %08x\n", pixel);
974 }
975 }
976
977 #StdOut
978 pixel = 802b5580
979 pixel = 8056a9ff
980 ##
981##
982
983#ToDo incomplete ##
984
985##
986
987# ------------------------------------------------------------------------------
988
989#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
990
991Copies rectangle of pixels from Canvas into Pixmap, converting their Image_Color_Type and Image_Alpha_Type.
992Pixels are readable when Device is raster. Pixels are not readable when SkCanvas is returned from
993GPU_Surface, returned by SkDocument::beginPage, returned by SkPictureRecorder::beginRecording,
994or SkCanvas is the base of a utility class like SkDumpCanvas.
995
996Pixel values are converted only if Canvas Image_Color_Type and Image_Alpha_Type does not match bitmap Image_Info.
997Only Pixmap pixels within the rectangle that intersect Canvas pixels are copied.
998Pixmap pixels outside the rectangle intersection are unchanged.
999
1000#Table
1001#Legend
1002# source rectangle # value ##
1003##
1004# left # srcX ##
1005# top # srcY ##
1006# width # bitmap.width() ##
1007# height # bitmap.height() ##
1008##
1009
1010 #Table
1011#Legend
1012# canvas pixel bounds # value ##
1013##
1014# left # 0 ##
1015# top # 0 ##
1016# width # imageInfo().width() ##
1017# height # imageInfo().height() ##
1018##
1019
1020Does not copy, and returns false if:
1021
1022#List
1023# Source rectangle and canvas pixel bounds do not intersect. ##
1024# Canvas pixels could not be converted to bitmap Image_Color_Type or bitmap Image_Alpha_Type. ##
1025# Canvas pixels are not readable; for instance, Canvas is not raster, or is document-based. ##
1026# bitmap pixels could not be allocated. ##
1027# Bitmap_Row_Bytes is too small to contain one row of pixels. ##
1028##
1029
1030#Param pixmap Receives pixels copied from Canvas. ##
1031#Param srcX Offset into readable pixels in x. ##
1032#Param srcY Offset into readable pixels in y. ##
1033
1034#Return true if pixels were copied. ##
1035
1036#Example
1037void draw(SkCanvas* canvas) {
1038 canvas->clear(0x8055aaff);
1039 uint32_t pixels[1] = { 0 };
1040 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
1041 canvas->readPixels(pixmap, 0, 0);
1042 SkDebugf("pixel = %08x\n", pixels[0]);
1043}
1044 #StdOut
1045 pixel = 802b5580
1046 ##
1047##
1048
1049#ToDo incomplete ##
1050
1051##
1052
1053# ------------------------------------------------------------------------------
1054
1055#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
1056
1057Copies pixels enclosed by bitmap offset to (x, y) from Canvas into bitmap, converting their Image_Color_Type and Image_Alpha_Type.
1058Pixels are readable when Device is raster. Pixels are not readable when SkCanvas is returned from
1059GPU_Surface, returned by SkDocument::beginPage, returned by SkPictureRecorder::beginRecording,
1060or SkCanvas is the base of a utility class like SkDumpCanvas.
1061Allocates pixel storage in bitmap if needed.
1062
1063Pixel values are converted only if Canvas Image_Color_Type and Image_Alpha_Type does not match bitmap Image_Info.
1064Only pixels within the rectangle that intersect Canvas pixels are copied.
1065Bitamp pixels outside the rectangle intersection are unchanged.
1066
1067 #Table
1068#Legend
1069# canvas pixel bounds # value ##
1070##
1071# left # 0 ##
1072# top # 0 ##
1073# width # imageInfo().width() ##
1074# height # imageInfo().height() ##
1075##
1076
1077Does not copy, and returns false if:
1078
1079#List
1080# Bounds formed by (x, y) and bitmap (width, height) and canvas pixel bounds do not intersect. ##
1081# Canvas pixels could not be converted to bitmap Image_Color_Type or bitmap Image_Alpha_Type. ##
1082# Canvas pixels are not readable; for instance, Canvas is not raster, or is document-based. ##
1083# bitmap pixels could not be allocated. ##
1084# Bitmap_Row_Bytes is too small to contain one row of pixels. ##
1085##
1086
1087#Param bitmap Receives pixels copied from Canvas. ##
1088#Param srcX Offset into readable pixels in x. ##
1089#Param srcY Offset into readable pixels in y. ##
1090
1091#Return true if pixels were copied. ##
1092
1093#Example
1094void draw(SkCanvas* canvas) {
1095 canvas->clear(0x8055aaff);
1096 SkBitmap bitmap;
1097 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
1098 canvas->readPixels(bitmap, 0, 0);
1099 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
1100}
1101 #StdOut
1102 pixel = 802b5580
1103 ##
1104##
1105
1106#ToDo incomplete ##
1107
1108##
1109
1110# ------------------------------------------------------------------------------
1111
1112#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
1113
1114Copies to Canvas pixels, ignoring the Matrix and Clip, converting to match
1115info Image_Color_Type and info Image_Alpha_Type.
1116
1117Pixel values are converted only if Canvas Image_Color_Type and Image_Alpha_Type does not match info.
1118Only pixels within the source rectangle that intersect Canvas pixel bounds are copied.
1119Canvas pixels outside the rectangle intersection are unchanged.
1120
1121#Table
1122#Legend
1123# source rectangle # value ##
1124##
1125# left # x ##
1126# top # y ##
1127# width # info.width() ##
1128# height # info.height() ##
1129##
1130
1131 #Table
1132#Legend
1133# canvas pixel bounds # value ##
1134##
1135# left # 0 ##
1136# top # 0 ##
1137# width # imageInfo().width() ##
1138# height # imageInfo().height() ##
1139##
1140
1141Does not copy, and returns false if:
1142
1143#List
1144# Source rectangle and canvas pixel bounds do not intersect. ##
1145# pixels could not be converted to Canvas Image_Color_Type or Canvas Image_Alpha_Type. ##
1146# Canvas pixels are not writable; for instance, Canvas is document-based. ##
1147# rowBytes is too small to contain one row of pixels. ##
1148##
1149
1150#Param info Dimensions, Image_Color_Type, and Image_Alpha_Type of pixels. ##
1151#Param pixels Pixels to copy, of size info.height() times rowBytes. ##
1152#Param rowBytes Offset from one row to the next, usually info.width() times pixel size. ##
1153#Param x Offset into Canvas writable pixels in x. ##
1154#Param y Offset into Canvas writable pixels in y. ##
1155
1156#Return true if pixels were written to Canvas. ##
1157
1158#Example
1159 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
1160 for (int y = 0; y < 256; ++y) {
1161 uint32_t pixels[256];
1162 for (int x = 0; x < 256; ++x) {
1163 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
1164 }
1165 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
1166 }
1167##
1168
1169#ToDo incomplete ##
1170
1171##
1172
1173# ------------------------------------------------------------------------------
1174
1175#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
1176
1177Writes to Canvas pixels, ignoring the Matrix and Clip, converting to match
1178bitmap Image_Color_Type and bitmap Image_Alpha_Type.
1179
1180Pixel values are converted only if Canvas Image_Color_Type and Image_Alpha_Type does not match bitmap.
1181Only pixels within the source rectangle that intersect Canvas pixel bounds are copied.
1182Canvas pixels outside the rectangle intersection are unchanged.
1183
1184#Table
1185#Legend
1186# source rectangle # value ##
1187##
1188# left # x ##
1189# top # y ##
1190# width # bitmap.width() ##
1191# height # bitmap.height() ##
1192##
1193
1194 #Table
1195#Legend
1196# canvas pixel bounds # value ##
1197##
1198# left # 0 ##
1199# top # 0 ##
1200# width # imageInfo().width() ##
1201# height # imageInfo().height() ##
1202##
1203
1204Does not copy, and returns false if:
1205
1206#List
1207# Source rectangle and Canvas pixel bounds do not intersect. ##
1208# bitmap does not have allocated pixels. ##
1209# bitmap pixels could not be converted to Canvas Image_Color_Type or Canvas Image_Alpha_Type. ##
1210# Canvas pixels are not writable; for instance, Canvas is document-based. ##
1211# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
1212##
1213
1214#Param bitmap Provides pixels copied to Canvas. ##
1215#Param x Offset into Canvas writable pixels in x. ##
1216#Param y Offset into Canvas writable pixels in y. ##
1217
1218#Return true if pixels were written to Canvas. ##
1219
1220#Example
1221void draw(SkCanvas* canvas) {
1222 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
1223 SkBitmap bitmap;
1224 bitmap.setInfo(imageInfo);
1225 uint32_t pixels[4];
1226 bitmap.setPixels(pixels);
1227 for (int y = 0; y < 256; y += 2) {
1228 for (int x = 0; x < 256; x += 2) {
1229 pixels[0] = SkColorSetRGB(x, y, x | y);
1230 pixels[1] = SkColorSetRGB(x ^ y, y, x);
1231 pixels[2] = SkColorSetRGB(x, x & y, y);
1232 pixels[3] = SkColorSetRGB(~x, ~y, x);
1233 canvas->writePixels(bitmap, x, y);
1234 }
1235 }
1236}
1237##
1238
1239#ToDo incomplete ##
1240
1241##
1242
1243# ------------------------------------------------------------------------------
1244#Topic State_Stack
1245
1246Canvas maintains a stack of state that allows hierarchical drawing, commonly used
1247to implement windows and views. The initial state has an identity matrix and and an infinite clip.
1248Even with a wide-open clip, drawing is constrained by the bounds of the
1249Canvas Surface or Device.
1250
1251Canvas savable state consists of Clip, Matrix, and Draw_Filter.
1252Clip describes the area that may be drawn to.
1253Matrix transforms the geometry.
1254Draw_Filter (deprecated on most platforms) modifies the paint before drawing.
1255
1256save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
1257save state and return the depth of the stack.
1258
1259restore() and restoreToCount revert state to its value when saved.
1260
1261Each state on the stack intersects Clip with the previous Clip,
1262and concatenates Matrix with the previous Matrix.
1263The intersected Clip makes the drawing area the same or smaller;
1264the concatenated Matrix may move the origin and potentially scale or rotate
1265the coordinate space.
1266
1267Canvas does not require balancing the state stack but it is a good idea
1268to do so. Calling save() without restore() will eventually cause Skia to fail;
1269mismatched save() and restore() create hard to find bugs.
1270
1271It is not possible to use state to draw outside of the clip defined by the
1272previous state.
1273
1274#Example
1275#Description
1276Draw to ever smaller clips; then restore drawing to full canvas.
1277Note that the second clipRect is not permitted to enlarge Clip.
1278##
1279#Height 160
1280void draw(SkCanvas* canvas) {
1281 SkPaint paint;
1282 canvas->save(); // records stack depth to restore
1283 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
1284 canvas->clear(SK_ColorRED); // draws to limit of clip
1285 canvas->save(); // records stack depth to restore
1286 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
1287 canvas->clear(SK_ColorBLUE); // draws to smaller clip
1288 canvas->restore(); // enlarges clip
1289 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
1290 canvas->restore(); // enlarges clip
1291 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
1292}
1293##
1294
1295Each Clip uses the current Matrix for its coordinates.
1296
1297#Example
1298#Description
1299While clipRect is given the same rectangle twice, Matrix makes the second
1300clipRect draw at half the size of the first.
1301##
1302#Height 128
1303void draw(SkCanvas* canvas) {
1304 canvas->clipRect(SkRect::MakeWH(100, 100));
1305 canvas->clear(SK_ColorRED);
1306 canvas->scale(.5, .5);
1307 canvas->clipRect(SkRect::MakeWH(100, 100));
1308 canvas->clear(SK_ColorBLUE);
1309}
1310##
1311
1312#SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
1313
1314#Method int save()
1315
1316Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms).
1317Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1318restoring the Matrix, Clip, and Draw_Filter to their state when save() was called.
1319
1320Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, and resetMatrix.
1321Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
1322
1323Saved Canvas state is put on a stack; multiple calls to save() should be balance by an equal number of
1324calls to restore().
1325
1326Call restoreToCount with result to restore this and subsequent saves.
1327
1328#Return Depth of saved stack. ##
1329
1330#Example
1331#Description
1332The black square is translated 50 pixels down and to the right.
1333Restoring Canvas state removes translate() from Canvas stack;
1334the red square is not translated, and is drawn at the origin.
1335##
1336#Height 100
1337void draw(SkCanvas* canvas) {
1338 SkPaint paint;
1339 SkRect rect = { 0, 0, 25, 25 };
1340 canvas->drawRect(rect, paint);
1341 canvas->save();
1342 canvas->translate(50, 50);
1343 canvas->drawRect(rect, paint);
1344 canvas->restore();
1345 paint.setColor(SK_ColorRED);
1346 canvas->drawRect(rect, paint);
1347}
1348##
1349
1350#ToDo incomplete ##
1351
1352##
1353
1354# ------------------------------------------------------------------------------
1355#Subtopic Layer
1356
1357Layer allocates a temporary offscreen Bitmap to draw into. When the drawing is complete,
1358the Bitmap is drawn into the Canvas.
1359
1360Layer is saved in a stack along with other saved state. When state with a Layer
1361is restored, the offscreen Bitmap is drawn into the previous layer.
1362
1363Layer may be initialized with the contents of the previous layer. When Layer is
1364restored, its Bitmap can be modified by Paint passed to Layer to apply Color_Alpha,
1365Color_Filter, Image_Filter, and Blend_Mode.
1366
1367#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1368
1369Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1370and allocates an offscreen Bitmap for subsequent drawing.
1371Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1372and draws the offscreen bitmap.
1373The Matrix, Clip, and Draw_Filter are restored to their state when save() was called.
1374
1375Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, and resetMatrix.
1376Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
1377
1378Rect bounds suggests but does not define the offscreen size. To clip drawing to a specific rectangle,
1379use clipRect.
1380
1381Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode when restore() is called.
1382
1383Call restoreToCount with result to restore this and subsequent saves.
1384
1385#Param bounds Used as a hint to limit the size of the offscreen; may be nullptr. ##
1386#Param paint Used when restore() is called to draw the offscreen; may be nullptr. ##
1387
1388#Return Depth of saved stack. ##
1389
1390#Example
1391#Description
1392Rectangles are blurred by Image_Filter when restore() draws offscreen to main Canvas.
1393##
1394#Height 128
1395void draw(SkCanvas* canvas) {
1396 SkPaint paint, blur;
1397 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1398 canvas->saveLayer(nullptr, &blur);
1399 SkRect rect = { 25, 25, 50, 50};
1400 canvas->drawRect(rect, paint);
1401 canvas->translate(50, 50);
1402 paint.setColor(SK_ColorRED);
1403 canvas->drawRect(rect, paint);
1404 canvas->restore();
1405}
1406##
1407
1408#ToDo incomplete ##
1409
1410##
1411
1412#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
1413
1414Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1415and allocates an offscreen Bitmap for subsequent drawing.
1416Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1417and draws the offscreen Bitmap.
1418The Matrix, Clip, and Draw_Filter are restored to their state when save() was called.
1419
1420Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, and resetMatrix.
1421Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
1422
1423bounds suggests but does not define the offscreen size. To clip drawing to a specific rectangle,
1424use clipRect.
1425
1426Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode when restore() is called.
1427
1428Call restoreToCount with result to restore this and subsequent saves.
1429
1430#Param bounds Used as a hint to limit the size of the offscreen; may be nullptr. ##
1431#Param paint Used when restore() is called to draw the offscreen; may be nullptr. ##
1432
1433#Return Depth of saved stack. ##
1434
1435#Example
1436#Description
1437Rectangles are blurred by Image_Filter when restore() draws offscreen to main Canvas.
1438The red rectangle is clipped; it does not fully fit on the offscreen Canvas.
1439Image_Filter blurs past edge of offscreen so red rectangle is blurred on all sides.
1440##
1441#Height 128
1442void draw(SkCanvas* canvas) {
1443 SkPaint paint, blur;
1444 blur.setImageFilter(SkImageFilter::MakeBlur(3, 3, nullptr));
1445 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1446 SkRect rect = { 25, 25, 50, 50};
1447 canvas->drawRect(rect, paint);
1448 canvas->translate(50, 50);
1449 paint.setColor(SK_ColorRED);
1450 canvas->drawRect(rect, paint);
1451 canvas->restore();
1452}
1453##
1454
1455#ToDo incomplete ##
1456
1457##
1458
1459#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
1460
1461Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1462and allocates an offscreen bitmap for subsequent drawing.
1463LCD_Text is preserved when the offscreen is drawn to the prior layer.
1464
1465Draw text on an opaque background so that LCD_Text blends correctly with the prior layer.
1466
1467Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1468and draws the offscreen bitmap.
1469The Matrix, Clip, and Draw_Filter are restored to their state when save() was called.
1470
1471Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, and resetMatrix.
1472Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
1473
1474Draw LCD_Text on an opaque background to get good results.
1475
1476bounds suggests but does not define the offscreen size. To clip drawing to a specific rectangle,
1477use clipRect.
1478
1479paint modifies how the offscreen overlays the prior layer. Color_Alpha, Blend_Mode,
1480Color_Filter, Draw_Looper, Image_Filter, and Mask_Filter, affect the offscreen draw.
1481
1482Call restoreToCount with result to restore this and subsequent saves.
1483
1484#Param bounds Used as a hint to limit the size of the offscreen; may be nullptr. ##
1485#Param paint Used when restore() is called to draw the offscreen; may be nullptr. ##
1486
1487#Return Depth of saved stack. ##
1488
1489#Example
1490 SkPaint paint;
1491 paint.setAntiAlias(true);
1492 paint.setLCDRenderText(true);
1493 paint.setTextSize(20);
1494 for (auto preserve : { false, true } ) {
1495 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
1496 : canvas->saveLayer(nullptr, nullptr);
1497 SkPaint p;
1498 p.setColor(SK_ColorWHITE);
1499 // Comment out the next line to draw on a non-opaque background.
1500 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
1501 canvas->drawString("Hamburgefons", 30, 60, paint);
1502
1503 p.setColor(0xFFCCCCCC);
1504 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
1505 canvas->drawString("Hamburgefons", 30, 90, paint);
1506
1507 canvas->restore();
1508 canvas->translate(0, 80);
1509 }
1510 ##
1511
1512#ToDo incomplete ##
1513
1514##
1515
1516#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1517
1518Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1519and allocates an offscreen bitmap for subsequent drawing.
1520
1521Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1522and blends the offscreen bitmap with alpha opacity onto the prior layer.
1523The Matrix, Clip, and Draw_Filter are restored to their state when save() was called.
1524
1525Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, and resetMatrix.
1526Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
1527
1528bounds suggests but does not define the offscreen size. To clip drawing to a specific rectangle,
1529use clipRect.
1530
1531Call restoreToCount with result to restore this and subsequent saves.
1532
1533#Param bounds Used as a hint to limit the size of the offscreen; may be nullptr. ##
1534#Param alpha The opacity of the offscreen; zero is fully transparent, 255 is fully opaque. ##
1535
1536#Return Depth of saved stack. ##
1537
1538#Example
1539 SkPaint paint;
1540 paint.setColor(SK_ColorRED);
1541 canvas->drawCircle(50, 50, 50, paint);
1542 canvas->saveLayerAlpha(nullptr, 128);
1543 paint.setColor(SK_ColorBLUE);
1544 canvas->drawCircle(100, 50, 50, paint);
1545 paint.setColor(SK_ColorGREEN);
1546 paint.setAlpha(128);
1547 canvas->drawCircle(75, 90, 50, paint);
1548 canvas->restore();
1549##
1550
1551#ToDo incomplete ##
1552
1553##
1554
1555#Enum SaveLayerFlags
1556
1557#Code
1558 enum {
1559 kIsOpaque_SaveLayerFlag = 1 << 0,
1560 kPreserveLCDText_SaveLayerFlag = 1 << 1,
1561 kInitWithPrevious_SaveLayerFlag = 1 << 2,
1562 };
1563
1564 typedef uint32_t SaveLayerFlags;
1565##
1566
1567SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
1568defining how the offscreen allocated by saveLayer operates.
1569
1570#Const kIsOpaque_SaveLayerFlag 1
1571 Creates offscreen without transparency. Flag is ignored if layer Paint contains
1572 Image_Filter or Color_Filter.
1573##
1574
1575#Const kPreserveLCDText_SaveLayerFlag 2
1576 Creates offscreen for LCD text. Flag is ignored if layer Paint contains
1577 Image_Filter or Color_Filter.
1578##
1579
1580#Const kInitWithPrevious_SaveLayerFlag 4
1581 Initializes offscreen with the contents of the previous layer.
1582##
1583
1584#Example
1585#Height 160
1586#Description
1587Canvas layer captures red and blue circles scaled up by four.
1588scalePaint blends offscreen back with transparency.
1589##
1590void draw(SkCanvas* canvas) {
1591 SkPaint redPaint, bluePaint, scalePaint;
1592 redPaint.setColor(SK_ColorRED);
1593 canvas->drawCircle(21, 21, 8, redPaint);
1594 bluePaint.setColor(SK_ColorBLUE);
1595 canvas->drawCircle(31, 21, 8, bluePaint);
1596 SkMatrix matrix;
1597 matrix.setScale(4, 4);
1598 scalePaint.setAlpha(0x40);
1599 scalePaint.setImageFilter(
1600 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1601 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
1602 SkCanvas::kInitWithPrevious_SaveLayerFlag);
1603 canvas->saveLayer(saveLayerRec);
1604 canvas->restore();
1605}
1606##
1607
1608#ToDo incomplete ##
1609
1610#Enum ##
1611
1612#Struct SaveLayerRec
1613
1614#Code
1615 struct SaveLayerRec {
1616 SaveLayerRec*(...
1617
1618 const SkRect* fBounds;
1619 const SkPaint* fPaint;
1620 const SkImageFilter* fBackdrop;
1621 SaveLayerFlags fSaveLayerFlags;
1622 };
1623##
1624
1625SaveLayerRec contains the state used to create the layer offscreen.
1626
1627#Member const SkRect* fBounds
1628 fBounds is used as a hint to limit the size of the offscreen; may be nullptr.
1629 fBounds suggests but does not define the offscreen size. To clip drawing to a specific rectangle,
1630 use clipRect.
1631##
1632
1633#Member const SkPaint* fPaint
1634 fPaint modifies how the offscreen overlays the prior layer; may be nullptr. Color_Alpha, Blend_Mode,
1635 Color_Filter, Draw_Looper, Image_Filter, and Mask_Filter affect the offscreen draw.
1636##
1637
1638#Member const SkImageFilter* fBackdrop
1639 fBackdrop applies Image_Filter to the prior layer when copying to the layer offscreen; may be nullptr.
1640 Use kInitWithPrevious_SaveLayerFlag to copy the prior layer without a Image_Filter.
1641##
1642
1643#Member const SkImage* fClipMask
1644#ToDo header documentation is incomplete ##
1645 may be nullptr.
1646##
1647
1648#Member const SkMatrix* fClipMatrix
1649#ToDo header documentation is incomplete ##
1650 may be nullptr.
1651##
1652
1653#Member SaveLayerFlags fSaveLayerFlags
1654 fSaveLayerFlags are used to create layer offscreen without transparency, create layer offscreen for
1655 LCD text, and to create layer offscreen with the contents of the previous layer.
1656##
1657
1658#Example
1659#Height 160
1660#Description
1661Canvas layer captures a red anti-aliased circle and a blue aliased circle scaled up by four.
1662After drawing another unscaled red circle on top, the offscreen is transferred to the main canvas.
1663##
1664void draw(SkCanvas* canvas) {
1665 SkPaint redPaint, bluePaint;
1666 redPaint.setAntiAlias(true);
1667 redPaint.setColor(SK_ColorRED);
1668 canvas->drawCircle(21, 21, 8, redPaint);
1669 bluePaint.setColor(SK_ColorBLUE);
1670 canvas->drawCircle(31, 21, 8, bluePaint);
1671 SkMatrix matrix;
1672 matrix.setScale(4, 4);
1673 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
1674 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
1675 canvas->saveLayer(saveLayerRec);
1676 canvas->drawCircle(125, 85, 8, redPaint);
1677 canvas->restore();
1678}
1679##
1680
1681#Method SaveLayerRec()
1682
1683Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
1684
1685#Return empty SaveLayerRec. ##
1686
1687#Example
1688 SkCanvas::SaveLayerRec rec1;
1689 rec1.fSaveLayerFlags = SkCanvas::kIsOpaque_SaveLayerFlag;
1690 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kIsOpaque_SaveLayerFlag);
1691 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1692 && rec1.fPaint == rec2.fPaint
1693 && rec1.fBackdrop == rec2.fBackdrop
1694 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1695 #StdOut
1696 rec1 == rec2
1697 ##
1698##
1699
1700##
1701
1702#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
1703
1704Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
1705
1706#Param bounds Offscreen dimensions; may be nullptr. ##
1707#Param paint Applied to offscreen when overlaying prior layer; may be nullptr. ##
1708#Param saveLayerFlags SaveLayerRec options to modify offscreen. ##
1709
1710#Return SaveLayerRec with empty backdrop. ##
1711
1712#Example
1713 SkCanvas::SaveLayerRec rec1;
1714 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1715 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1716 && rec1.fPaint == rec2.fPaint
1717 && rec1.fBackdrop == rec2.fBackdrop
1718 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1719 #StdOut
1720 rec1 == rec2
1721 ##
1722##
1723
1724##
1725
1726#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1727 SaveLayerFlags saveLayerFlags)
1728
1729Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
1730
1731#Param bounds Offscreen dimensions; may be nullptr. ##
1732#Param paint Applied to offscreen when overlaying prior layer; may be nullptr. ##
1733#Param backdrop Copies prior layer to offscreen with Image_Filter; may be nullptr. ##
1734#Param saveLayerFlags SaveLayerRec options to modify offscreen. ##
1735
1736#Return SaveLayerRec fully specified. ##
1737
1738#Example
1739 SkCanvas::SaveLayerRec rec1;
1740 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1741 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1742 && rec1.fPaint == rec2.fPaint
1743 && rec1.fBackdrop == rec2.fBackdrop
1744 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1745 #StdOut
1746 rec1 == rec2
1747 ##
1748##
1749
1750##
1751
1752#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1753 const SkImage* clipMask, const SkMatrix* clipMatrix,
1754 SaveLayerFlags saveLayerFlags)
1755
1756#Experimental
1757Not ready for general use.
1758##
1759
1760#Param bounds Offscreen dimensions; may be nullptr. ##
1761#Param paint Applied to offscreen when overlaying prior layer; may be nullptr. ##
1762#Param backdrop Copies prior layer to offscreen with Image_Filter; may be nullptr. ##
1763#Param clipMask May be nullptr. ##
1764#Param clipMatrix May be nullptr. ##
1765#Param saveLayerFlags SaveLayerRec options to modify offscreen. ##
1766
1767#Return SaveLayerRec fully specified. ##
1768
1769#ToDo incomplete ##
1770
1771##
1772
1773#Struct ##
1774
1775#Method int saveLayer(const SaveLayerRec& layerRec)
1776
1777Saves Matrix, Clip, and Draw_Filter (Draw_Filter deprecated on most platforms),
1778and allocates an offscreen bitmap for subsequent drawing.
1779
1780Calling restore() discards changes to Matrix, Clip, and Draw_Filter,
1781and blends the offscreen bitmap with alpha opacity onto the prior layer.
1782The Matrix, Clip, and Draw_Filter are restored to their state when save() was called.
1783
1784Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix, and resetMatrix.
1785Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
1786
1787SaveLayerRec contains the state used to create the layer offscreen.
1788
1789Call restoreToCount with result to restore this and subsequent saves.
1790
1791#Param layerRec offscreen state. ##
1792
1793#Return depth of save state stack. ##
1794
1795#Example
1796#Description
1797The example draws an image, and saves it into a layer with kInitWithPrevious_SaveLayerFlag.
1798Next it punches a hole in the layer and restore with SkBlendMode::kPlus.
1799Where the layer was cleared, the original image will draw unchanged.
1800Outside of the circle the mandrill is brightened.
1801##
1802 #Image 3
1803 // sk_sp<SkImage> image = GetResourceAsImage("mandrill_256.png");
1804 canvas->drawImage(image, 0, 0, nullptr);
1805 SkCanvas::SaveLayerRec rec;
1806 SkPaint paint;
1807 paint.setBlendMode(SkBlendMode::kPlus);
1808 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1809 rec.fPaint = &paint;
1810 canvas->saveLayer(rec);
1811 paint.setBlendMode(SkBlendMode::kClear);
1812 canvas->drawCircle(128, 128, 96, paint);
1813 canvas->restore();
1814##
1815
1816#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
1817
1818##
1819
1820#Subtopic Layer ##
1821
1822# ------------------------------------------------------------------------------
1823
1824#Method void restore()
1825
1826Removes changes to Matrix, Clip, and Draw_Filter since Canvas state was
1827last saved. The state is removed from the stack.
1828
1829Does nothing if the stack is empty.
1830
1831#Example
1832void draw(SkCanvas* canvas) {
1833 SkCanvas simple;
1834 SkDebugf("depth = %d\n", simple.getSaveCount());
1835 simple.restore();
1836 SkDebugf("depth = %d\n", simple.getSaveCount());
1837}
1838##
1839
1840##
1841
1842# ------------------------------------------------------------------------------
1843
1844#Method int getSaveCount() const
1845
1846Returns the number of saved states, each containing: Matrix, Clip, and Draw_Filter.
1847Equals the number of save() calls less the number of restore() calls plus one.
1848The save count of a new canvas is one.
1849
1850#Return depth of save state stack. ##
1851
1852#Example
1853void draw(SkCanvas* canvas) {
1854 SkCanvas simple;
1855 SkDebugf("depth = %d\n", simple.getSaveCount());
1856 simple.save();
1857 SkDebugf("depth = %d\n", simple.getSaveCount());
1858 simple.restore();
1859 SkDebugf("depth = %d\n", simple.getSaveCount());
1860}
1861#StdOut
1862depth = 1
1863depth = 2
1864depth = 1
1865##
1866##
1867
1868##
1869
1870# ------------------------------------------------------------------------------
1871
1872#Method void restoreToCount(int saveCount)
1873
1874Restores state to Matrix, Clip, and Draw_Filter
1875values when save(), saveLayer, saveLayerPreserveLCDTextRequests, or saveLayerAlpha
1876returned saveCount.
1877
1878Does nothing if saveCount is greater than state stack count.
1879Restores state to initial values if saveCount is less than or equal to one.
1880
1881#Param saveCount The depth of state stack to restore. ##
1882
1883#Example
1884void draw(SkCanvas* canvas) {
1885 SkDebugf("depth = %d\n", canvas->getSaveCount());
1886 canvas->save();
1887 canvas->save();
1888 SkDebugf("depth = %d\n", canvas->getSaveCount());
1889 canvas->restoreToCount(0);
1890 SkDebugf("depth = %d\n", canvas->getSaveCount());
1891}
1892#StdOut
1893depth = 1
1894depth = 3
1895depth = 1
1896##
1897##
1898
1899##
1900
1901#Topic State_Stack ##
1902
1903# ------------------------------------------------------------------------------
1904#Topic Matrix
1905
1906#Method void translate(SkScalar dx, SkScalar dy)
1907
1908Translate Matrix by dx along the x-axis and dy along the y-axis.
1909
1910Mathematically, replace Matrix with a translation matrix
1911pre-multiplied with Matrix.
1912
1913This has the effect of moving the drawing by (dx, dy) before transforming
1914the result with Matrix.
1915
1916#Param dx The distance to translate in x. ##
1917#Param dy The distance to translate in y. ##
1918
1919#Example
1920#Height 128
1921#Description
1922scale() followed by translate() produces different results from translate() followed
1923by scale().
1924
1925The blue stroke follows translate of (50, 50); a black
1926fill follows scale of (2, 1/2.f). After restoring the clip, which resets
1927Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
1928follows translate of (50, 50).
1929##
1930void draw(SkCanvas* canvas) {
1931 SkPaint filledPaint;
1932 SkPaint outlinePaint;
1933 outlinePaint.setStyle(SkPaint::kStroke_Style);
1934 outlinePaint.setColor(SK_ColorBLUE);
1935 canvas->save();
1936 canvas->translate(50, 50);
1937 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
1938 canvas->scale(2, 1/2.f);
1939 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
1940 canvas->restore();
1941 filledPaint.setColor(SK_ColorGRAY);
1942 outlinePaint.setColor(SK_ColorRED);
1943 canvas->scale(2, 1/2.f);
1944 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
1945 canvas->translate(50, 50);
1946 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
1947}
1948##
1949
1950#ToDo incomplete ##
1951
1952##
1953
1954# ------------------------------------------------------------------------------
1955
1956#Method void scale(SkScalar sx, SkScalar sy)
1957
1958Scale Matrix by sx on the x-axis and sy on the y-axis.
1959
1960Mathematically, replace Matrix with a scale matrix
1961pre-multiplied with Matrix.
1962
1963This has the effect of scaling the drawing by (sx, sy) before transforming
1964the result with Matrix.
1965
1966#Param sx The amount to scale in x. ##
1967#Param sy The amount to scale in y. ##
1968
1969#Example
1970#Height 160
1971void draw(SkCanvas* canvas) {
1972 SkPaint paint;
1973 SkRect rect = { 10, 20, 60, 120 };
1974 canvas->translate(20, 20);
1975 canvas->drawRect(rect, paint);
1976 canvas->scale(2, .5f);
1977 paint.setColor(SK_ColorGRAY);
1978 canvas->drawRect(rect, paint);
1979}
1980##
1981
1982#ToDo incomplete ##
1983
1984##
1985
1986# ------------------------------------------------------------------------------
1987
1988#Method void rotate(SkScalar degrees)
1989
1990Rotate Matrix by degrees. Positive degrees rotates clockwise.
1991
1992Mathematically, replace Matrix with a rotation matrix
1993pre-multiplied with Matrix.
1994
1995This has the effect of rotating the drawing by degrees before transforming
1996the result with Matrix.
1997
1998#Param degrees The amount to rotate, in degrees. ##
1999
2000#Example
2001#Description
2002Draw clock hands at time 5:10. The hour hand and minute hand point up and
2003are rotated clockwise.
2004##
2005void draw(SkCanvas* canvas) {
2006 SkPaint paint;
2007 paint.setStyle(SkPaint::kStroke_Style);
2008 canvas->translate(128, 128);
2009 canvas->drawCircle(0, 0, 60, paint);
2010 canvas->save();
2011 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
2012 canvas->drawLine(0, 0, 0, -50, paint);
2013 canvas->restore();
2014 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
2015 canvas->drawLine(0, 0, 0, -30, paint);
2016}
2017##
2018
2019#ToDo incomplete ##
2020
2021##
2022
2023# ------------------------------------------------------------------------------
2024
2025#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
2026
2027Rotate Matrix by degrees about a point at (px, py). Positive degrees rotates clockwise.
2028
2029Mathematically, construct a rotation matrix. Pre-multiply the rotation matrix by
2030a translation matrix, then replace Matrix with the resulting matrix
2031pre-multiplied with Matrix.
2032
2033This has the effect of rotating the drawing about a given point before transforming
2034the result with Matrix.
2035
2036#Param degrees The amount to rotate, in degrees. ##
2037#Param px The x coordinate of the point to rotate about. ##
2038#Param py The y coordinate of the point to rotate about. ##
2039
2040#Example
2041#Height 192
2042void draw(SkCanvas* canvas) {
2043 SkPaint paint;
2044 paint.setTextSize(96);
2045 canvas->drawString("A1", 130, 100, paint);
2046 canvas->rotate(180, 130, 100);
2047 canvas->drawString("A1", 130, 100, paint);
2048}
2049##
2050
2051#ToDo incomplete ##
2052
2053##
2054
2055# ------------------------------------------------------------------------------
2056
2057#Method void skew(SkScalar sx, SkScalar sy)
2058
2059Skew Matrix by sx on the x-axis and sy on the y-axis. A positive value of sx skews the
2060drawing right as y increases; a positive value of sy skews the drawing down as x increases.
2061
2062Mathematically, replace Matrix with a skew matrix
2063pre-multiplied with Matrix.
2064
2065Preconcat the current matrix with the specified skew.
2066#Param sx The amount to skew in x. ##
2067#Param sy The amount to skew in y. ##
2068
2069This has the effect of scaling the drawing by (sx, sy) before transforming
2070the result with Matrix.
2071
2072#Example
2073 #Description
2074 Black text mimics an oblique text style by using a negative skew in x that
2075 shifts the geometry to the right as the y values decrease.
2076 Red text uses a positive skew in y to shift the geometry down as the x values
2077 increase.
2078 Blue text combines x and y skew to rotate and scale.
2079 ##
2080 SkPaint paint;
2081 paint.setTextSize(128);
2082 canvas->translate(30, 130);
2083 canvas->save();
2084 canvas->skew(-.5, 0);
2085 canvas->drawString("A1", 0, 0, paint);
2086 canvas->restore();
2087 canvas->save();
2088 canvas->skew(0, .5);
2089 paint.setColor(SK_ColorRED);
2090 canvas->drawString("A1", 0, 0, paint);
2091 canvas->restore();
2092 canvas->skew(-.5, .5);
2093 paint.setColor(SK_ColorBLUE);
2094 canvas->drawString("A1", 0, 0, paint);
2095##
2096
2097#ToDo incomplete ##
2098
2099##
2100
2101# ------------------------------------------------------------------------------
2102
2103#Method void concat(const SkMatrix& matrix)
2104
2105Replace Matrix with matrix pre-multiplied with Matrix.
2106
2107This has the effect of transforming the drawn geometry by matrix, before transforming
2108the result with Matrix.
2109
2110#Param matrix Pre-multiply with Matrix. ##
2111
2112#Example
2113void draw(SkCanvas* canvas) {
2114 SkPaint paint;
2115 paint.setTextSize(80);
2116 paint.setTextScaleX(.3);
2117 SkMatrix matrix;
2118 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
2119 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
2120 canvas->drawRect(rect[0], paint);
2121 canvas->drawRect(rect[1], paint);
2122 paint.setColor(SK_ColorWHITE);
2123 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
2124 canvas->concat(matrix);
2125 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
2126}
2127##
2128
2129#ToDo incomplete ##
2130
2131##
2132
2133# ------------------------------------------------------------------------------
2134
2135#Method void setMatrix(const SkMatrix& matrix)
2136
2137Replace Matrix with matrix.
2138Unlike concat(), any prior matrix state is overwritten.
2139
2140#Param matrix Copied into Matrix. ##
2141
2142#Example
2143#Height 128
2144void draw(SkCanvas* canvas) {
2145 SkPaint paint;
2146 canvas->scale(4, 6);
2147 canvas->drawString("truth", 2, 10, paint);
2148 SkMatrix matrix;
2149 matrix.setScale(2.8f, 6);
2150 canvas->setMatrix(matrix);
2151 canvas->drawString("consequences", 2, 20, paint);
2152}
2153##
2154
2155#ToDo incomplete ##
2156
2157##
2158
2159# ------------------------------------------------------------------------------
2160
2161#Method void resetMatrix()
2162
2163Sets Matrix to the identity matrix.
2164Any prior matrix state is overwritten.
2165
2166#Example
2167#Height 128
2168void draw(SkCanvas* canvas) {
2169 SkPaint paint;
2170 canvas->scale(4, 6);
2171 canvas->drawString("truth", 2, 10, paint);
2172 canvas->resetMatrix();
2173 canvas->scale(2.8f, 6);
2174 canvas->drawString("consequences", 2, 20, paint);
2175}
2176##
2177
2178#ToDo incomplete ##
2179
2180##
2181
2182# ------------------------------------------------------------------------------
2183
2184#Method const SkMatrix& getTotalMatrix() const
2185
2186Returns Matrix.
2187This does not account for translation by Device or Surface.
2188
2189#Return Matrix on Canvas. ##
2190
2191#Example
2192 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
2193 #StdOut
2194 isIdentity true
2195 ##
2196##
2197
2198#ToDo incomplete ##
2199
2200##
2201
2202#Topic Matrix ##
2203
2204# ------------------------------------------------------------------------------
2205#Topic Clip
2206
2207Clip is built from a stack of clipping paths. Each Path in the
2208stack can be constructed from one or more Path_Contour elements. The
2209Path_Contour may be composed of any number of Path_Verb segments. Each
2210Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
2211by Path_Contour.
2212
2213Clip stack of Path elements successfully restrict the Path area. Each
2214Path is transformed by Matrix, then intersected with or subtracted from the
2215prior Clip to form the replacement Clip. Use SkClipOp::kDifference
2216to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
2217with Clip.
2218
2219A clipping Path may be anti-aliased; if Path, after transformation, is
2220composed of horizontal and vertical lines, clearing Anti-alias allows whole pixels
2221to either be inside or outside the clip. The fastest drawing has a aliased,
2222rectanglar clip.
2223
2224If clipping Path has Anti-alias set, clip may partially clip a pixel, requiring
2225that drawing blend partially with the destination along the edge. A rotated
2226rectangular anti-aliased clip looks smoother but draws slower.
2227
2228Clip can combine with Rect and Round_Rect primitives; like
2229Path, these are transformed by Matrix before they are combined with Clip.
2230
2231Clip can combine with Region. Region is assumed to be in Device coordinates
2232and is unaffected by Matrix.
2233
2234#Example
2235#Height 90
2236 #Description
2237 Draw a red circle with an aliased clip and an anti-aliased clip.
2238 Use an image filter to zoom into the pixels drawn.
2239 The edge of the aliased clip fully draws pixels in the red circle.
2240 The edge of the anti-aliased clip partially draws pixels in the red circle.
2241 ##
2242 SkPaint redPaint, scalePaint;
2243 redPaint.setAntiAlias(true);
2244 redPaint.setColor(SK_ColorRED);
2245 canvas->save();
2246 for (bool antialias : { false, true } ) {
2247 canvas->save();
2248 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
2249 canvas->drawCircle(17, 11, 8, redPaint);
2250 canvas->restore();
2251 canvas->translate(16, 0);
2252 }
2253 canvas->restore();
2254 SkMatrix matrix;
2255 matrix.setScale(6, 6);
2256 scalePaint.setImageFilter(
2257 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
2258 SkCanvas::SaveLayerRec saveLayerRec(
2259 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
2260 canvas->saveLayer(saveLayerRec);
2261 canvas->restore();
2262##
2263
2264#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
2265
2266Replace Clip with the intersection or difference of Clip and rect,
2267with an aliased or anti-aliased clip edge. rect is transformed by Matrix
2268before it is combined with Clip.
2269
2270#Param rect Rectangle to combine with Clip. ##
2271#Param op Clip_Op to apply to Clip. ##
2272#Param doAntiAlias true if Clip is to be anti-aliased. ##
2273
2274#Example
2275#Height 128
2276void draw(SkCanvas* canvas) {
2277 canvas->rotate(10);
2278 SkPaint paint;
2279 paint.setAntiAlias(true);
2280 for (auto alias: { false, true } ) {
2281 canvas->save();
2282 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
2283 canvas->drawCircle(100, 60, 60, paint);
2284 canvas->restore();
2285 canvas->translate(80, 0);
2286 }
2287}
2288##
2289
2290#ToDo incomplete ##
2291
2292##
2293
2294#Method void clipRect(const SkRect& rect, SkClipOp op)
2295
2296Replace Clip with the intersection or difference of Clip and rect.
2297Resulting Clip is aliased; pixels are fully contained by the clip.
2298rect is transformed by Matrix
2299before it is combined with Clip.
2300
2301#Param rect Rectangle to combine with Clip. ##
2302#Param op Clip_Op to apply to Clip. ##
2303
2304#Example
2305#Height 192
2306#Width 280
2307void draw(SkCanvas* canvas) {
2308 SkPaint paint;
2309 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
2310 canvas->save();
2311 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
2312 canvas->drawCircle(100, 100, 60, paint);
2313 canvas->restore();
2314 canvas->translate(80, 0);
2315 }
2316}
2317##
2318
2319#ToDo incomplete ##
2320
2321##
2322
2323#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
2324
2325Replace Clip with the intersection of Clip and rect.
2326Resulting Clip is aliased; pixels are fully contained by the clip.
2327rect is transformed by Matrix
2328before it is combined with Clip.
2329
2330#Param rect Rectangle to combine with Clip. ##
2331#Param doAntiAlias true if Clip is to be anti-aliased. ##
2332
2333#Example
2334#Height 133
2335 #Description
2336 A circle drawn in pieces looks uniform when drawn aliased.
2337 The same circle pieces blend with pixels more than once when anti-aliased,
2338 visible as a thin pair of lines through the right circle.
2339 ##
2340void draw(SkCanvas* canvas) {
2341 canvas->clear(SK_ColorWHITE);
2342 SkPaint paint;
2343 paint.setAntiAlias(true);
2344 paint.setColor(0x8055aaff);
2345 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
2346 for (auto alias: { false, true } ) {
2347 canvas->save();
2348 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
2349 canvas->drawCircle(67, 67, 60, paint);
2350 canvas->restore();
2351 canvas->save();
2352 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
2353 canvas->drawCircle(67, 67, 60, paint);
2354 canvas->restore();
2355 canvas->translate(120, 0);
2356 }
2357}
2358##
2359
2360#ToDo incomplete ##
2361
2362##
2363
2364#Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect)
2365
2366Sets the max clip rectangle, which can be set by clipRect, clipRRect and
2367clipPath and intersect the current clip with the specified rect.
2368The max clip affects only future ops (it is not retroactive).
2369The clip restriction is not recorded in pictures.
2370
2371#Private
2372This is private API to be used only by Android framework.
2373##
2374
2375#Param rect The maximum allowed clip in device coordinates.
Cary Clark579985c2017-07-31 11:48:27 -04002376 Empty rect means max clip is not enforced.
2377#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04002378
2379##
2380
2381#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
2382
2383Replace Clip with the intersection or difference of Clip and rrect,
2384with an aliased or anti-aliased clip edge.
2385rrect is transformed by Matrix
2386before it is combined with Clip.
2387
2388#Param rrect Round_Rect to combine with Clip. ##
2389#Param op Clip_Op to apply to Clip. ##
2390#Param doAntiAlias true if Clip is to be antialiased. ##
2391
2392#Example
2393#Height 128
2394void draw(SkCanvas* canvas) {
2395 canvas->clear(SK_ColorWHITE);
2396 SkPaint paint;
2397 paint.setAntiAlias(true);
2398 paint.setColor(0x8055aaff);
2399 SkRRect oval;
2400 oval.setOval({10, 20, 90, 100});
2401 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
2402 canvas->drawCircle(70, 100, 60, paint);
2403}
2404##
2405
2406#ToDo incomplete ##
2407
2408##
2409
2410#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
2411
2412Replace Clip with the intersection or difference of Clip and rrect.
2413Resulting Clip is aliased; pixels are fully contained by the clip.
2414rrect is transformed by Matrix
2415before it is combined with Clip.
2416
2417#Param rrect Round_Rect to combine with Clip. ##
2418#Param op Clip_Op to apply to Clip. ##
2419
2420#Example
2421#Height 128
2422void draw(SkCanvas* canvas) {
2423 SkPaint paint;
2424 paint.setColor(0x8055aaff);
2425 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
2426 canvas->clipRRect(oval, SkClipOp::kIntersect);
2427 canvas->drawCircle(70, 100, 60, paint);
2428}
2429##
2430
2431#ToDo incomplete ##
2432
2433##
2434
2435#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
2436
2437Replace Clip with the intersection of Clip and rrect,
2438with an aliased or anti-aliased clip edge.
2439rrect is transformed by Matrix
2440before it is combined with Clip.
2441
2442#Param rrect Round_Rect to combine with Clip. ##
2443#Param doAntiAlias true if Clip is to be antialiased. ##
2444
2445#Example
2446#Height 128
2447void draw(SkCanvas* canvas) {
2448 SkPaint paint;
2449 paint.setAntiAlias(true);
2450 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
2451 canvas->clipRRect(oval, true);
2452 canvas->drawCircle(70, 100, 60, paint);
2453}
2454##
2455
2456#ToDo incomplete ##
2457
2458##
2459
2460#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
2461
2462Replace Clip with the intersection or difference of Clip and path,
2463with an aliased or anti-aliased clip edge. Path_Fill_Type determines if path
2464describes the area inside or outside its contours; and if Path_Contour overlaps
2465itself or another Path_Contour, whether the overlaps form part of the area.
2466path is transformed by Matrix
2467before it is combined with Clip.
2468
2469#Param path Path to combine with Clip. ##
2470#Param op Clip_Op to apply to Clip. ##
2471#Param doAntiAlias true if Clip is to be antialiased. ##
2472
2473#Example
2474#Description
2475Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
2476area outside clip is subtracted from circle.
2477
2478Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
2479area inside clip is intersected with circle.
2480##
2481void draw(SkCanvas* canvas) {
2482 SkPaint paint;
2483 paint.setAntiAlias(true);
2484 SkPath path;
2485 path.addRect({20, 30, 100, 110});
2486 path.setFillType(SkPath::kInverseWinding_FillType);
2487 canvas->save();
2488 canvas->clipPath(path, SkClipOp::kDifference, false);
2489 canvas->drawCircle(70, 100, 60, paint);
2490 canvas->restore();
2491 canvas->translate(100, 100);
2492 path.setFillType(SkPath::kWinding_FillType);
2493 canvas->clipPath(path, SkClipOp::kIntersect, false);
2494 canvas->drawCircle(70, 100, 60, paint);
2495}
2496##
2497
2498#ToDo incomplete ##
2499
2500##
2501
2502#Method void clipPath(const SkPath& path, SkClipOp op)
2503
2504Replace Clip with the intersection or difference of Clip and path.
2505Resulting Clip is aliased; pixels are fully contained by the clip.
2506Path_Fill_Type determines if path
2507describes the area inside or outside its contours; and if Path_Contour overlaps
2508itself or another Path_Contour, whether the overlaps form part of the area.
2509path is transformed by Matrix
2510before it is combined with Clip.
2511
2512#Param path Path to combine with Clip. ##
2513#Param op Clip_Op to apply to Clip. ##
2514
2515#Example
2516#Description
2517Overlapping Rects form a clip. When clip's Path_Fill_Type is set to
2518SkPath::kWinding_FillType, the overlap is included. Set to
2519SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2520##
2521void draw(SkCanvas* canvas) {
2522 SkPaint paint;
2523 paint.setAntiAlias(true);
2524 SkPath path;
2525 path.addRect({20, 15, 100, 95});
2526 path.addRect({50, 65, 130, 135});
2527 path.setFillType(SkPath::kWinding_FillType);
2528 canvas->save();
2529 canvas->clipPath(path, SkClipOp::kIntersect);
2530 canvas->drawCircle(70, 85, 60, paint);
2531 canvas->restore();
2532 canvas->translate(100, 100);
2533 path.setFillType(SkPath::kEvenOdd_FillType);
2534 canvas->clipPath(path, SkClipOp::kIntersect);
2535 canvas->drawCircle(70, 85, 60, paint);
2536}
2537##
2538
2539#ToDo incomplete ##
2540
2541##
2542
2543#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
2544
2545Replace Clip with the intersection of Clip and path.
2546Resulting Clip is aliased; pixels are fully contained by the clip.
2547Path_Fill_Type determines if path
2548describes the area inside or outside its contours; and if Path_Contour overlaps
2549itself or another Path_Contour, whether the overlaps form part of the area.
2550path is transformed by Matrix
2551before it is combined with Clip.
2552
2553#Param path Path to combine with Clip. ##
2554#Param doAntiAlias true if Clip is to be antialiased. ##
2555
2556#Example
2557#Height 212
2558#Description
2559Clip loops over itself covering its center twice. When clip's Path_Fill_Type
2560is set to SkPath::kWinding_FillType, the overlap is included. Set to
2561SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2562##
2563void draw(SkCanvas* canvas) {
2564 SkPaint paint;
2565 paint.setAntiAlias(true);
2566 SkPath path;
2567 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2568 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2569 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2570 path.setFillType(SkPath::kWinding_FillType);
2571 canvas->save();
2572 canvas->clipPath(path, SkClipOp::kIntersect);
2573 canvas->drawCircle(50, 50, 45, paint);
2574 canvas->restore();
2575 canvas->translate(100, 100);
2576 path.setFillType(SkPath::kEvenOdd_FillType);
2577 canvas->clipPath(path, SkClipOp::kIntersect);
2578 canvas->drawCircle(50, 50, 45, paint);
2579}
2580##
2581
2582#ToDo incomplete ##
2583
2584##
2585
2586# ------------------------------------------------------------------------------
2587
2588#Method void setAllowSimplifyClip(bool allow)
2589
2590#Experimental
2591Only used for testing.
2592##
2593
2594Set to simplify clip stack using path ops.
2595
2596##
2597
2598# ------------------------------------------------------------------------------
2599
2600#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2601
2602Replace Clip with the intersection or difference of Clip and Region deviceRgn.
2603Resulting Clip is aliased; pixels are fully contained by the clip.
2604deviceRgn is unaffected by Matrix.
2605
2606#Param deviceRgn Region to combine with Clip. ##
2607#Param op Clip_Op to apply to Clip. ##
2608
2609#Example
2610#Description
2611 region is unaffected by canvas rotation; rect is affected by canvas rotation.
2612 Both clips are aliased; this is unnoticable on Region clip because it
2613 aligns to pixel boundaries.
2614##
2615void draw(SkCanvas* canvas) {
2616 SkPaint paint;
2617 paint.setAntiAlias(true);
2618 SkIRect iRect = {30, 40, 120, 130 };
2619 SkRegion region(iRect);
2620 canvas->rotate(10);
2621 canvas->save();
2622 canvas->clipRegion(region, SkClipOp::kIntersect);
2623 canvas->drawCircle(50, 50, 45, paint);
2624 canvas->restore();
2625 canvas->translate(100, 100);
2626 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2627 canvas->drawCircle(50, 50, 45, paint);
2628}
2629##
2630
2631#ToDo incomplete ##
2632
2633##
2634
2635#Method bool quickReject(const SkRect& rect) const
2636
2637Return true if Rect rect, transformed by Matrix, can be quickly determined to be
2638outside of Clip. May return false even though rect is outside of Clip.
2639
2640Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2641
2642#Param rect Rect to compare with Clip. ##
2643
2644#Return true if rect, transformed by Matrix, does not intersect Clip. ##
2645
2646#Example
2647void draw(SkCanvas* canvas) {
2648 SkRect testRect = {30, 30, 120, 129 };
2649 SkRect clipRect = {30, 130, 120, 230 };
2650 canvas->save();
2651 canvas->clipRect(clipRect);
2652 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2653 canvas->restore();
2654 canvas->rotate(10);
2655 canvas->clipRect(clipRect);
2656 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2657}
2658 #StdOut
2659 quickReject true
2660 quickReject false
2661 ##
2662##
2663
2664#ToDo incomplete ##
2665
2666##
2667
2668#Method bool quickReject(const SkPath& path) const
2669
2670Return true if path, transformed by Matrix, can be quickly determined to be
2671outside of Clip. May return false even though path is outside of Clip.
2672
2673Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
2674
2675#Param path Path to compare with Clip. ##
2676
2677#Return true if path, transformed by Matrix, does not intersect Clip. ##
2678
2679#Example
2680void draw(SkCanvas* canvas) {
2681 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2682 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2683 SkPath testPath, clipPath;
2684 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2685 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2686 canvas->save();
2687 canvas->clipPath(clipPath);
2688 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2689 canvas->restore();
2690 canvas->rotate(10);
2691 canvas->clipPath(clipPath);
2692 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2693 #StdOut
2694 quickReject true
2695 quickReject false
2696 ##
2697}
2698##
2699
2700#ToDo incomplete ##
2701
2702##
2703
2704#Method SkRect getLocalClipBounds() const
2705
2706Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2707return SkRect::MakeEmpty, where all Rect sides equal zero.
2708
2709Rect returned is outset by one to account for partial pixel coverage if Clip
2710is anti-aliased.
2711
2712#Return bounds of Clip in local coordinates. ##
2713
2714#Example
2715 #Description
2716 Initial bounds is device bounds outset by 1 on all sides.
2717 Clipped bounds is clipPath bounds outset by 1 on all sides.
2718 Scaling the canvas by two in x and y scales the local bounds by 1/2 in x and y.
2719 ##
2720 SkCanvas local(256, 256);
2721 canvas = &local;
2722 SkRect bounds = canvas->getLocalClipBounds();
2723 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2724 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2725 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2726 SkPath clipPath;
2727 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2728 canvas->clipPath(clipPath);
2729 bounds = canvas->getLocalClipBounds();
2730 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2731 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2732 canvas->scale(2, 2);
2733 bounds = canvas->getLocalClipBounds();
2734 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2735 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2736 #StdOut
2737 left:-1 top:-1 right:257 bottom:257
2738 left:29 top:129 right:121 bottom:231
2739 left:14.5 top:64.5 right:60.5 bottom:115.5
2740 ##
2741##
2742
2743# local canvas in example works around bug in fiddle ##
2744#Bug 6524 ##
2745
2746##
2747
2748#Method bool getLocalClipBounds(SkRect* bounds) const
2749
2750Return bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
2751return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2752
2753bounds is outset by one to account for partial pixel coverage if Clip
2754is anti-aliased.
2755
2756#Param bounds Rect of Clip in local coordinates. ##
2757
2758#Return true if Clip bounds is not empty. ##
2759
2760#Example
2761 void draw(SkCanvas* canvas) {
2762 SkCanvas local(256, 256);
2763 canvas = &local;
2764 SkRect bounds;
2765 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2766 ? "false" : "true");
2767 SkPath path;
2768 canvas->clipPath(path);
2769 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2770 ? "false" : "true");
2771 }
2772 #StdOut
2773 local bounds empty = false
2774 local bounds empty = true
2775 ##
2776##
2777
2778# local canvas in example works around bug in fiddle ##
2779#Bug 6524 ##
2780
2781##
2782
2783#Method SkIRect getDeviceClipBounds() const
2784
2785Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2786return SkRect::MakeEmpty, where all Rect sides equal zero.
2787
2788Unlike getLocalClipBounds, returned IRect is not outset.
2789
2790#Return bounds of Clip in Device coordinates. ##
2791
2792#Example
2793void draw(SkCanvas* canvas) {
2794 #Description
2795 Initial bounds is device bounds, not outset.
2796 Clipped bounds is clipPath bounds, not outset.
2797 Scaling the canvas by 1/2 in x and y scales the device bounds by 1/2 in x and y.
2798 ##
2799 SkCanvas device(256, 256);
2800 canvas = &device;
2801 SkIRect bounds = canvas->getDeviceClipBounds();
2802 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2803 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2804 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
2805 SkPath clipPath;
2806 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2807 canvas->save();
2808 canvas->clipPath(clipPath);
2809 bounds = canvas->getDeviceClipBounds();
2810 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2811 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2812 canvas->restore();
2813 canvas->scale(1.f/2, 1.f/2);
2814 canvas->clipPath(clipPath);
2815 bounds = canvas->getDeviceClipBounds();
2816 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2817 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2818 #StdOut
2819 left:0 top:0 right:256 bottom:256
2820 left:30 top:130 right:120 bottom:230
2821 left:15 top:65 right:60 bottom:115
2822 ##
2823}
2824##
2825
2826#ToDo some confusion on why with an identity Matrix local and device are different ##
2827
2828# device canvas in example works around bug in fiddle ##
2829#Bug 6524 ##
2830
2831##
2832
2833#Method bool getDeviceClipBounds(SkIRect* bounds) const
2834
2835Return IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
2836return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
2837
2838Unlike getLocalClipBounds, bounds is not outset.
2839
2840#Param bounds Rect of Clip in device coordinates. ##
2841
2842#Return true if Clip bounds is not empty. ##
2843
2844#Example
2845 void draw(SkCanvas* canvas) {
2846 SkIRect bounds;
2847 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2848 ? "false" : "true");
2849 SkPath path;
2850 canvas->clipPath(path);
2851 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2852 ? "false" : "true");
2853 }
2854 #StdOut
2855 device bounds empty = false
2856 device bounds empty = true
2857 ##
2858##
2859
2860#ToDo incomplete ##
2861
2862##
2863
2864#Topic Clip ##
2865
2866# ------------------------------------------------------------------------------
2867
2868#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
2869
2870Fill Clip with Color color.
2871mode determines how Color_ARGB is combined with destination.
2872
2873#Param color Unpremultiplied Color_ARGB. ##
2874#Param mode SkBlendMode used to combine source color and destination. ##
2875
2876#Example
2877 canvas->drawColor(SK_ColorRED);
2878 canvas->clipRect(SkRect::MakeWH(150, 150));
2879 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
2880 canvas->clipRect(SkRect::MakeWH(75, 75));
2881 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
2882##
2883
2884#ToDo incomplete ##
2885
2886##
2887
2888# ------------------------------------------------------------------------------
2889
2890#Method void clear(SkColor color)
2891
2892Fill Clip with Color color using SkBlendMode::kSrc.
2893This has the effect of replacing all pixels contained by Clip with color.
2894
2895#Param color Unpremultiplied Color_ARGB. ##
2896
2897#Example
2898void draw(SkCanvas* canvas) {
2899 canvas->save();
2900 canvas->clipRect(SkRect::MakeWH(256, 128));
2901 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
2902 canvas->restore();
2903 canvas->save();
2904 canvas->clipRect(SkRect::MakeWH(150, 192));
2905 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
2906 canvas->restore();
2907 canvas->clipRect(SkRect::MakeWH(75, 256));
2908 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
2909}
2910##
2911
2912#ToDo incomplete ##
2913
2914##
2915
2916# ------------------------------------------------------------------------------
2917
2918#Method void discard()
2919
2920Make Canvas contents undefined. Subsequent calls that read Canvas pixels,
2921such as drawing with SkBlendMode, return undefined results. discard() does
2922not change Clip or Matrix.
2923
2924discard() may do nothing, depending on the implementation of Surface or Device
2925that created Canvas.
2926
2927discard() allows optimized performance on subsequent draws by removing
2928cached data associated with Surface or Device.
2929It is not necessary to call discard() once done with Canvas;
2930any cached data is deleted when owning Surface or Device is deleted.
2931
2932#ToDo example? not sure how to make this meaningful w/o more implementation detail ##
2933
2934#NoExample
2935##
2936
2937##
2938
2939# ------------------------------------------------------------------------------
2940
2941#Method void drawPaint(const SkPaint& paint)
2942
2943Fill Clip with Paint paint. drawPaint is affected by Paint components
2944Rasterizer, Mask_Filter, Shader, Color_Filter, Image_Filter, and Blend_Mode; but not by
2945Path_Effect.
2946
2947# can Path_Effect in paint ever alter drawPaint?
2948
2949#Param paint Used to fill the canvas. ##
2950
2951#Example
2952void draw(SkCanvas* canvas) {
2953 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
2954 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
2955 SkPaint paint;
2956 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
2957 canvas->drawPaint(paint);
2958}
2959##
2960
2961#ToDo incomplete ##
2962
2963##
2964
2965# ------------------------------------------------------------------------------
2966
2967#Enum PointMode
2968
2969#Code
2970 enum PointMode {
2971 kPoints_PointMode,
2972 kLines_PointMode,
2973 kPolygon_PointMode
2974 };
2975##
2976
2977Selects if an array of points are drawn as discrete points, as lines, or as
2978an open polygon.
2979
2980#Const kPoints_PointMode 0
2981 Draw each point separately.
2982##
2983
2984#Const kLines_PointMode 1
2985 Draw each pair of points as a line segment.
2986##
2987
2988#Const kPolygon_PointMode 2
2989 Draw the array of points as a open polygon.
2990##
2991
2992#Example
2993 #Description
2994 The upper left corner shows three squares when drawn as points.
2995 The upper right corner shows one line; when drawn as lines, two points are required per line.
2996 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
2997 The lower left corner shows two lines with a miter when path contains polygon.
2998 ##
2999void draw(SkCanvas* canvas) {
3000 SkPaint paint;
3001 paint.setStyle(SkPaint::kStroke_Style);
3002 paint.setStrokeWidth(10);
3003 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
3004 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
3005 canvas->translate(128, 0);
3006 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
3007 canvas->translate(0, 128);
3008 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
3009 SkPath path;
3010 path.addPoly(points, 3, false);
3011 canvas->translate(-128, 0);
3012 canvas->drawPath(path, paint);
3013}
3014##
3015
3016#ToDo incomplete ##
3017
3018##
3019
3020# ------------------------------------------------------------------------------
3021
3022#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
3023
3024Draw pts using Clip, Matrix and Paint paint.
3025count is the number of points; if count is less than one, drawPoints has no effect.
3026mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
3027
3028If mode is kPoints_PointMode, the shape of point drawn depends on paint Paint_Stroke_Cap.
3029If paint is set to SkPaint::kRound_Cap, each point draws a circle of diameter Paint_Stroke_Width.
3030If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
3031each point draws a square of width and height Paint_Stroke_Width.
3032
3033If mode is kLines_PointMode, each pair of points draws a line segment.
3034One line is drawn for every two points; each point is used once. If count is odd,
3035the final point is ignored.
3036
3037If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
3038count minus one lines are drawn; the first and last point are used once.
3039
3040Each line segment respects paint Paint_Stroke_Cap and Paint_Stroke_Width.
3041Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3042
3043drawPoints always draws each element one at a time; drawPoints is not affected by
3044Paint_Stroke_Join, and unlike drawPath, does not create a mask from all points and lines
3045before drawing.
3046
3047#Param mode Whether pts draws points or lines. ##
3048#Param count The number of points in the array. ##
3049#Param pts Array of points to draw. ##
3050#Param paint Stroke, blend, color, and so on, used to draw. ##
3051
3052#Example
3053#Height 200
3054 #Description
3055 #List
3056 # The first column draws points. ##
3057 # The second column draws points as lines. ##
3058 # The third column draws points as a polygon. ##
3059 # The fourth column draws points as a polygonal path. ##
3060 # The first row uses a round cap and round join. ##
3061 # The second row uses a square cap and a miter join. ##
3062 # The third row uses a butt cap and a bevel join. ##
3063 ##
3064 The transparent color makes multiple line draws visible;
3065 the path is drawn all at once.
3066 ##
3067void draw(SkCanvas* canvas) {
3068 SkPaint paint;
3069 paint.setAntiAlias(true);
3070 paint.setStyle(SkPaint::kStroke_Style);
3071 paint.setStrokeWidth(10);
3072 paint.setColor(0x80349a45);
3073 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
3074 const SkPaint::Join join[] = { SkPaint::kRound_Join,
3075 SkPaint::kMiter_Join,
3076 SkPaint::kBevel_Join };
3077 int joinIndex = 0;
3078 SkPath path;
3079 path.addPoly(points, 3, false);
3080 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
3081 paint.setStrokeCap(cap);
3082 paint.setStrokeJoin(join[joinIndex++]);
3083 for (const auto mode : { SkCanvas::kPoints_PointMode,
3084 SkCanvas::kLines_PointMode,
3085 SkCanvas::kPolygon_PointMode } ) {
3086 canvas->drawPoints(mode, 3, points, paint);
3087 canvas->translate(64, 0);
3088 }
3089 canvas->drawPath(path, paint);
3090 canvas->translate(-192, 64);
3091 }
3092}
3093##
3094
3095#ToDo incomplete ##
3096
3097##
3098
3099# ------------------------------------------------------------------------------
3100
3101#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
3102
3103Draw point at (x, y) using Clip, Matrix and Paint paint.
3104
3105The shape of point drawn depends on paint Paint_Stroke_Cap.
3106If paint is set to SkPaint::kRound_Cap, draw a circle of diameter Paint_Stroke_Width.
3107If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
3108draw a square of width and height Paint_Stroke_Width.
3109Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3110
3111#Param x Left edge of circle or square. ##
3112#Param y Top edge of circle or square. ##
3113#Param paint Stroke, blend, color, and so on, used to draw. ##
3114
3115#Example
3116void draw(SkCanvas* canvas) {
3117 SkPaint paint;
3118 paint.setAntiAlias(true);
3119 paint.setColor(0x80349a45);
3120 paint.setStyle(SkPaint::kStroke_Style);
3121 paint.setStrokeWidth(100);
3122 paint.setStrokeCap(SkPaint::kRound_Cap);
3123 canvas->scale(1, 1.2f);
3124 canvas->drawPoint(64, 96, paint);
3125 canvas->scale(.6f, .8f);
3126 paint.setColor(SK_ColorWHITE);
3127 canvas->drawPoint(106, 120, paint);
3128}
3129##
3130
3131#ToDo incomplete ##
3132
3133##
3134
3135# ------------------------------------------------------------------------------
3136
3137#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
3138
3139Draw line segment from (x0, y0) to (x1, y1) using Clip, Matrix, and Paint paint.
3140In paint: Paint_Stroke_Width describes the line thickness; Paint_Stroke_Cap draws the end rounded or square;
3141Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
3142
3143#Param x0 Start of line segment on x-axis. ##
3144#Param y0 Start of line segment on y-axis. ##
3145#Param x1 End of line segment on x-axis. ##
3146#Param y1 End of line segment on y-axis. ##
3147#Param paint Stroke, blend, color, and so on, used to draw. ##
3148
3149#Example
3150 SkPaint paint;
3151 paint.setAntiAlias(true);
3152 paint.setColor(0xFF9a67be);
3153 paint.setStrokeWidth(20);
3154 canvas->skew(1, 0);
3155 canvas->drawLine(32, 96, 32, 160, paint);
3156 canvas->skew(-2, 0);
3157 canvas->drawLine(288, 96, 288, 160, paint);
3158##
3159
3160#ToDo incomplete ##
3161
3162##
3163
3164# ------------------------------------------------------------------------------
3165
3166#Method void drawRect(const SkRect& rect, const SkPaint& paint)
3167
3168Draw Rect rect using Clip, Matrix, and Paint paint.
3169In paint: Paint_Style determines if rectangle is stroked or filled;
3170if stroked, Paint_Stroke_Width describes the line thickness, and
3171Paint_Stroke_Join draws the corners rounded or square.
3172
3173#Param rect The rectangle to be drawn. ##
3174#Param paint Stroke or fill, blend, color, and so on, used to draw. ##
3175
3176#Example
3177void draw(SkCanvas* canvas) {
3178 SkPoint rectPts[] = { {64, 48}, {192, 160} };
3179 SkPaint paint;
3180 paint.setAntiAlias(true);
3181 paint.setStyle(SkPaint::kStroke_Style);
3182 paint.setStrokeWidth(20);
3183 paint.setStrokeJoin(SkPaint::kRound_Join);
3184 SkMatrix rotator;
3185 rotator.setRotate(30, 128, 128);
3186 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3187 paint.setColor(color);
3188 SkRect rect;
3189 rect.set(rectPts[0], rectPts[1]);
3190 canvas->drawRect(rect, paint);
3191 rotator.mapPoints(rectPts, 2);
3192 }
3193}
3194##
3195
3196#ToDo incomplete ##
3197
3198##
3199
3200# ------------------------------------------------------------------------------
3201
3202#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
3203
3204Draw IRect rect using Clip, Matrix, and Paint paint.
3205In paint: Paint_Style determines if rectangle is stroked or filled;
3206if stroked, Paint_Stroke_Width describes the line thickness, and
3207Paint_Stroke_Join draws the corners rounded or square.
3208
3209#Param rect The rectangle to be drawn. ##
3210#Param paint Stroke or fill, blend, color, and so on, used to draw. ##
3211
3212#Example
3213 SkIRect rect = { 64, 48, 192, 160 };
3214 SkPaint paint;
3215 paint.setAntiAlias(true);
3216 paint.setStyle(SkPaint::kStroke_Style);
3217 paint.setStrokeWidth(20);
3218 paint.setStrokeJoin(SkPaint::kRound_Join);
3219 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
3220 paint.setColor(color);
3221 canvas->drawIRect(rect, paint);
3222 canvas->rotate(30, 128, 128);
3223 }
3224##
3225
3226#ToDo incomplete ##
3227
3228##
3229
3230# ------------------------------------------------------------------------------
3231
3232#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
3233
3234Draw Region region using Clip, Matrix, and Paint paint.
3235In paint: Paint_Style determines if rectangle is stroked or filled;
3236if stroked, Paint_Stroke_Width describes the line thickness, and
3237Paint_Stroke_Join draws the corners rounded or square.
3238
3239#Param region The region to be drawn. ##
3240#Param paint Paint stroke or fill, blend, color, and so on, used to draw. ##
3241
3242#Example
3243void draw(SkCanvas* canvas) {
3244 SkRegion region;
3245 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
3246 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
3247 SkPaint paint;
3248 paint.setAntiAlias(true);
3249 paint.setStyle(SkPaint::kStroke_Style);
3250 paint.setStrokeWidth(20);
3251 paint.setStrokeJoin(SkPaint::kRound_Join);
3252 canvas->drawRegion(region, paint);
3253}
3254##
3255
3256#ToDo incomplete ##
3257
3258##
3259
3260# ------------------------------------------------------------------------------
3261
3262#Method void drawOval(const SkRect& oval, const SkPaint& paint)
3263
3264Draw Oval oval using Clip, Matrix, and Paint.
3265In paint: Paint_Style determines if Oval is stroked or filled;
3266if stroked, Paint_Stroke_Width describes the line thickness.
3267
3268#Param oval Rect bounds of Oval. ##
3269#Param paint Paint stroke or fill, blend, color, and so on, used to draw. ##
3270
3271#Example
3272void draw(SkCanvas* canvas) {
3273 canvas->clear(0xFF3f5f9f);
3274 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
3275 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
3276 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
3277 SkScalar pos[] = { 0.2f, 1.0f };
3278 SkRect bounds = SkRect::MakeWH(80, 70);
3279 SkPaint paint;
3280 paint.setAntiAlias(true);
3281 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
3282 SkShader::kClamp_TileMode));
3283 canvas->drawOval(bounds , paint);
3284}
3285##
3286
3287#ToDo incomplete ##
3288
3289##
3290
3291# ------------------------------------------------------------------------------
3292
3293#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
3294
3295Draw Round_Rect rrect using Clip, Matrix, and Paint paint.
3296In paint: Paint_Style determines if rrect is stroked or filled;
3297if stroked, Paint_Stroke_Width describes the line thickness.
3298
3299rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or may have
3300any combination of positive non-square radii for the four corners.
3301
3302#Param rrect Round_Rect with up to eight corner radii to draw. ##
3303#Param paint Paint stroke or fill, blend, color, and so on, used to draw. ##
3304
3305#Example
3306void draw(SkCanvas* canvas) {
3307 SkPaint paint;
3308 paint.setAntiAlias(true);
3309 SkRect outer = {30, 40, 210, 220};
3310 SkRect radii = {30, 50, 70, 90 };
3311 SkRRect rRect;
3312 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
3313 canvas->drawRRect(rRect, paint);
3314 paint.setColor(SK_ColorWHITE);
3315 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
3316 outer.fLeft + radii.fLeft, outer.fBottom, paint);
3317 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
3318 outer.fRight - radii.fRight, outer.fBottom, paint);
3319 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
3320 outer.fRight, outer.fTop + radii.fTop, paint);
3321 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
3322 outer.fRight, outer.fBottom - radii.fBottom, paint);
3323}
3324##
3325
3326#ToDo incomplete ##
3327
3328##
3329
3330# ------------------------------------------------------------------------------
3331
3332#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
3333
3334Draw Round_Rect outer and inner
3335using Clip, Matrix, and Paint paint.
3336outer must contain inner or the drawing is undefined.
3337In paint: Paint_Style determines if rrect is stroked or filled;
3338if stroked, Paint_Stroke_Width describes the line thickness.
3339If stroked and Round_Rect corner has zero length radii, Paint_Stroke_Join can draw
3340corners rounded or square.
3341
3342GPU-backed platforms take advantage of drawDRRect since both outer and inner are
3343concave and outer contains inner. These platforms may not be able to draw
3344Path built with identical data as fast.
3345
3346#Param outer Round_Rect outer bounds to draw. ##
3347#Param inner Round_Rect inner bounds to draw. ##
3348#Param paint Paint stroke or fill, blend, color, and so on, used to draw. ##
3349
3350#Example
3351void draw(SkCanvas* canvas) {
3352 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3353 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
3354 SkPaint paint;
3355 canvas->drawDRRect(outer, inner, paint);
3356}
3357##
3358
3359#Example
3360#Description
3361 Outer Rect has no corner radii, but stroke join is rounded.
3362 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
3363 Stroke join does not affect inner Round_Rect since it has no sharp corners.
3364##
3365void draw(SkCanvas* canvas) {
3366 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
3367 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
3368 SkPaint paint;
3369 paint.setAntiAlias(true);
3370 paint.setStyle(SkPaint::kStroke_Style);
3371 paint.setStrokeWidth(20);
3372 paint.setStrokeJoin(SkPaint::kRound_Join);
3373 canvas->drawDRRect(outer, inner, paint);
3374 paint.setStrokeWidth(1);
3375 paint.setColor(SK_ColorWHITE);
3376 canvas->drawDRRect(outer, inner, paint);
3377}
3378##
3379
3380#ToDo incomplete ##
3381
3382##
3383
3384# ------------------------------------------------------------------------------
3385
3386#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
3387
3388Draw Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint.
3389If radius is zero or less, nothing is drawn.
3390In paint: Paint_Style determines if Circle is stroked or filled;
3391if stroked, Paint_Stroke_Width describes the line thickness.
3392
3393#Param cx Circle center on the x-axis. ##
3394#Param cy Circle center on the y-axis. ##
3395#Param radius Half the diameter of Circle. ##
3396#Param paint Paint stroke or fill, blend, color, and so on, used to draw. ##
3397
3398#Example
3399 void draw(SkCanvas* canvas) {
3400 SkPaint paint;
3401 paint.setAntiAlias(true);
3402 canvas->drawCircle(128, 128, 90, paint);
3403 paint.setColor(SK_ColorWHITE);
3404 canvas->drawCircle(86, 86, 20, paint);
3405 canvas->drawCircle(160, 76, 20, paint);
3406 canvas->drawCircle(140, 150, 35, paint);
3407 }
3408##
3409
3410#ToDo incomplete ##
3411
3412##
3413
3414# ------------------------------------------------------------------------------
3415
3416#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
3417 bool useCenter, const SkPaint& paint)
3418
3419Draw Arc using Clip, Matrix, and Paint paint.
3420Arc is part of Oval bounded by oval, sweeping from startAngle to startAngle plus
3421sweepAngle. startAngle and sweepAngle are in degrees.
3422startAngle of zero places start point at the right middle edge of oval.
3423A positive sweepAngle places Arc end point clockwise from start point;
3424a negative sweepAngle places Arc end point counterclockwise from start point.
3425sweepAngle may exceed 360 degrees, a full circle.
3426If useCenter is true, draw a wedge that includes lines from oval
3427center to Arc end points. If useCenter is false, draw Arc between end points.
3428
3429If Rect oval is empty or sweepAngle is zero, nothing is drawn.
3430
3431#Param oval Rect bounds of Oval containing Arc to draw. ##
3432#Param startAngle Angle in degrees where Arc begins. ##
3433#Param sweepAngle Sweep angle in degrees; positive is clockwise. ##
3434#Param useCenter If true include the center of the oval. ##
3435#Param paint Paint stroke or fill, blend, color, and so on, used to draw. ##
3436
3437#Example
3438 void draw(SkCanvas* canvas) {
3439 SkPaint paint;
3440 paint.setAntiAlias(true);
3441 SkRect oval = { 4, 4, 60, 60};
3442 for (auto useCenter : { false, true } ) {
3443 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
3444 paint.setStyle(style);
3445 for (auto degrees : { 45, 90, 180, 360} ) {
3446 canvas->drawArc(oval, 0, degrees , useCenter, paint);
3447 canvas->translate(64, 0);
3448 }
3449 canvas->translate(-256, 64);
3450 }
3451 }
3452 }
3453##
3454
3455#Example
3456#Height 64
3457 void draw(SkCanvas* canvas) {
3458 SkPaint paint;
3459 paint.setAntiAlias(true);
3460 paint.setStyle(SkPaint::kStroke_Style);
3461 paint.setStrokeWidth(4);
3462 SkRect oval = { 4, 4, 60, 60};
3463 float intervals[] = { 5, 5 };
3464 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
3465 for (auto degrees : { 270, 360, 540, 720 } ) {
3466 canvas->drawArc(oval, 0, degrees, false, paint);
3467 canvas->translate(64, 0);
3468 }
3469 }
3470##
3471
3472#ToDo incomplete ##
3473
3474##
3475
3476# ------------------------------------------------------------------------------
3477
3478#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
3479
3480Draw Round_Rect bounded by Rect rect, with corner radii (rx, ry) using Clip, Matrix,
3481and Paint paint.
3482In paint: Paint_Style determines if Round_Rect is stroked or filled;
3483if stroked, Paint_Stroke_Width describes the line thickness.
3484If rx or ry are less than zero, they are treated as if they are zero.
3485If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
3486If rx and ry are zero, Round_Rect is drawn as Rect and if stroked is affected by Paint_Stroke_Join.
3487
3488#Param rect Rect bounds of Round_Rect to draw. ##
3489#Param rx Semiaxis length in x of oval describing rounded corners. ##
3490#Param ry Semiaxis length in y of oval describing rounded corners. ##
3491#Param paint Stroke, blend, color, and so on, used to draw. ##
3492
3493#Example
3494#Description
3495 Top row has a zero radius a generates a rectangle.
3496 Second row radii sum to less than sides.
3497 Third row radii sum equals sides.
3498 Fourth row radii sum exceeds sides; radii are scaled to fit.
3499##
3500 void draw(SkCanvas* canvas) {
3501 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
3502 SkPaint paint;
3503 paint.setStrokeWidth(15);
3504 paint.setStrokeJoin(SkPaint::kRound_Join);
3505 paint.setAntiAlias(true);
3506 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
3507 paint.setStyle(style );
3508 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
3509 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
3510 canvas->translate(0, 60);
3511 }
3512 canvas->translate(80, -240);
3513 }
3514 }
3515##
3516
3517#ToDo incomplete ##
3518
3519##
3520
3521# ------------------------------------------------------------------------------
3522
3523#Method void drawPath(const SkPath& path, const SkPaint& paint)
3524
3525Draw Path path using Clip, Matrix, and Paint paint.
3526Path contains an array of Path_Contour, each of which may be open or closed.
3527
3528In paint: Paint_Style determines if Round_Rect is stroked or filled:
3529if filled, Path_Fill_Type determines whether Path_Contour describes inside or outside of fill;
3530if stroked, Paint_Stroke_Width describes the line thickness, Paint_Stroke_Cap describes line ends,
3531and Paint_Stroke_Join describes how corners are drawn.
3532
3533#Param path Path to draw. ##
3534#Param paint Stroke, blend, color, and so on, used to draw. ##
3535
3536#Example
3537#Description
3538 Top rows draw stroked path with combinations of joins and caps. The open contour
3539 is affected by caps; the closed contour is affected by joins.
3540 Bottom row draws fill the same for open and closed contour.
3541 First bottom column shows winding fills overlap.
3542 Second bottom column shows even odd fills exclude overlap.
3543 Third bottom column shows inverse winding fills area outside both contours.
3544##
3545void draw(SkCanvas* canvas) {
3546 SkPath path;
3547 path.moveTo(20, 20);
3548 path.quadTo(60, 20, 60, 60);
3549 path.close();
3550 path.moveTo(60, 20);
3551 path.quadTo(60, 60, 20, 60);
3552 SkPaint paint;
3553 paint.setStrokeWidth(10);
3554 paint.setAntiAlias(true);
3555 paint.setStyle(SkPaint::kStroke_Style);
3556 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
3557 paint.setStrokeJoin(join);
3558 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
3559 paint.setStrokeCap(cap);
3560 canvas->drawPath(path, paint);
3561 canvas->translate(80, 0);
3562 }
3563 canvas->translate(-240, 60);
3564 }
3565 paint.setStyle(SkPaint::kFill_Style);
3566 for (auto fill : { SkPath::kWinding_FillType,
3567 SkPath::kEvenOdd_FillType,
3568 SkPath::kInverseWinding_FillType } ) {
3569 path.setFillType(fill);
3570 canvas->save();
3571 canvas->clipRect({0, 10, 80, 70});
3572 canvas->drawPath(path, paint);
3573 canvas->restore();
3574 canvas->translate(80, 0);
3575 }
3576}
3577##
3578
3579#ToDo incomplete ##
3580
3581##
3582
3583# ------------------------------------------------------------------------------
3584#Topic Draw_Image
3585
3586drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or a smart pointer as a convenience.
3587The pairs of calls are otherwise identical.
3588
3589
3590#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL)
3591
3592Draw Image image, with its top-left corner at (left, top),
3593using Clip, Matrix, and optional Paint paint.
3594
3595If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3596If image is kAlpha_8_SkColorType, apply Shader.
3597if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3598beyond image bounds, replicate image edge colors, just as Shader made from
3599SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3600color when it samples outside of its bounds.
3601
3602#Param image Uncompressed rectangular map of pixels. ##
3603#Param left Left side of image. ##
3604#Param top Top side of image. ##
3605#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3606
3607#Example
3608#Height 64
3609#Image 4
3610void draw(SkCanvas* canvas) {
3611 // sk_sp<SkImage> image;
3612 SkImage* imagePtr = image.get();
3613 canvas->drawImage(imagePtr, 0, 0);
3614 SkPaint paint;
3615 canvas->drawImage(imagePtr, 80, 0, &paint);
3616 paint.setAlpha(0x80);
3617 canvas->drawImage(imagePtr, 160, 0, &paint);
3618}
3619##
3620
3621#ToDo incomplete ##
3622
3623##
3624
3625# ------------------------------------------------------------------------------
3626
3627#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
3628 const SkPaint* paint = NULL)
3629
3630Draw Image image, with its top-left corner at (left, top),
3631using Clip, Matrix, and optional Paint paint.
3632
3633If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3634If image is kAlpha_8_SkColorType, apply Shader.
3635if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3636beyond image bounds, replicate image edge colors, just as Shader made from
3637SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3638color when it samples outside of its bounds.
3639
3640#Param image Uncompressed rectangular map of pixels. ##
3641#Param left Left side of image. ##
3642#Param top Top side of image. ##
3643#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3644
3645#Example
3646#Height 64
3647#Image 4
3648void draw(SkCanvas* canvas) {
3649 // sk_sp<SkImage> image;
3650 canvas->drawImage(image, 0, 0);
3651 SkPaint paint;
3652 canvas->drawImage(image, 80, 0, &paint);
3653 paint.setAlpha(0x80);
3654 canvas->drawImage(image, 160, 0, &paint);
3655}
3656##
3657
3658#ToDo incomplete ##
3659
3660##
3661
3662# ------------------------------------------------------------------------------
3663
3664#Enum SrcRectConstraint
3665
3666#Code
3667 enum SrcRectConstraint {
3668 kStrict_SrcRectConstraint,
3669 kFast_SrcRectConstraint,
3670 };
3671##
3672
3673SrcRectConstraint controls the behavior at the edge of the Rect src, provided to drawImageRect,
3674trading off speed for precision.
3675
3676Image_Filter in Paint may sample multiple pixels in the image.
3677Rect src restricts the bounds of pixels that may be read. Image_Filter may slow
3678down if it cannot read outside the bounds, when sampling near the edge of Rect src.
3679SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
3680outside Rect src.
3681
3682#Const kStrict_SrcRectConstraint
3683 Requires Image_Filter to respect Rect src,
3684 sampling only inside of its bounds, possibly with a performance penalty.
3685##
3686
3687#Const kFast_SrcRectConstraint
3688 Permits Image_Filter to sample outside of Rect src
3689 by half the width of Image_Filter, permitting it to run faster but with
3690 error at the image edges.
3691##
3692
3693#Example
3694#Height 64
3695#Description
3696 redBorder contains a black and white checkerboard bordered by red.
3697 redBorder is drawn scaled by 16 on the left.
3698 The middle and right bitmaps are filtered checkboards.
3699 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3700 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3701##
3702void draw(SkCanvas* canvas) {
3703 SkBitmap redBorder;
3704 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3705 SkCanvas checkRed(redBorder);
3706 checkRed.clear(SK_ColorRED);
3707 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3708 { SK_ColorWHITE, SK_ColorBLACK } };
3709 checkRed.writePixels(
3710 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3711 canvas->scale(16, 16);
3712 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3713 canvas->resetMatrix();
3714 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3715 SkPaint lowPaint;
3716 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3717 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3718 SkCanvas::kFast_SrcRectConstraint } ) {
3719 canvas->translate(80, 0);
3720 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3721 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3722 }
3723}
3724##
3725
3726#ToDo incomplete ##
3727
3728##
3729
3730# ------------------------------------------------------------------------------
3731
3732#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3733 const SkPaint* paint,
3734 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3735
3736Draw Rect src of Image image, scaled and translated to fill Rect dst.
3737Additionally transform draw using Clip, Matrix, and optional Paint paint.
3738If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3739If image is kAlpha_8_SkColorType, apply Shader.
3740if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3741beyond image bounds, replicate image edge colors, just as Shader made from
3742SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3743color when it samples outside of its bounds.
3744constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
3745set to kFast_SrcRectConstraint allows sampling outside to improve performance.
3746
3747#Param image Image containing pixels, dimensions, and format. ##
3748#Param src Source Rect of image to draw from. ##
3749#Param dst Destination Rect of image to draw to. ##
3750#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3751#Param constraint Filter strictly within src or draw faster. ##
3752
3753#Example
3754#Height 64
3755#Description
3756 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
3757 its bounds; there's no bleeding with kFast_SrcRectConstraint.
3758 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3759 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3760 with kFast_SrcRectConstraint red bleeds on the edges.
3761##
3762void draw(SkCanvas* canvas) {
3763 uint32_t pixels[][4] = {
3764 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
3765 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
3766 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
3767 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
3768 SkBitmap redBorder;
3769 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
3770 (void*) pixels, sizeof(pixels[0]));
3771 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3772 SkPaint lowPaint;
3773 for (auto constraint : {
3774 SkCanvas::kFast_SrcRectConstraint,
3775 SkCanvas::kStrict_SrcRectConstraint,
3776 SkCanvas::kFast_SrcRectConstraint } ) {
3777 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3778 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3779 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3780 canvas->translate(80, 0);
3781 }
3782}
3783##
3784
3785#ToDo incomplete ##
3786
3787##
3788
3789# ------------------------------------------------------------------------------
3790
3791#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
3792 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3793
3794Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
3795Note that isrc is on integer pixel boundaries; dst may include fractional boundaries.
3796Additionally transform draw using Clip, Matrix, and optional Paint paint.
3797If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3798If image is kAlpha_8_SkColorType, apply Shader.
3799if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3800beyond image bounds, replicate image edge colors, just as Shader made from
3801SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3802color when it samples outside of its bounds.
3803constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
3804set to kFast_SrcRectConstraint allows sampling outside to improve performance.
3805
3806#Param image Image containing pixels, dimensions, and format. ##
3807#Param isrc Source IRect of image to draw from. ##
3808#Param dst Destination Rect of image to draw to. ##
3809#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3810#Param constraint Filter strictly within src or draw faster. ##
3811
3812#Example
3813#Image 4
3814void draw(SkCanvas* canvas) {
3815 // sk_sp<SkImage> image;
3816 for (auto i : { 1, 2, 4, 8 } ) {
3817 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
3818 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
3819 }
3820}
3821##
3822
3823#ToDo incomplete ##
3824
3825##
3826
3827# ------------------------------------------------------------------------------
3828
3829#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
3830 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3831
3832Draw Image image, scaled and translated to fill Rect dst,
3833using Clip, Matrix, and optional Paint paint.
3834If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3835If image is kAlpha_8_SkColorType, apply Shader.
3836if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3837beyond image bounds, replicate image edge colors, just as Shader made from
3838SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3839color when it samples outside of its bounds.
3840Use constaint to choose kStrict_SrcRectConstraint or kFast_SrcRectConstraint.
3841
3842#Param image Image containing pixels, dimensions, and format. ##
3843#Param dst Destination Rect of image to draw to. ##
3844#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3845#Param constraint Filter strictly within src or draw faster. ##
3846
3847#Example
3848#Image 4
3849void draw(SkCanvas* canvas) {
3850 // sk_sp<SkImage> image;
3851 for (auto i : { 20, 40, 80, 160 } ) {
3852 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
3853 }
3854}
3855##
3856
3857#ToDo incomplete ##
3858
3859##
3860
3861# ------------------------------------------------------------------------------
3862
3863#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
3864 const SkPaint* paint,
3865 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3866
3867Draw Rect src of Image image, scaled and translated to fill Rect dst.
3868Additionally transform draw using Clip, Matrix, and optional Paint paint.
3869If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3870If image is kAlpha_8_SkColorType, apply Shader.
3871if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3872beyond image bounds, replicate image edge colors, just as Shader made from
3873SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3874color when it samples outside of its bounds.
3875constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
3876set to kFast_SrcRectConstraint allows sampling outside to improve performance.
3877
3878#Param image Image containing pixels, dimensions, and format. ##
3879#Param src Source Rect of image to draw from. ##
3880#Param dst Destination Rect of image to draw to. ##
3881#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3882#Param constraint Filter strictly within src or draw faster. ##
3883
3884#Example
3885#Height 64
3886#Description
3887 Canvas scales and translates; transformation from src to dst also scales.
3888 The two matrices are concatenated to create the final transformation.
3889##
3890void draw(SkCanvas* canvas) {
3891 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3892 { SK_ColorWHITE, SK_ColorBLACK } };
3893 SkBitmap bitmap;
3894 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
3895 (void*) pixels, sizeof(pixels[0]));
3896 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3897 SkPaint paint;
3898 canvas->scale(4, 4);
3899 for (auto alpha : { 50, 100, 150, 255 } ) {
3900 paint.setAlpha(alpha);
3901 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3902 canvas->translate(8, 0);
3903 }
3904}
3905##
3906
3907#ToDo incomplete ##
3908
3909##
3910
3911# ------------------------------------------------------------------------------
3912
3913#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
3914 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3915
3916Draw IRect isrc of Image image, scaled and translated to fill Rect dst.
3917Note that isrc is on integer pixel boundaries; dst may include fractional boundaries.
3918Additionally transform draw using Clip, Matrix, and optional Paint paint.
3919If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3920If image is kAlpha_8_SkColorType, apply Shader.
3921if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3922beyond image bounds, replicate image edge colors, just as Shader made from
3923SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the image's edge
3924color when it samples outside of its bounds.
3925cons set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
3926set to kFast_SrcRectConstraint allows sampling outside to improve performance.
3927
3928#Param image Image containing pixels, dimensions, and format. ##
3929#Param isrc Source IRect of image to draw from. ##
3930#Param dst Destination Rect of image to draw to. ##
3931#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3932#Param constraint Filter strictly within src or draw faster. ##
3933
3934#Example
3935#Height 64
3936void draw(SkCanvas* canvas) {
3937 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
3938 { 0xAAAAAAAA, 0xFFFFFFFF} };
3939 SkBitmap bitmap;
3940 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
3941 (void*) pixels, sizeof(pixels[0]));
3942 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3943 SkPaint paint;
3944 canvas->scale(4, 4);
3945 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3946 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3947 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3948 canvas->translate(8, 0);
3949 }
3950}
3951##
3952
3953#ToDo incomplete ##
3954##
3955
3956# ------------------------------------------------------------------------------
3957
3958#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
3959 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
3960
3961Draw Image image, scaled and translated to fill Rect dst,
3962using Clip, Matrix, and optional Paint paint.
3963If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
3964If image is kAlpha_8_SkColorType, apply Shader.
3965if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
3966beyond image bounds, replicate image edge colors, just as Shader made from
3967SkImage::makeShader with SkShader::kClamp_TileMode set replicates the image's edge
3968color when it samples outside of its bounds.
3969constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
3970set to kFast_SrcRectConstraint allows sampling outside to improve performance.
3971
3972#Param image Image containing pixels, dimensions, and format. ##
3973#Param dst Destination Rect of image to draw to. ##
3974#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
3975#Param constraint Filter strictly within src or draw faster. ##
3976
3977#Example
3978#Height 64
3979void draw(SkCanvas* canvas) {
3980 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3981 { 0xAAAA0000, 0xFFFF0000} };
3982 SkBitmap bitmap;
3983 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
3984 (void*) pixels, sizeof(pixels[0]));
3985 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3986 SkPaint paint;
3987 canvas->scale(4, 4);
3988 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3989 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3990 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
3991 canvas->translate(8, 0);
3992 }
3993}
3994##
3995
3996#ToDo incomplete ##
3997
3998##
3999
4000# ------------------------------------------------------------------------------
4001
4002#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
4003 const SkPaint* paint = nullptr)
4004
4005Draw Image image stretched differentially to fit into Rect dst.
4006IRect center divides the image into nine sections: four sides, four corners, and the center.
4007corners are unscaled or scaled down proportionately if their sides are larger than dst;
4008center and four sides are scaled to fit remaining space, if any.
4009Additionally transform draw using Clip, Matrix, and optional Paint paint.
4010If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4011If image is kAlpha_8_SkColorType, apply Shader.
4012if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
4013beyond image bounds, replicate image edge colors, just as Shader made from
4014SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the image's edge
4015color when it samples outside of its bounds.
4016
4017#Param image Image containing pixels, dimensions, and format. ##
4018#Param center IRect edge of image corners and sides. ##
4019#Param dst Destination Rect of image to draw to. ##
4020#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4021
4022#Example
4023#Height 128
4024#Description
4025 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
4026 The second image equals the size of center; only corners are drawn, unscaled.
4027 The remaining images are larger than center. All corners draw unscaled. The sides
4028 and center are scaled if needed to take up the remaining space.
4029##
4030void draw(SkCanvas* canvas) {
4031 SkIRect center = { 20, 10, 50, 40 };
4032 SkBitmap bitmap;
4033 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4034 SkCanvas bitCanvas(bitmap);
4035 SkPaint paint;
4036 SkColor gray = 0xFF000000;
4037 int left = 0;
4038 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4039 int top = 0;
4040 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4041 paint.setColor(gray);
4042 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4043 gray += 0x001f1f1f;
4044 top = bottom;
4045 }
4046 left = right;
4047 }
4048 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4049 SkImage* imagePtr = image.get();
4050 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4051 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4052 canvas->translate(dest + 4, 0);
4053 }
4054}
4055##
4056
4057#ToDo incomplete ##
4058
4059##
4060
4061# ------------------------------------------------------------------------------
4062
4063#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
4064 const SkPaint* paint = nullptr)
4065
4066Draw Image image stretched differentially to fit into Rect dst.
4067IRect center divides the image into nine sections: four sides, four corners, and the center.
4068corners are unscaled or scaled down proportionately if their sides are larger than dst;
4069center and four sides are scaled to fit remaining space, if any.
4070Additionally transform draw using Clip, Matrix, and optional Paint paint.
4071If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4072If image is kAlpha_8_SkColorType, apply Shader.
4073if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
4074beyond image bounds, replicate image edge colors, just as Shader made from
4075SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the image's edge
4076color when it samples outside of its bounds.
4077
4078#Param image Image containing pixels, dimensions, and format. ##
4079#Param center IRect edge of image corners and sides. ##
4080#Param dst Destination Rect of image to draw to. ##
4081#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4082
4083#Example
4084#Height 128
4085#Description
4086 The two leftmost images has four corners and sides to the left and right of center.
4087 The leftmost image scales the width of corners proportionately to fit.
4088 The third and fourth image corners are unscaled; the sides and center are scaled to
4089 fill the remaining space.
4090 The rightmost image has four corners scaled vertically to fit, and uses sides above
4091 and below center to fill the remaining space.
4092##
4093void draw(SkCanvas* canvas) {
4094 SkIRect center = { 20, 10, 50, 40 };
4095 SkBitmap bitmap;
4096 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4097 SkCanvas bitCanvas(bitmap);
4098 SkPaint paint;
4099 SkColor gray = 0xFF000000;
4100 int left = 0;
4101 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4102 int top = 0;
4103 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4104 paint.setColor(gray);
4105 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4106 gray += 0x001f1f1f;
4107 top = bottom;
4108 }
4109 left = right;
4110 }
4111 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4112 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4113 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4114 canvas->translate(dest + 4, 0);
4115 }
4116}
4117##
4118
4119#ToDo incomplete ##
4120
4121##
4122
4123# ------------------------------------------------------------------------------
4124
4125#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
4126 const SkPaint* paint = NULL)
4127
4128Draw Bitmap bitmap, with its top-left corner at (left, top),
4129using Clip, Matrix, and optional Paint paint.
4130If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4131If bitmap is kAlpha_8_SkColorType, apply Shader.
4132if paint contains Mask_Filter, generate mask from bitmap bounds. If generated mask extends
4133beyond bitmap bounds, replicate bitmap edge colors, just as Shader made from
4134SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the bitmap's edge
4135color when it samples outside of its bounds.
4136
4137#Param bitmap Bitmap containing pixels, dimensions, and format. ##
4138#Param left Left side of bitmap. ##
4139#Param top Top side of bitmap. ##
4140#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4141
4142#Example
4143#Height 64
4144void draw(SkCanvas* canvas) {
4145 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4146 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4147 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4148 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4149 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4150 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4151 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
4152 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
4153 SkBitmap bitmap;
4154 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4155 (void*) pixels, sizeof(pixels[0]));
4156 SkPaint paint;
4157 canvas->scale(4, 4);
4158 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4159 paint.setColor(color);
4160 canvas->drawBitmap(bitmap, 0, 0, &paint);
4161 canvas->translate(12, 0);
4162 }
4163}
4164##
4165
4166#ToDo incomplete ##
4167
4168##
4169
4170# ------------------------------------------------------------------------------
4171
4172#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
4173 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4174
4175Draw Rect src of Bitmap bitmap, scaled and translated to fill Rect dst.
4176Additionally transform draw using Clip, Matrix, and optional Paint paint.
4177If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4178If bitmap is kAlpha_8_SkColorType, apply Shader.
4179if paint contains Mask_Filter, generate mask from bitmap bounds. If generated mask extends
4180beyond bitmap bounds, replicate bitmap edge colors, just as Shader made from
4181SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the bitmap's edge
4182color when it samples outside of its bounds.
4183constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
4184set to kFast_SrcRectConstraint allows sampling outside to improve performance.
4185
4186#Param bitmap Bitmap containing pixels, dimensions, and format. ##
4187#Param src Source Rect of image to draw from. ##
4188#Param dst Destination Rect of image to draw to. ##
4189#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4190#Param constraint Filter strictly within src or draw faster. ##
4191
4192#Example
4193#Height 64
4194void draw(SkCanvas* canvas) {
4195 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
4196 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4197 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
4198 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
4199 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
4200 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
4201 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4202 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
4203 SkBitmap bitmap;
4204 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4205 (void*) pixels, sizeof(pixels[0]));
4206 SkPaint paint;
4207 paint.setMaskFilter(SkBlurMaskFilter::Make(kSolid_SkBlurStyle, 6));
4208 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
4209 paint.setColor(color);
4210 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4211 canvas->translate(48, 0);
4212 }
4213}
4214##
4215
4216#ToDo incomplete ##
4217
4218##
4219
4220# ------------------------------------------------------------------------------
4221
4222#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
4223 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4224
4225Draw IRect isrc of Bitmap bitmap, scaled and translated to fill Rect dst.
4226Note that isrc is on integer pixel boundaries; dst may include fractional boundaries.
4227Additionally transform draw using Clip, Matrix, and optional Paint paint.
4228If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4229If bitmap is kAlpha_8_SkColorType, apply Shader.
4230if paint contains Mask_Filter, generate mask from bitmap bounds. If generated mask extends
4231beyond bitmap bounds, replicate bitmap edge colors, just as Shader made from
4232SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the bitmap's edge
4233color when it samples outside of its bounds.
4234constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
4235set to kFast_SrcRectConstraint allows sampling outside to improve performance.
4236
4237#Param bitmap Bitmap containing pixels, dimensions, and format. ##
4238#Param isrc Source IRect of image to draw from. ##
4239#Param dst Destination Rect of image to draw to. ##
4240#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4241#Param constraint Filter strictly within src or draw faster. ##
4242
4243#Example
4244#Height 64
4245void draw(SkCanvas* canvas) {
4246 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
4247 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4248 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4249 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
4250 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
4251 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
4252 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
4253 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
4254 SkBitmap bitmap;
4255 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
4256 (void*) pixels, sizeof(pixels[0]));
4257 SkPaint paint;
4258 paint.setFilterQuality(kHigh_SkFilterQuality);
4259 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
4260 paint.setColor(color);
4261 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
4262 canvas->translate(48.25f, 0);
4263 }
4264}
4265##
4266
4267#ToDo incomplete ##
4268
4269##
4270
4271# ------------------------------------------------------------------------------
4272
4273#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
4274 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
4275
4276Draw Bitmap bitmap, scaled and translated to fill Rect dst.
4277Note that isrc is on integer pixel boundaries; dst may include fractional boundaries.
4278Additionally transform draw using Clip, Matrix, and optional Paint paint.
4279If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4280If bitmap is kAlpha_8_SkColorType, apply Shader.
4281if paint contains Mask_Filter, generate mask from bitmap bounds. If generated mask extends
4282beyond bitmap bounds, replicate bitmap edge colors, just as Shader made from
4283SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the bitmap's edge
4284color when it samples outside of its bounds.
4285constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to sample within src;
4286set to kFast_SrcRectConstraint allows sampling outside to improve performance.
4287
4288#Param bitmap Bitmap containing pixels, dimensions, and format. ##
4289#Param dst Destination Rect of image to draw to. ##
4290#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4291#Param constraint Filter strictly within src or draw faster. ##
4292
4293#Example
4294#Height 64
4295void draw(SkCanvas* canvas) {
4296 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
4297 { 0xAAAA0000, 0xFFFF0000} };
4298 SkBitmap bitmap;
4299 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
4300 (void*) pixels, sizeof(pixels[0]));
4301 SkPaint paint;
4302 canvas->scale(4, 4);
4303 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
4304 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
4305 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
4306 canvas->translate(8, 0);
4307 }
4308}
4309##
4310
4311#ToDo incomplete ##
4312
4313##
4314
4315# ------------------------------------------------------------------------------
4316
4317#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
4318 const SkPaint* paint = NULL)
4319
4320Draw Bitmap bitmap stretched differentially to fit into Rect dst.
4321IRect center divides the bitmap into nine sections: four sides, four corners, and the center.
4322corners are unscaled or scaled down proportionately if their sides are larger than dst;
4323center and four sides are scaled to fit remaining space, if any.
4324Additionally transform draw using Clip, Matrix, and optional Paint paint.
4325If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4326If bitmap is kAlpha_8_SkColorType, apply Shader.
4327if paint contains Mask_Filter, generate mask from bitmap bounds. If generated mask extends
4328beyond bitmap bounds, replicate bitmap edge colors, just as Shader made from
4329SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the bitmap's edge
4330color when it samples outside of its bounds.
4331
4332#Param bitmap Bitmap containing pixels, dimensions, and format. ##
4333#Param center IRect edge of image corners and sides. ##
4334#Param dst Destination Rect of image to draw to. ##
4335#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4336
4337#Example
4338#Height 128
4339#Description
4340 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4341 The leftmost bitmap draw scales the width of corners proportionately to fit.
4342 The third and fourth draw corners are unscaled; the sides and center are scaled to
4343 fill the remaining space.
4344 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4345 and below center to fill the remaining space.
4346##
4347void draw(SkCanvas* canvas) {
4348 SkIRect center = { 20, 10, 50, 40 };
4349 SkBitmap bitmap;
4350 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4351 SkCanvas bitCanvas(bitmap);
4352 SkPaint paint;
4353 SkColor gray = 0xFF000000;
4354 int left = 0;
4355 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4356 int top = 0;
4357 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4358 paint.setColor(gray);
4359 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4360 gray += 0x001f1f1f;
4361 top = bottom;
4362 }
4363 left = right;
4364 }
4365 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4366 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
4367 canvas->translate(dest + 4, 0);
4368 }
4369}
4370##
4371
4372#ToDo incomplete ##
4373
4374##
4375
4376# ------------------------------------------------------------------------------
4377#Struct Lattice
4378
4379 Lattice divides Bitmap or Image into a rectangular grid.
4380 Grid entries on even columns and even rows are fixed; these entries are
4381 always drawn at their original size if the destination is large enough.
4382 If the destination side is too small to hold the fixed entries, all fixed
4383 entries are proportionately scaled down to fit.
4384 The grid entries not on even columns and rows are scaled to fit the
4385 remaining space, if any.
4386
4387#Code
4388 struct Lattice {
4389 enum Flags {...
4390
4391 const int* fXDivs;
4392 const int* fYDivs;
4393 const Flags* fFlags;
4394 int fXCount;
4395 int fYCount;
4396 const SkIRect* fBounds;
4397 };
4398##
4399
4400 #Enum Flags
4401 #Code
4402 enum Flags : uint8_t {
4403 kTransparent_Flags = 1 << 0,
4404 };
4405 ##
4406
4407 Optional setting per rectangular grid entry to make it transparent.
4408
4409 #Const kTransparent_Flags 1
4410 Set to skip lattice rectangle by making it transparent.
4411 ##
4412 ##
4413
4414 #Member const int* fXDivs
4415 Array of x-coordinates that divide the bitmap vertically.
4416 Array entries must be unique, increasing, greater than or equal to fBounds left edge,
4417 and less than fBounds right edge.
4418 Set the first element to fBounds left to collapse the left column of fixed grid entries.
4419 ##
4420
4421 #Member const int* fYDivs
4422 Array of y-coordinates that divide the bitmap horizontally.
4423 Array entries must be unique, increasing, greater than or equal to fBounds top edge,
4424 and less than fBounds bottom edge.
4425 Set the first element to fBounds top to collapse the top row of fixed grid entries.
4426 ##
4427
4428 #Member const Flags* fFlags
4429 Optional array of Flags, one per rectangular grid entry:
4430 array length must be (fXCount + 1) * (fYCount + 1).
4431 Array entries correspond to the rectangular grid entries, ascending
4432 left to right and then top to bottom.
4433 ##
4434
4435 #Member int fXCount
4436 Number of entries in fXDivs array; one less than the number of horizontal divisions.
4437 ##
4438
4439 #Member int fYCount
4440 Number of entries in fYDivs array; one less than the number of vertical divisions.
4441 ##
4442
4443 #Member const SkIRect* fBounds
4444 Optional subset IRect source to draw from.
4445 If nullptr, source bounds is dimensions of Bitmap or Image.
4446 ##
4447
4448#Struct Lattice ##
4449
4450#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
4451 const SkPaint* paint = nullptr)
4452
4453Draw Bitmap bitmap stretched differentially to fit into Rect dst.
4454
4455Lattice lattice divides bitmap into a rectangular grid.
4456Each intersection of an even-numbered row and column is fixed; like the corners
4457of drawBitmapNine, fixed lattice elements never scale larger than their initial size
4458and shrink proportionately when all fixed elements exceed the bitmap's dimension.
4459All other grid elements scale to fill the available space, if any.
4460
4461Additionally transform draw using Clip, Matrix, and optional Paint paint.
4462If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4463If bitmap is kAlpha_8_SkColorType, apply Shader.
4464if paint contains Mask_Filter, generate mask from bitmap bounds. If generated mask extends
4465beyond bitmap bounds, replicate bitmap edge colors, just as Shader made from
4466SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the bitmap's edge
4467color when it samples outside of its bounds.
4468
4469#Param bitmap Bitmap containing pixels, dimensions, and format. ##
4470#Param lattice Division of bitmap into fixed and variable rectangles. ##
4471#Param dst Destination Rect of image to draw to. ##
4472#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4473
4474#Example
4475#Height 128
4476#Description
4477 The two leftmost bitmap draws has four corners and sides to the left and right of center.
4478 The leftmost bitmap draw scales the width of corners proportionately to fit.
4479 The third and fourth draw corners are unscaled; the sides are scaled to
4480 fill the remaining space; the center is transparent.
4481 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
4482 and below center to fill the remaining space.
4483##
4484void draw(SkCanvas* canvas) {
4485 SkIRect center = { 20, 10, 50, 40 };
4486 SkBitmap bitmap;
4487 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4488 SkCanvas bitCanvas(bitmap);
4489 SkPaint paint;
4490 SkColor gray = 0xFF000000;
4491 int left = 0;
4492 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4493 int top = 0;
4494 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4495 paint.setColor(gray);
4496 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4497 gray += 0x001f1f1f;
4498 top = bottom;
4499 }
4500 left = right;
4501 }
4502 const int xDivs[] = { center.fLeft, center.fRight };
4503 const int yDivs[] = { center.fTop, center.fBottom };
4504 SkCanvas::Lattice::Flags flags[3][3];
4505 memset(flags, 0, sizeof(flags));
4506 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4507 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4508 SK_ARRAY_COUNT(yDivs), nullptr };
4509 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4510 canvas->drawBitmapLattice(bitmap, lattice , SkRect::MakeWH(dest, 110 - dest), nullptr);
4511 canvas->translate(dest + 4, 0);
4512 }
4513}
4514##
4515
4516#ToDo incomplete ##
4517
4518##
4519
4520# ------------------------------------------------------------------------------
4521
4522#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
4523 const SkPaint* paint = nullptr)
4524
4525Draw Image image stretched differentially to fit into Rect dst.
4526
4527Lattice lattice divides image into a rectangular grid.
4528Each intersection of an even-numbered row and column is fixed; like the corners
4529of drawImageNine, fixed lattice elements never scale larger than their initial size
4530and shrink proportionately when all fixed elements exceed the bitmap's dimension.
4531All other grid elements scale to fill the available space, if any.
4532
4533Additionally transform draw using Clip, Matrix, and optional Paint paint.
4534If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode, and Draw_Looper.
4535If image is kAlpha_8_SkColorType, apply Shader.
4536if paint contains Mask_Filter, generate mask from image bounds. If generated mask extends
4537beyond image bounds, replicate image edge colors, just as Shader made from
4538SkShader::MakeBitmapShader with SkShader::kClamp_TileMode set replicates the image's edge
4539color when it samples outside of its bounds.
4540
4541#Param image Image containing pixels, dimensions, and format. ##
4542#Param lattice Division of bitmap into fixed and variable rectangles. ##
4543#Param dst Destination Rect of image to draw to. ##
4544#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter, and so on; or nullptr. ##
4545
4546#Example
4547#Height 128
4548#Description
4549 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
4550 The second image equals the size of center; only corners are drawn, unscaled.
4551 The remaining images are larger than center. All corners draw unscaled. The sides
4552 are scaled if needed to take up the remaining space; the center is transparent.
4553##
4554void draw(SkCanvas* canvas) {
4555 SkIRect center = { 20, 10, 50, 40 };
4556 SkBitmap bitmap;
4557 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
4558 SkCanvas bitCanvas(bitmap);
4559 SkPaint paint;
4560 SkColor gray = 0xFF000000;
4561 int left = 0;
4562 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
4563 int top = 0;
4564 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
4565 paint.setColor(gray);
4566 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
4567 gray += 0x001f1f1f;
4568 top = bottom;
4569 }
4570 left = right;
4571 }
4572 const int xDivs[] = { center.fLeft, center.fRight };
4573 const int yDivs[] = { center.fTop, center.fBottom };
4574 SkCanvas::Lattice::Flags flags[3][3];
4575 memset(flags, 0, sizeof(flags));
4576 flags[1][1] = SkCanvas::Lattice::kTransparent_Flags;
4577 SkCanvas::Lattice lattice = { xDivs, yDivs, flags[0], SK_ARRAY_COUNT(xDivs),
4578 SK_ARRAY_COUNT(yDivs), nullptr };
4579 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4580 SkImage* imagePtr = image.get();
4581 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4582 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4583 canvas->translate(dest + 4, 0);
4584 }
4585}
4586##
4587
4588#ToDo incomplete ##
4589
4590##
4591
4592#Topic Draw_Image ##
4593
4594# ------------------------------------------------------------------------------
4595
4596#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
4597 const SkPaint& paint)
4598
4599Draw text, with origin at (x, y), using Clip, Matrix, and Paint paint.
4600text's meaning depends on Paint_Text_Encoding; by default, text encoding is UTF-8.
4601x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default text
4602draws left to right, positioning the first glyph's left side bearing at x and its
4603baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4604
4605All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4606Image_Filter, and Draw_Looper; apply to text. By default, drawText draws filled 12 point black
4607glyphs.
4608
4609#Param text Character code points or glyphs drawn. ##
4610#Param byteLength Byte length of text array. ##
4611#Param x Start of text on x-axis. ##
4612#Param y Start of text on y-axis. ##
4613#Param paint Text size, blend, color, and so on, used to draw. ##
4614
4615#Example
4616#Height 200
4617#Description
4618 The same text is drawn varying Paint_Text_Size and varying
4619 Matrix.
4620##
4621void draw(SkCanvas* canvas) {
4622 SkPaint paint;
4623 paint.setAntiAlias(true);
4624 float textSizes[] = { 12, 18, 24, 36 };
4625 for (auto size: textSizes ) {
4626 paint.setTextSize(size);
4627 canvas->drawText("Aa", 2, 10, 20, paint);
4628 canvas->translate(0, size * 2);
4629 }
4630 paint.reset();
4631 paint.setAntiAlias(true);
4632 float yPos = 20;
4633 for (auto size: textSizes ) {
4634 float scale = size / 12.f;
4635 canvas->resetMatrix();
4636 canvas->translate(100, 0);
4637 canvas->scale(scale, scale);
4638 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
4639 yPos += size * 2;
4640 }
4641}
4642##
4643
4644#ToDo incomplete ##
4645
4646##
4647
4648#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
4649
4650Draw null terminated string, with origin at (x, y), using Clip, Matrix, and Paint paint.
4651string's meaning depends on Paint_Text_Encoding; by default, string encoding is UTF-8.
4652Other values of Paint_Text_Encoding are unlikely to produce the desired results, since
4653zero bytes may be embedded in the string.
4654x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default string
4655draws left to right, positioning the first glyph's left side bearing at x and its
4656baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4657
4658All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4659Image_Filter, and Draw_Looper; apply to string. By default, drawString draws filled 12 point black
4660glyphs.
4661
4662#Param string Character code points or glyphs drawn, ending with a char value of zero. ##
4663#Param x Start of string on x-axis. ##
4664#Param y Start of string on y-axis. ##
4665#Param paint Text size, blend, color, and so on, used to draw. ##
4666
4667#Example
4668 SkPaint paint;
4669 canvas->drawString("a small hello", 20, 20, paint);
4670##
4671
4672#SeeAlso drawText
4673
4674##
4675
4676#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
4677
4678Draw null terminated string, with origin at (x, y), using Clip, Matrix, and Paint paint.
4679string's meaning depends on Paint_Text_Encoding; by default, string encoding is UTF-8.
4680Other values of Paint_Text_Encoding are unlikely to produce the desired results, since
4681zero bytes may be embedded in the string.
4682x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default string
4683draws left to right, positioning the first glyph's left side bearing at x and its
4684baseline at y. Text size is affected by Matrix and Paint_Text_Size.
4685
4686All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4687Image_Filter, and Draw_Looper; apply to string. By default, drawString draws filled 12 point black
4688glyphs.
4689
4690#Param string Character code points or glyphs drawn, ending with a char value of zero. ##
4691#Param x Start of string on x-axis. ##
4692#Param y Start of string on y-axis. ##
4693#Param paint Text size, blend, color, and so on, used to draw. ##
4694
4695#Example
4696 SkPaint paint;
4697 SkString string("a small hello");
4698 canvas->drawString(string, 20, 20, paint);
4699##
4700
4701#SeeAlso drawText
4702
4703##
4704
4705# ------------------------------------------------------------------------------
4706
4707#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
4708 const SkPaint& paint)
4709
4710Draw each glyph in text with the origin in pos array, using Clip, Matrix, and Paint paint.
4711The number of entries in pos array must match the number of glyphs described by byteLength of text.
4712text's meaning depends on Paint_Text_Encoding; by default, text encoding is UTF-8.
4713pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default each
4714glyph's left side bearing is positioned at x and its
4715baseline is positioned at y. Text size is affected by Matrix and Paint_Text_Size.
4716
4717All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4718Image_Filter, and Draw_Looper; apply to text. By default, drawPosText draws filled 12 point black
4719glyphs.
4720
4721Layout engines such as Harfbuzz typically use drawPosText to position each glyph
4722rather than using the font's advance widths.
4723
4724#Param text Character code points or glyphs drawn. ##
4725#Param byteLength Byte length of text array. ##
4726#Param pos Array of glyph origins. ##
4727#Param paint Text size, blend, color, and so on, used to draw. ##
4728
4729#Example
4730#Height 120
4731void draw(SkCanvas* canvas) {
4732 const char hello[] = "HeLLo!";
4733 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
4734 {172, 100} };
4735 SkPaint paint;
4736 paint.setTextSize(60);
4737 canvas->drawPosText(hello, strlen(hello), pos, paint);
4738}
4739##
4740
4741#ToDo incomplete ##
4742
4743##
4744
4745# ------------------------------------------------------------------------------
4746
4747#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
4748 const SkPaint& paint)
4749
4750Draw each glyph in text with its (x, y) origin composed from xpos array and constY, using Clip, Matrix, and Paint paint.
4751The number of entries in xpos array must match the number of glyphs described by byteLength of text.
4752text's meaning depends on Paint_Text_Encoding; by default, text encoding is UTF-8.
4753pos elements' meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default each
4754glyph's left side bearing is positioned at an xpos element and its
4755baseline is positioned at constY. Text size is affected by Matrix and Paint_Text_Size.
4756
4757All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4758Image_Filter, and Draw_Looper; apply to text. By default, drawPosTextH draws filled 12 point black
4759glyphs.
4760
4761Layout engines such as Harfbuzz typically use drawPosTextH to position each glyph
4762rather than using the font's advance widths if all glyphs share the same baseline.
4763
4764#Param text Character code points or glyphs drawn. ##
4765#Param byteLength Byte length of text array. ##
4766#Param xpos Array of x positions, used to position each glyph. ##
4767#Param constY Shared y coordinate for all of x positions. ##
4768#Param paint Text size, blend, color, and so on, used to draw. ##
4769
4770#Example
4771#Height 40
4772 void draw(SkCanvas* canvas) {
4773 SkScalar xpos[] = { 20, 40, 80, 160 };
4774 SkPaint paint;
4775 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
4776 }
4777##
4778
4779#ToDo incomplete ##
4780
4781##
4782
4783# ------------------------------------------------------------------------------
4784
4785#Method void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
4786 SkScalar vOffset, const SkPaint& paint)
4787
4788Draw text on Path path, using Clip, Matrix, and Paint paint.
4789Origin of text is at distance hOffset along the path, offset by a perpendicular vector of
4790length vOffset. If the path section corresponding the glyph advance is curved, the glyph
4791is drawn curved to match; control points in the glyph are mapped to projected points parallel
4792to the path. If the text's advance is larger than the path length, the excess text is clipped.
4793
4794text's meaning depends on Paint_Text_Encoding; by default, text encoding is UTF-8.
4795Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default text
4796positions the first glyph's left side bearing at origin x and its
4797baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
4798
4799All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4800Image_Filter, and Draw_Looper; apply to text. By default, drawTextOnPathHV draws filled 12 point black
4801glyphs.
4802
4803#Param text Character code points or glyphs drawn. ##
4804#Param byteLength Byte length of text array. ##
4805#Param path Path providing text baseline. ##
4806#Param hOffset Distance along path to offset origin. ##
4807#Param vOffset Offset of text above (if negative) or below (if positive) the path. ##
4808#Param paint Text size, blend, color, and so on, used to draw. ##
4809
4810#Example
4811 void draw(SkCanvas* canvas) {
4812 const char aero[] = "correo a" "\xC3" "\xA9" "reo";
4813 const size_t len = sizeof(aero) - 1;
4814 SkPath path;
4815 path.addOval({43-26, 43-26, 43+26, 43+26}, SkPath::kCW_Direction, 3);
4816 SkPaint paint;
4817 paint.setTextSize(24);
4818 for (auto offset : { 0, 10, 20 } ) {
4819 canvas->drawTextOnPathHV(aero, len, path, 0, -offset, paint);
4820 canvas->translate(70 + offset, 70 + offset);
4821 }
4822 }
4823##
4824
4825#ToDo incomplete ##
4826
4827##
4828
4829# ------------------------------------------------------------------------------
4830
4831#Method void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
4832 const SkMatrix* matrix, const SkPaint& paint)
4833
4834Draw text on Path path, using Clip, Matrix, and Paint paint.
4835Origin of text is at beginning of path offset by matrix, if provided, before it is mapped to path.
4836If the path section corresponding the glyph advance is curved, the glyph
4837is drawn curved to match; control points in the glyph are mapped to projected points parallel
4838to the path. If the text's advance is larger than the path length, the excess text is clipped.
4839
4840text's meaning depends on Paint_Text_Encoding; by default, text encoding is UTF-8.
4841Origin meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default text
4842positions the first glyph's left side bearing at origin x and its
4843baseline at origin y. Text size is affected by Matrix and Paint_Text_Size.
4844
4845All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4846Image_Filter, and Draw_Looper; apply to text. By default, drawTextOnPath draws filled 12 point black
4847glyphs.
4848
4849#Param text Character code points or glyphs drawn. ##
4850#Param byteLength Byte length of text array. ##
4851#Param path Path providing text baseline. ##
4852#Param matrix Optional transform of glyphs before mapping to path; or nullptr. ##
4853#Param paint Text size, blend, color, and so on, used to draw. ##
4854
4855#Example
4856 void draw(SkCanvas* canvas) {
4857 const char roller[] = "rollercoaster";
4858 const size_t len = sizeof(roller) - 1;
4859 SkPath path;
4860 path.cubicTo(40, -80, 120, 80, 160, -40);
4861 SkPaint paint;
4862 paint.setTextSize(32);
4863 paint.setStyle(SkPaint::kStroke_Style);
4864 SkMatrix matrix;
4865 matrix.setIdentity();
4866 for (int i = 0; i < 3; ++i) {
4867 canvas->translate(25, 60);
4868 canvas->drawPath(path, paint);
4869 canvas->drawTextOnPath(roller, len, path, &matrix, paint);
4870 matrix.preTranslate(0, 10);
4871 }
4872 }
4873##
4874
4875#ToDo incomplete ##
4876
4877##
4878
4879# ------------------------------------------------------------------------------
4880
4881#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
4882 const SkRect* cullRect, const SkPaint& paint)
4883
4884Draw text, transforming each glyph by the corresponding SkRSXform,
4885using Clip, Matrix, and Paint paint.
4886RSXform array specifies a separate square scale, rotation, and translation for
4887each glyph.
4888Optional Rect cullRect is a conservative bounds of text,
4889taking into account RSXform and paint. If cullrect is outside of Clip, canvas can
4890skip drawing.
4891
4892All elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4893Image_Filter, and Draw_Looper; apply to text. By default, drawTextRSXform draws filled 12 point black
4894glyphs.
4895
4896#Param text Character code points or glyphs drawn. ##
4897#Param byteLength Byte length of text array. ##
4898#Param xform RSXform rotates, scales, and translates each glyph individually. ##
4899#Param cullRect Rect bounds of text for efficient clipping; or nullptr. ##
4900#Param paint Text size, blend, color, and so on, used to draw. ##
4901
4902#Example
4903void draw(SkCanvas* canvas) {
4904 const int iterations = 26;
4905 SkRSXform transforms[iterations];
4906 char alphabet[iterations];
4907 SkScalar angle = 0;
4908 SkScalar scale = 1;
4909 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
4910 const SkScalar s = SkScalarSin(angle) * scale;
4911 const SkScalar c = SkScalarCos(angle) * scale;
4912 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
4913 angle += .45;
4914 scale += .2;
4915 alphabet[i] = 'A' + i;
4916 }
4917 SkPaint paint;
4918 paint.setTextAlign(SkPaint::kCenter_Align);
4919 canvas->translate(110, 138);
4920 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
4921}
4922##
4923
4924#ToDo incomplete ##
4925
4926##
4927
4928# ------------------------------------------------------------------------------
4929
4930#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
4931
4932Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
4933blob contains glyphs, their positions, and paint attributes specific to text:
4934Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X, Paint_Text_Align,
4935Paint_Hinting, Anti-alias, Paint_Fake_Bold, Font_Embedded_Bitmaps, Full_Hinting_Spacing,
4936LCD_Text, Linear_Text, Subpixel_Text, and Paint_Vertical_Text.
4937
4938Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4939Image_Filter, and Draw_Looper; apply to blob.
4940
4941#Param blob Glyphs, positions, and their paints' text size, typeface, and so on. ##
4942#Param x Horizontal offset applied to blob. ##
4943#Param y Vertical offset applied to blob. ##
4944#Param paint Blend, color, stroking, and so on, used to draw. ##
4945
4946#Example
4947#Height 120
4948 void draw(SkCanvas* canvas) {
4949 SkTextBlobBuilder textBlobBuilder;
4950 const char bunny[] = "/(^x^)\\";
4951 const int len = sizeof(bunny) - 1;
4952 uint16_t glyphs[len];
4953 SkPaint paint;
4954 paint.textToGlyphs(bunny, len, glyphs);
4955 int runs[] = { 3, 1, 3 };
4956 SkPoint textPos = { 20, 100 };
4957 int glyphIndex = 0;
4958 for (auto runLen : runs) {
4959 paint.setTextSize(1 == runLen ? 20 : 50);
4960 const SkTextBlobBuilder::RunBuffer& run =
4961 textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
4962 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
4963 textPos.fX += paint.measureText(&bunny[glyphIndex], runLen, nullptr);
4964 glyphIndex += runLen;
4965 }
4966 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4967 paint.reset();
4968 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4969 }
4970##
4971
4972#ToDo incomplete ##
4973
4974##
4975
4976# ------------------------------------------------------------------------------
4977
4978#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
4979
4980Draw Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
4981blob contains glyphs, their positions, and paint attributes specific to text:
4982Typeface, Paint_Text_Size, Paint_Text_Scale_X, Paint_Text_Skew_X, Paint_Text_Align,
4983Paint_Hinting, Anti-alias, Paint_Fake_Bold, Font_Embedded_Bitmaps, Full_Hinting_Spacing,
4984LCD_Text, Linear_Text, Subpixel_Text, and Paint_Vertical_Text.
4985
4986Elements of paint: Path_Effect, Rasterizer, Mask_Filter, Shader, Color_Filter,
4987Image_Filter, and Draw_Looper; apply to blob.
4988
4989#Param blob Glyphs, positions, and their paints' text size, typeface, and so on. ##
4990#Param x Horizontal offset applied to blob. ##
4991#Param y Vertical offset applied to blob. ##
4992#Param paint Blend, color, stroking, and so on, used to draw. ##
4993
4994#Example
4995#Height 120
4996#Description
4997Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob.
4998Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
4999##
5000 void draw(SkCanvas* canvas) {
5001 SkTextBlobBuilder textBlobBuilder;
5002 SkPaint paint;
5003 paint.setTextSize(50);
5004 paint.setColor(SK_ColorRED);
5005 const SkTextBlobBuilder::RunBuffer& run =
5006 textBlobBuilder.allocRun(paint, 1, 20, 100);
5007 run.glyphs[0] = 20;
5008 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
5009 paint.setTextSize(10);
5010 paint.setColor(SK_ColorBLUE);
5011 canvas->drawTextBlob(blob.get(), 0, 0, paint);
5012 }
5013##
5014
5015#ToDo incomplete ##
5016
5017##
5018
5019# ------------------------------------------------------------------------------
5020
5021#Method void drawPicture(const SkPicture* picture)
5022
5023Draw Picture picture, using Clip and Matrix.
5024Clip and Matrix are unchanged by picture contents, as if
5025save() was called before and restore() was called after drawPicture.
5026
5027Picture records a series of draw commands for later playback.
5028
5029#Param picture Recorded drawing commands to play. ##
5030
5031#Example
5032void draw(SkCanvas* canvas) {
5033 SkPictureRecorder recorder;
5034 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5035 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5036 SkPaint paint;
5037 paint.setColor(color);
5038 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5039 recordingCanvas->translate(10, 10);
5040 recordingCanvas->scale(1.2f, 1.4f);
5041 }
5042 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5043 const SkPicture* playbackPtr = playback.get();
5044 canvas->drawPicture(playback);
5045 canvas->scale(2, 2);
5046 canvas->translate(50, 0);
5047 canvas->drawPicture(playback);
5048}
5049##
5050
5051#ToDo incomplete ##
5052
5053##
5054
5055# ------------------------------------------------------------------------------
5056
5057#Method void drawPicture(const sk_sp<SkPicture>& picture)
5058
5059Draw Picture picture, using Clip and Matrix.
5060Clip and Matrix are unchanged by picture contents, as if
5061save() was called before and restore() was called after drawPicture.
5062
5063Picture records a series of draw commands for later playback.
5064
5065#Param picture Recorded drawing commands to play. ##
5066
5067#Example
5068void draw(SkCanvas* canvas) {
5069 SkPictureRecorder recorder;
5070 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5071 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5072 SkPaint paint;
5073 paint.setColor(color);
5074 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5075 recordingCanvas->translate(10, 10);
5076 recordingCanvas->scale(1.2f, 1.4f);
5077 }
5078 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5079 canvas->drawPicture(playback);
5080 canvas->scale(2, 2);
5081 canvas->translate(50, 0);
5082 canvas->drawPicture(playback);
5083}
5084##
5085
5086#ToDo incomplete ##
5087
5088##
5089
5090# ------------------------------------------------------------------------------
5091
5092#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
5093
5094Draw Picture picture, using Clip and Matrix;
5095transforming picture with Matrix matrix, if provided;
5096and use Paint paint Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode, if provided.
5097
5098matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5099paint use is equivalent to: saveLayer, drawPicture, restore().
5100
5101#Param picture Recorded drawing commands to play. ##
5102#Param matrix Optional Matrix to rotate, scale, translate, and so on; or nullptr. ##
5103#Param paint Optional Paint to apply transparency, filtering, and so on; or nullptr. ##
5104
5105#Example
5106void draw(SkCanvas* canvas) {
5107 SkPaint paint;
5108 SkPictureRecorder recorder;
5109 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5110 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5111 paint.setColor(color);
5112 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5113 recordingCanvas->translate(10, 10);
5114 recordingCanvas->scale(1.2f, 1.4f);
5115 }
5116 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5117 const SkPicture* playbackPtr = playback.get();
5118 SkMatrix matrix;
5119 matrix.reset();
5120 for (auto alpha : { 70, 140, 210 } ) {
5121 paint.setAlpha(alpha);
5122 canvas->drawPicture(playbackPtr, &matrix, &paint);
5123 matrix.preTranslate(70, 70);
5124 }
5125}
5126##
5127
5128#ToDo incomplete ##
5129
5130##
5131
5132# ------------------------------------------------------------------------------
5133
5134#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
5135
5136Draw Picture picture, using Clip and Matrix;
5137transforming picture with Matrix matrix, if provided;
5138and use Paint paint Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode, if provided.
5139
5140matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
5141paint use is equivalent to: saveLayer, drawPicture, restore().
5142
5143#Param picture Recorded drawing commands to play. ##
5144#Param matrix Optional Matrix to rotate, scale, translate, and so on; or nullptr. ##
5145#Param paint Optional Paint to apply transparency, filtering, and so on; or nullptr. ##
5146
5147#Example
5148void draw(SkCanvas* canvas) {
5149 SkPaint paint;
5150 SkPictureRecorder recorder;
5151 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
5152 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
5153 paint.setColor(color);
5154 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
5155 recordingCanvas->translate(10, 10);
5156 recordingCanvas->scale(1.2f, 1.4f);
5157 }
5158 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
5159 SkMatrix matrix;
5160 matrix.reset();
5161 for (auto alpha : { 70, 140, 210 } ) {
5162 paint.setAlpha(alpha);
5163 canvas->drawPicture(playback, &matrix, &paint);
5164 matrix.preTranslate(70, 70);
5165 }
5166}
5167##
5168
5169#ToDo incomplete ##
5170
5171##
5172
5173# ------------------------------------------------------------------------------
5174
5175#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
5176
5177Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
5178If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint contains Shader,
5179Blend_Mode mode combines Vertices_Colors with Shader.
5180
5181#Param vertices The triangle mesh to draw. ##
5182#Param mode Combines Vertices_Colors with Shader, if both are present. ##
5183#Param paint Specifies the Shader, used as Vertices texture, if present. ##
5184
5185#Example
5186void draw(SkCanvas* canvas) {
5187 SkPaint paint;
5188 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5189 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5190 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5191 SK_ARRAY_COUNT(points), points, nullptr, colors);
5192 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
5193}
5194##
5195
5196#ToDo incomplete ##
5197
5198##
5199
5200# ------------------------------------------------------------------------------
5201
5202#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
5203
5204Draw Vertices vertices, a triangle mesh, using Clip and Matrix.
5205If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint contains Shader,
5206Blend_Mode mode combines Vertices_Colors with Shader.
5207
5208#Param vertices The triangle mesh to draw. ##
5209#Param mode Combines Vertices_Colors with Shader, if both are present. ##
5210#Param paint Specifies the Shader, used as Vertices texture, if present. ##
5211
5212#Example
5213void draw(SkCanvas* canvas) {
5214 SkPaint paint;
5215 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
5216 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
5217 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5218 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
5219 SkShader::kClamp_TileMode));
5220 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
5221 SK_ARRAY_COUNT(points), points, texs, colors);
5222 canvas->drawVertices(vertices.get(), SkBlendMode::kDarken, paint);
5223}
5224##
5225
5226#ToDo incomplete ##
5227
5228##
5229
5230# ------------------------------------------------------------------------------
5231
5232#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5233 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
5234
5235Draw a cubic Coons patch: the interpolation of four cubics with shared corners,
5236associating a color, and optionally a texture coordinate, with each corner.
5237
5238#ToDo can patch use image filter? ##
5239
5240The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter, Color_Alpha,
5241Image_Filter, and Blend_Mode. If Shader is provided it is treated as the Coons
5242patch texture; Blend_Mode mode combines Color colors and Shader if both are provided.
5243
5244#Param cubics Point array cubics specifying the four cubics starting at the top left corner,
Cary Clark579985c2017-07-31 11:48:27 -04005245 in clockwise order, sharing every fourth point. The last cubic ends at the first point.
5246#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04005247#Param colors Color array color associating colors with corners in top left, top right, bottom right,
Cary Clark579985c2017-07-31 11:48:27 -04005248 bottom left order.
5249#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04005250#Param texCoords Point array texCoords mapping Shader as texture to corners in same order, if paint
Cary Clark579985c2017-07-31 11:48:27 -04005251 contains Shader; or nullptr.
5252#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04005253#Param mode Blend_Mode for colors and Shader if present. ##
5254#Param paint Shader, Color_Filter, Blend_Mode, used to draw. ##
5255
5256#Example
5257#Image 5
5258void draw(SkCanvas* canvas) {
5259 // SkBitmap source = cmbkygk;
5260 SkPaint paint;
5261 paint.setFilterQuality(kLow_SkFilterQuality);
5262 paint.setAntiAlias(true);
5263 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5264 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5265 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5266 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5267 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
5268 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
5269 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5270 SkShader::kClamp_TileMode, nullptr));
5271 canvas->scale(15, 15);
5272 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
5273 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
5274 canvas->translate(4, 4);
5275 }
5276}
5277##
5278
5279#ToDo incomplete ##
5280
5281##
5282
5283# ------------------------------------------------------------------------------
5284
5285#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
5286 const SkPoint texCoords[4], const SkPaint& paint)
5287
5288Draw a cubic Coons patch: the interpolation of four cubics with shared corners,
5289associating a color, a texture coordinate, or both, with each corner.
5290
5291The Coons patch uses Clip and Matrix, Paint paint's Shader, Color_Filter, Color_Alpha,
5292Image_Filter, (?) and Blend_Mode. If Shader is provided it is treated as the Coons
5293patch texture.
5294
5295#Param cubics Point array cubics specifying the four cubics starting at the top left corner,
Cary Clark579985c2017-07-31 11:48:27 -04005296 in clockwise order, sharing every fourth point. The last cubic ends at the first point.
5297#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04005298#Param colors Color array color associating colors with corners in top left, top right, bottom right,
Cary Clark579985c2017-07-31 11:48:27 -04005299 bottom left order; or nullptr.
5300#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04005301#Param texCoords Point array texCoords mapping Shader as texture to corners in same order, if paint
Cary Clark579985c2017-07-31 11:48:27 -04005302 contains Shader; or nullptr.
5303#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04005304#Param paint Shader, Color_Filter, Blend_Mode, used to draw. ##
5305
5306#Example
5307void draw(SkCanvas* canvas) {
5308 SkPaint paint;
5309 paint.setAntiAlias(true);
5310 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5311 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5312 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5313 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5314 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
5315 canvas->scale(30, 30);
5316 canvas->drawPatch(cubics, colors, nullptr, paint);
5317 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
5318 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
5319 {0.5f,3.2f} };
5320 paint.setTextSize(18.f / 30);
5321 paint.setTextAlign(SkPaint::kCenter_Align);
5322 for (int i = 0; i< 10; ++i) {
5323 char digit = '0' + i;
5324 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
5325 }
5326 canvas->drawString("10", text[10].fX, text[10].fY, paint);
5327 canvas->drawString("11", text[11].fX, text[11].fY, paint);
5328 paint.setStyle(SkPaint::kStroke_Style);
5329 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
5330 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
5331}
5332##
5333
5334#Example
5335#Image 6
5336void draw(SkCanvas* canvas) {
5337 // SkBitmap source = checkerboard;
5338 SkPaint paint;
5339 paint.setFilterQuality(kLow_SkFilterQuality);
5340 paint.setAntiAlias(true);
5341 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
5342 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
5343 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
5344 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
5345 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
5346 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
5347 SkShader::kClamp_TileMode, nullptr));
5348 canvas->scale(30, 30);
5349 canvas->drawPatch(cubics, nullptr, texCoords, paint);
5350}
5351##
5352
5353#ToDo incomplete ##
5354
5355##
5356
5357# ------------------------------------------------------------------------------
5358
5359#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
5360 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5361 const SkPaint* paint)
5362
5363Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
5364paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode to draw, if present.
5365For each entry in the array, Rect tex locates sprite in atlas, and RSXform xform transforms it
5366into destination space.
5367xform, text, and colors if present, must contain count entries.
5368Optional colors is applied for each sprite using Blend_Mode.
5369Optional cullRect is a conservative bounds of all transformed sprites.
5370If cullrect is outside of Clip, canvas can skip drawing.
5371
5372#Param atlas Image containing sprites. ##
5373#Param xform RSXform mappings for sprites in atlas. ##
5374#Param tex Rect locations of sprites in atlas. ##
5375#Param colors Color, one per sprite, blended with sprite using Blend_Mode; or nullptr. ##
5376#Param count Number of sprites to draw. ##
5377#Param mode Blend_Mode combining colors and sprites. ##
5378#Param cullRect Rect bounds of transformed sprites for efficient clipping; or nullptr. ##
5379#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; or nullptr. ##
5380
5381#Example
5382#Image 3
5383void draw(SkCanvas* canvas) {
5384 // SkBitmap source = mandrill;
5385 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5386 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5387 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5388 const SkImage* imagePtr = image.get();
5389 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
5390}
5391##
5392
5393#ToDo incomplete ##
5394
5395##
5396
5397# ------------------------------------------------------------------------------
5398
5399#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5400 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
5401 const SkPaint* paint)
5402
5403Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
5404paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode to draw, if present.
5405For each entry in the array, Rect tex locates sprite in atlas, and RSXform xform transforms it
5406into destination space.
5407xform, text, and colors if present, must contain count entries.
5408Optional colors is applied for each sprite using Blend_Mode.
5409Optional cullRect is a conservative bounds of all transformed sprites.
5410If cullrect is outside of Clip, canvas can skip drawing.
5411
5412#Param atlas Image containing sprites. ##
5413#Param xform RSXform mappings for sprites in atlas. ##
5414#Param tex Rect locations of sprites in atlas. ##
5415#Param colors Color, one per sprite, blended with sprite using Blend_Mode; or nullptr. ##
5416#Param count Number of sprites to draw. ##
5417#Param mode Blend_Mode combining colors and sprites. ##
5418#Param cullRect Rect bounds of transformed sprites for efficient clipping; or nullptr. ##
5419#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; or nullptr. ##
5420
5421#Example
5422#Image 3
5423void draw(SkCanvas* canvas) {
5424 // SkBitmap source = mandrill;
5425 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5426 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5427 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
5428 SkPaint paint;
5429 paint.setAlpha(127);
5430 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
5431}
5432##
5433
5434#ToDo bug in example on cpu side, gpu looks ok ##
5435
5436##
5437
5438# ------------------------------------------------------------------------------
5439
5440#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
5441 const SkRect* cullRect, const SkPaint* paint)
5442
5443Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
5444paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode to draw, if present.
5445For each entry in the array, Rect tex locates sprite in atlas, and RSXform xform transforms it
5446into destination space.
5447xform and text must contain count entries.
5448Optional cullRect is a conservative bounds of all transformed sprites.
5449If cullrect is outside of Clip, canvas can skip drawing.
5450
5451#Param atlas Image containing sprites. ##
5452#Param xform RSXform mappings for sprites in atlas. ##
5453#Param tex Rect locations of sprites in atlas. ##
5454#Param count Number of sprites to draw. ##
5455#Param cullRect Rect bounds of transformed sprites for efficient clipping; or nullptr. ##
5456#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; or nullptr. ##
5457
5458#Example
5459#Image 3
5460void draw(SkCanvas* canvas) {
5461 // sk_sp<SkImage> image = mandrill;
5462 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
5463 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
5464 const SkImage* imagePtr = image.get();
5465 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
5466}
5467##
5468
5469#ToDo incomplete ##
5470
5471##
5472
5473# ------------------------------------------------------------------------------
5474
5475#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
5476 int count, const SkRect* cullRect, const SkPaint* paint)
5477
5478Draw a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
5479paint uses Anti-alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode to draw, if present.
5480For each entry in the array, Rect tex locates sprite in atlas, and RSXform xform transforms it
5481into destination space.
5482xform and text must contain count entries.
5483Optional cullRect is a conservative bounds of all transformed sprites.
5484If cullrect is outside of Clip, canvas can skip drawing.
5485
5486#Param atlas Image containing sprites. ##
5487#Param xform RSXform mappings for sprites in atlas. ##
5488#Param tex Rect locations of sprites in atlas. ##
5489#Param count Number of sprites to draw. ##
5490#Param cullRect Rect bounds of transformed sprites for efficient clipping; or nullptr. ##
5491#Param paint Paint Color_Filter, Image_Filter, Blend_Mode, and so on; or nullptr. ##
5492
5493#Example
5494#Image 3
5495void draw(SkCanvas* canvas) {
5496 // sk_sp<SkImage> image = mandrill;
5497 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
5498 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
5499 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
5500}
5501##
5502
5503#ToDo incomplete ##
5504
5505##
5506
5507# ------------------------------------------------------------------------------
5508
5509#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = NULL)
5510
5511Draw Drawable drawable using Clip and Matrix, concatenated with
5512optional matrix.
5513
5514If Canvas has an asynchronous implementation, as is the case
5515when it is recording into Picture, then drawable will be referenced,
5516so that SkDrawable::draw() can be called when the operation is finalized. To force
5517immediate drawing, call SkDrawable::draw() instead.
5518
5519#Param drawable Custom struct encapsulating drawing commands. ##
5520#Param matrix Transformation applied to drawing; or nullptr. ##
5521
5522#Example
5523#Height 100
5524#Function
5525struct MyDrawable : public SkDrawable {
5526 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5527
5528 void onDraw(SkCanvas* canvas) override {
5529 SkPath path;
5530 path.conicTo(10, 90, 50, 90, 0.9f);
5531 SkPaint paint;
5532 paint.setColor(SK_ColorBLUE);
5533 canvas->drawRect(path.getBounds(), paint);
5534 paint.setAntiAlias(true);
5535 paint.setColor(SK_ColorWHITE);
5536 canvas->drawPath(path, paint);
5537 }
5538};
5539
5540#Function ##
5541void draw(SkCanvas* canvas) {
5542 sk_sp<SkDrawable> drawable(new MyDrawable);
5543 SkMatrix matrix;
5544 matrix.setTranslate(10, 10);
5545 canvas->drawDrawable(drawable.get(), &matrix);
5546}
5547##
5548
5549#ToDo incomplete ##
5550
5551##
5552
5553# ------------------------------------------------------------------------------
5554
5555#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
5556
5557Draw Drawable drawable using Clip and Matrix, offset by (x, y).
5558
5559If Canvas has an asynchronous implementation, as is the case
5560when it is recording into Picture, then drawable will be referenced,
5561so that SkDrawable::draw() can be called when the operation is finalized. To force
5562immediate drawing, call SkDrawable::draw() instead.
5563
5564#Param drawable Custom struct encapsulating drawing commands. ##
5565#Param x Offset into Canvas writable pixels in x. ##
5566#Param y Offset into Canvas writable pixels in y. ##
5567
5568#Example
5569#Height 100
5570#Function
5571struct MyDrawable : public SkDrawable {
5572 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
5573
5574 void onDraw(SkCanvas* canvas) override {
5575 SkPath path;
5576 path.conicTo(10, 90, 50, 90, 0.9f);
5577 SkPaint paint;
5578 paint.setColor(SK_ColorBLUE);
5579 canvas->drawRect(path.getBounds(), paint);
5580 paint.setAntiAlias(true);
5581 paint.setColor(SK_ColorWHITE);
5582 canvas->drawPath(path, paint);
5583 }
5584};
5585
5586#Function ##
5587void draw(SkCanvas* canvas) {
5588 sk_sp<SkDrawable> drawable(new MyDrawable);
5589 canvas->drawDrawable(drawable.get(), 10, 10);
5590}
5591##
5592
5593#ToDo incomplete ##
5594
5595##
5596
5597# ------------------------------------------------------------------------------
5598
5599#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
5600
5601Associate Rect on Canvas when an annotation; a key-value pair, where the key is
5602a null-terminated utf8 string, and optional value is stored as Data.
5603
5604Only some canvas implementations, such as recording to Picture, or drawing to
5605Document_PDF, use annotations.
5606
5607#Param rect Rect extent of canvas to annotate. ##
5608#Param key String used for lookup. ##
5609#Param value Data holding value stored in annotation. ##
5610
5611#Example
5612 #Height 1
5613 const char text[] = "Click this link!";
5614 SkRect bounds;
5615 SkPaint paint;
5616 paint.setTextSize(40);
5617 (void)paint.measureText(text, strlen(text), &bounds);
5618 const char url[] = "https://www.google.com/";
5619 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
5620 canvas->drawAnnotation(bounds, "url_key", urlData.get());
5621##
5622
5623#ToDo incomplete ##
5624
5625##
5626
5627# ------------------------------------------------------------------------------
5628
5629#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
5630
5631Associate Rect on Canvas when an annotation; a key-value pair, where the key is
5632a null-terminated utf8 string, and optional value is stored as Data.
5633
5634Only some canvas implementations, such as recording to Picture, or drawing to
5635Document_PDF, use annotations.
5636
5637#Param rect Rect extent of canvas to annotate. ##
5638#Param key String used for lookup. ##
5639#Param value Data holding value stored in annotation. ##
5640
5641#Example
5642#Height 1
5643 const char text[] = "Click this link!";
5644 SkRect bounds;
5645 SkPaint paint;
5646 paint.setTextSize(40);
5647 (void)paint.measureText(text, strlen(text), &bounds);
5648 const char url[] = "https://www.google.com/";
5649 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
5650 canvas->drawAnnotation(bounds, "url_key", urlData.get());
5651##
5652
5653#ToDo incomplete ##
5654
5655##
5656
5657#Method SkDrawFilter* getDrawFilter() const
5658
5659Legacy call to be deprecated.
5660
5661#Deprecated
5662##
5663
5664##
5665
5666#Method virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter)
5667
5668Legacy call to be deprecated.
5669
5670#Deprecated
5671##
5672
5673##
5674
5675# ------------------------------------------------------------------------------
5676
5677#Method virtual bool isClipEmpty() const
5678
5679Returns true if Clip is empty; that is, nothing will draw.
5680
5681isClipEmpty may do work when called; it should not be called
5682more often than needed. However, once called, subsequent calls perform no
5683work until Clip changes.
5684
5685#Return true if Clip is empty. ##
5686
5687#Example
5688 void draw(SkCanvas* canvas) {
5689 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
5690 SkPath path;
5691 canvas->clipPath(path);
5692 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
5693 }
5694 #StdOut
5695 clip is not empty
5696 clip is empty
5697 ##
5698##
5699
5700#ToDo incomplete ##
5701
5702##
5703
5704# ------------------------------------------------------------------------------
5705
5706#Method virtual bool isClipRect() const
5707
5708Returns true if Clip is Rect and not empty.
5709Returns false if the clip is empty, or if it is not Rect.
5710
5711#Return true if Clip is Rect and not empty. ##
5712
5713#Example
5714 void draw(SkCanvas* canvas) {
5715 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
5716 canvas->clipRect({0, 0, 0, 0});
5717 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
5718 }
5719 #StdOut
5720 clip is rect
5721 clip is not rect
5722 ##
5723##
5724
5725#ToDo incomplete ##
5726
5727##
5728
5729#Class SkCanvas ##
5730#Topic Canvas ##