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