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