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