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