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