Home | History | Annotate | Download | only in docs
      1 #Topic Canvas
      2 #Alias Canvas_Reference ##
      3 
      4 #Class SkCanvas
      5 
      6 #Code
      7 #Populate
      8 ##
      9 
     10 Canvas provides an interface for drawing, and how the drawing is clipped and transformed.
     11 Canvas contains a stack of Matrix and Clip values.
     12 
     13 Canvas and Paint together provide the state to draw into Surface or Device.
     14 Each Canvas draw call transforms the geometry of the object by the concatenation of all
     15 Matrix values in the stack. The transformed geometry is clipped by the intersection
     16 of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing
     17 state such as Color, Typeface, text size, stroke width, Shader and so on.
     18 
     19 To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
     20 Request Canvas from Surface to obtain the interface to draw.
     21 Canvas generated by Raster_Surface draws to memory visible to the CPU.
     22 Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
     23 
     24 To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
     25 Document based Canvas and other Canvas subclasses reference Device describing the
     26 destination.
     27 
     28 Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
     29 This approach may be deprecated in the future.
     30 
     31 Canvas may be created directly when no Surface is required; some Canvas methods
     32 implicitly create Raster_Surface.
     33 
     34 # ------------------------------------------------------------------------------
     35 
     36 #Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
     37                                                           size_t rowBytes,
     38                                                           const SkSurfaceProps* props = nullptr)
     39 #In Constructors
     40 #Line # creates from SkImageInfo and Pixel_Storage ##
     41 #Populate
     42 
     43 #Example
     44     #Description
     45         Allocates a three by three bitmap, clears it to white, and draws a black pixel
     46         in the center.
     47     ##
     48 void draw(SkCanvas* ) {
     49     SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3);  // device aligned, 32 bpp, Premultiplied
     50     const size_t minRowBytes = info.minRowBytes();  // bytes used by one bitmap row
     51     const size_t size = info.computeMinByteSize();  // bytes used by all rows
     52     SkAutoTMalloc<SkPMColor> storage(size);  // allocate storage for pixels
     53     SkPMColor* pixels = storage.get();  // get pointer to allocated storage
     54     // create a SkCanvas backed by a raster device, and delete it when the
     55     // function goes out of scope.
     56     std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
     57     canvas->clear(SK_ColorWHITE);  // white is Unpremultiplied, in ARGB order
     58     canvas->flush();  // ensure that pixels are cleared
     59     SkPMColor pmWhite = pixels[0];  // the Premultiplied format may vary
     60     SkPaint paint;  // by default, draws black
     61     canvas->drawPoint(1, 1, paint);  // draw in the center
     62     canvas->flush();  // ensure that point was drawn
     63     for (int y = 0; y < info.height(); ++y) {
     64         for (int x = 0; x < info.width(); ++x) {
     65             SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
     66         }
     67         SkDebugf("\n");
     68     }
     69 }
     70     #StdOut
     71         ---
     72         -x-
     73         ---
     74     ##
     75 ##
     76 
     77 #SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
     78 
     79 ##
     80 
     81 # ------------------------------------------------------------------------------
     82 
     83 #Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
     84                                                          size_t rowBytes)
     85 #In Constructors
     86 #Line # creates from image data and Pixel_Storage ##
     87 #Populate
     88 
     89 #Example
     90     #Description
     91         Allocates a three by three bitmap, clears it to white, and draws a black pixel
     92         in the center.
     93     ##
     94 void draw(SkCanvas* ) {
     95     const int width = 3;
     96     const int height = 3;
     97     SkPMColor pixels[height][width];  // allocate a 3 by 3 Premultiplied bitmap on the stack
     98     // create a SkCanvas backed by a raster device, and delete it when the
     99     // function goes out of scope.
    100     std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
    101             width,
    102             height,
    103             pixels[0],  // top-left of the bitmap
    104             sizeof(pixels[0]));  // byte width of the each row
    105     // write a Premultiplied value for white into all pixels in the bitmap
    106     canvas->clear(SK_ColorWHITE);
    107     SkPMColor pmWhite = pixels[0][0];  // the Premultiplied format may vary
    108     SkPaint paint;  // by default, draws black
    109     canvas->drawPoint(1, 1, paint);  // draw in the center
    110     canvas->flush();  // ensure that pixels is ready to be read
    111     for (int y = 0; y < height; ++y) {
    112         for (int x = 0; x < width; ++x) {
    113             SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
    114         }
    115         SkDebugf("\n");
    116     }
    117 }
    118     #StdOut
    119         ---
    120         -x-
    121         ---
    122     ##
    123 ##
    124 
    125 #SeeAlso MakeRasterDirect SkSurface::MakeRasterDirect SkImageInfo::MakeN32Premul
    126 
    127 ##
    128 
    129 # ------------------------------------------------------------------------------
    130 
    131 #Method SkCanvas()
    132 
    133 #Line # creates with no Surface, no dimensions ##
    134 #Populate
    135 
    136 #Example
    137 
    138 #Description
    139 Passes a placeholder to a function that requires one.
    140 ##
    141 
    142 #Function
    143 static void check_for_rotated_ctm(const SkCanvas* canvas) {
    144     const SkMatrix& matrix = canvas->getTotalMatrix();
    145     SkDebugf("rect stays rect is %s\n", matrix.rectStaysRect() ? "true" : "false");
    146 }
    147 
    148 ##
    149 void draw(SkCanvas* canvas) {
    150     check_for_rotated_ctm(canvas);
    151     canvas->rotate(30);
    152     check_for_rotated_ctm(canvas);
    153 
    154     SkCanvas defaultCanvas;
    155     check_for_rotated_ctm(&defaultCanvas);
    156 }
    157 
    158     #StdOut
    159         rect stays rect is true
    160         rect stays rect is false
    161         rect stays rect is true
    162     ##
    163 ##
    164 
    165 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
    166 
    167 ##
    168 
    169 # ------------------------------------------------------------------------------
    170 
    171 #Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
    172 
    173 #Line # creates with no Surface, set dimensions, Surface_Properties ##
    174 #Populate
    175 
    176 #Example
    177     SkCanvas canvas(10, 20);  // 10 units wide, 20 units high
    178     canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10));  // clip is outside canvas' device
    179     SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
    180 
    181     #StdOut
    182         canvas is empty
    183     ##
    184 ##
    185 
    186 #SeeAlso MakeRasterDirect SkSurfaceProps SkPixelGeometry SkCreateColorSpaceXformCanvas
    187 
    188 ##
    189 
    190 # ------------------------------------------------------------------------------
    191 
    192 #Method explicit SkCanvas(const SkBitmap& bitmap)
    193 
    194 #Line # uses existing Bitmap ##
    195 #Populate
    196 
    197 #Example
    198 #Description
    199 The actual output depends on the installed fonts.
    200 ##
    201     SkBitmap bitmap;
    202     // create a bitmap 5 wide and 11 high
    203     bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
    204     SkCanvas canvas(bitmap);
    205     canvas.clear(SK_ColorWHITE);  // white is Unpremultiplied, in ARGB order
    206     SkPixmap pixmap;  // provides guaranteed access to the drawn pixels
    207     if (!canvas.peekPixels(&pixmap)) {
    208         SkDebugf("peekPixels should never fail.\n");
    209     }
    210     const SkPMColor* pixels = pixmap.addr32();  // points to top-left of bitmap
    211     SkPMColor pmWhite = pixels[0];  // the Premultiplied format may vary
    212     SkPaint paint;  // by default, draws black, 12 point text
    213     canvas.drawString("!", 1, 10, SkFont(), paint);  // 1 char at baseline (1, 10)
    214     for (int y = 0; y < bitmap.height(); ++y) {
    215         for (int x = 0; x < bitmap.width(); ++x) {
    216             SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
    217         }
    218         SkDebugf("\n");
    219     }
    220 
    221     #StdOut
    222     -----
    223     ---x-
    224     ---x-
    225     ---x-
    226     ---x-
    227     ---x-
    228     ---x-
    229     -----
    230     ---x-
    231     ---x-
    232     -----
    233     #StdOut ##
    234 ##
    235 
    236 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
    237 
    238 ##
    239 
    240 # ------------------------------------------------------------------------------
    241 
    242 #Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
    243 
    244 #Line # uses existing Bitmap and Surface_Properties ##
    245 #Populate
    246 
    247 #Example
    248 #Description
    249 The actual output depends on the installed fonts.
    250 ##
    251     SkBitmap bitmap;
    252     // create a bitmap 5 wide and 11 high
    253     bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
    254     SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
    255     canvas.clear(SK_ColorWHITE);  // white is Unpremultiplied, in ARGB order
    256     SkPixmap pixmap;  // provides guaranteed access to the drawn pixels
    257     if (!canvas.peekPixels(&pixmap)) {
    258         SkDebugf("peekPixels should never fail.\n");
    259     }
    260     const SkPMColor* pixels = pixmap.addr32();  // points to top-left of bitmap
    261     SkPMColor pmWhite = pixels[0];  // the Premultiplied format may vary
    262     SkPaint paint;  // by default, draws black, 12 point text
    263     canvas.drawString("!", 1, 10, SkFont(), paint);  // 1 char at baseline (1, 10)
    264     for (int y = 0; y < bitmap.height(); ++y) {
    265         for (int x = 0; x < bitmap.width(); ++x) {
    266             SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
    267         }
    268         SkDebugf("\n");
    269     }
    270 
    271     #StdOut
    272     -----
    273     ---x-
    274     ---x-
    275     ---x-
    276     ---x-
    277     ---x-
    278     ---x-
    279     -----
    280     ---x-
    281     ---x-
    282     -----
    283     #StdOut ##
    284 ##
    285 
    286 #SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
    287 
    288 ##
    289 
    290 # ------------------------------------------------------------------------------
    291 
    292 #Method virtual ~SkCanvas()
    293 
    294 #Line # draws saved Layers, frees resources ##
    295 #Populate
    296 
    297 #Example
    298 #Description
    299 Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
    300 drawing surface that blends with the bitmap. When Layer goes out of
    301 scope, Layer destructor is called. The saved Layer is restored, drawing
    302 transparent letters.
    303 ##
    304 void draw(SkCanvas* canvas) {
    305     SkBitmap bitmap;
    306     bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
    307     {
    308         SkCanvas offscreen(bitmap);
    309         SkPaint paint;
    310         SkFont font(nullptr, 100);
    311         offscreen.drawString("ABC", 20, 160, font, paint);
    312         SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
    313         offscreen.saveLayerAlpha(&layerBounds, 128);
    314         offscreen.clear(SK_ColorWHITE);
    315         offscreen.drawString("DEF", 20, 160, font, paint);
    316     }
    317     canvas->drawBitmap(bitmap, 0, 0, nullptr);
    318 }
    319 ##
    320 
    321 #SeeAlso State_Stack
    322 
    323 ##
    324 
    325 # ------------------------------------------------------------------------------
    326 #Subtopic Property
    327 #Line # metrics and attributes ##
    328 ##
    329 
    330 #Method SkMetaData& getMetaData()
    331 #In Property
    332 #In Utility
    333 #Line # associates additional data with the canvas ##
    334 #Populate
    335 
    336 #Example
    337     const char* kHelloMetaData = "HelloMetaData";
    338     SkCanvas canvas;
    339     SkMetaData& metaData = canvas.getMetaData();
    340     SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
    341     metaData.setString(kHelloMetaData, "Hello!");
    342     SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
    343     metaData.removeString(kHelloMetaData);
    344     SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
    345 
    346     #StdOut
    347         before: (null)
    348         during: Hello!
    349         after: (null)
    350     #StdOut ##
    351 ##
    352 
    353 #SeeAlso SkMetaData
    354 
    355 ##
    356 
    357 # ------------------------------------------------------------------------------
    358 
    359 #Method SkImageInfo imageInfo() const
    360 #In Property
    361 #Line # returns Image_Info for Canvas ##
    362 #Populate
    363 
    364 #Example
    365     SkCanvas emptyCanvas;
    366     SkImageInfo canvasInfo = emptyCanvas.imageInfo();
    367     SkImageInfo emptyInfo;
    368     SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
    369 
    370     #StdOut
    371         emptyInfo == canvasInfo
    372     ##
    373 ##
    374 
    375 #SeeAlso SkImageInfo MakeRasterDirect makeSurface
    376 
    377 ##
    378 
    379 # ------------------------------------------------------------------------------
    380 
    381 #Method bool getProps(SkSurfaceProps* props) const
    382 #In Property
    383 #Line # copies Surface_Properties if available ##
    384 #Populate
    385 
    386 #Example
    387     SkBitmap bitmap;
    388     SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
    389     SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
    390     SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
    391     if (!canvas.getProps(&surfaceProps)) {
    392         SkDebugf("getProps failed unexpectedly.\n");
    393     }
    394     SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
    395 
    396     #StdOut
    397         isRGB:0
    398         isRGB:1
    399     #StdOut ##
    400 ##
    401 
    402 #SeeAlso SkSurfaceProps makeSurface
    403 
    404 ##
    405 
    406 # ------------------------------------------------------------------------------
    407 #Subtopic Utility
    408 #Line # rarely called management functions ##
    409 ##
    410 
    411 #Method void flush()
    412 #In Utility
    413 #Line # triggers execution of all pending draw operations ##
    414 #Populate
    415 
    416 #NoExample
    417 ##
    418 
    419 #SeeAlso peekPixels SkSurface::flush GrContext::flush GrContext::abandonContext
    420 
    421 ##
    422 
    423 # ------------------------------------------------------------------------------
    424 
    425 #Method virtual SkISize getBaseLayerSize() const
    426 #In Property
    427 #Line # returns size of base Layer in global coordinates ##
    428 #Populate
    429 
    430 #Example
    431     SkBitmap bitmap;
    432     bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
    433     SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
    434     canvas.clipRect(SkRect::MakeWH(10, 40));
    435     SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
    436     if (clipDeviceBounds.isEmpty()) {
    437         SkDebugf("Empty clip bounds is unexpected!\n");
    438     }
    439     SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
    440     SkISize baseLayerSize = canvas.getBaseLayerSize();
    441     SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
    442 
    443     #StdOut
    444         clip=10,30
    445         size=20,30
    446     ##
    447 ##
    448 
    449 #ToDo is this the same as the width and height of surface? ##
    450 
    451 #SeeAlso getDeviceClipBounds
    452 
    453 ##
    454 
    455 # ------------------------------------------------------------------------------
    456 
    457 #Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
    458 #In Constructors
    459 #Line # creates Surface matching SkImageInfo and SkSurfaceProps ##
    460 #Populate
    461 
    462 #Example
    463     sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
    464     SkCanvas* smallCanvas = surface->getCanvas();
    465     SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
    466     sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
    467     SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
    468     SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
    469 
    470     #StdOut
    471         compatible != nullptr
    472         size = 3, 4
    473     ##
    474 ##
    475 
    476 #SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps
    477 
    478 ##
    479 
    480 # ------------------------------------------------------------------------------
    481 
    482 #Method virtual GrContext* getGrContext()
    483 #In Property
    484 #Line # returns GPU_Context of the GPU_Surface ##
    485 #Populate
    486 
    487 #Example
    488 void draw(SkCanvas* canvas) {
    489     if (canvas->getGrContext()) {
    490          canvas->clear(SK_ColorRED);
    491     } else {
    492          canvas->clear(SK_ColorBLUE);
    493     }
    494 }
    495 ##
    496 
    497 #ToDo fiddle should show both CPU and GPU out ##
    498 
    499 #SeeAlso GrContext
    500 
    501 ##
    502 
    503 # ------------------------------------------------------------------------------
    504 
    505 #Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
    506 #In Utility
    507 #In Property
    508 #Line # returns writable pixel access if available ##
    509 #Populate
    510 
    511 #Example
    512 void draw(SkCanvas* canvas) {
    513     if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
    514          canvas->clear(SK_ColorRED);
    515     } else {
    516          canvas->clear(SK_ColorBLUE);
    517     }
    518 }
    519 ##
    520 
    521 #Example
    522 #Description
    523 Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
    524 Layer to add a large dotted "DEF". Finally blends Layer with the
    525 device.
    526 
    527 The Layer and blended result appear on the CPU and GPU but the large dotted
    528 "DEF" appear only on the CPU.
    529 ##
    530 void draw(SkCanvas* canvas) {
    531   SkPaint paint;
    532   SkFont font(nullptr, 100);
    533   canvas->drawString("ABC", 20, 160, font, paint);
    534   SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
    535   canvas->saveLayerAlpha(&layerBounds, 128);
    536   canvas->clear(SK_ColorWHITE);
    537   canvas->drawString("DEF", 20, 160, font, paint);
    538   SkImageInfo imageInfo;
    539   size_t rowBytes;
    540   SkIPoint origin;
    541   uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
    542   if (access) {
    543     int h = imageInfo.height();
    544     int v = imageInfo.width();
    545     int rowWords = rowBytes / sizeof(uint32_t);
    546     for (int y = 0; y < h; ++y) {
    547         int newY = (y - h / 2) * 2 + h / 2;
    548         if (newY < 0 || newY >= h) {
    549             continue;
    550         }
    551         for (int x = 0; x < v; ++x) {
    552             int newX = (x - v / 2) * 2 + v / 2;
    553             if (newX < 0 || newX >= v) {
    554                 continue;
    555             }
    556             if (access[y * rowWords + x] == SK_ColorBLACK) {
    557                 access[newY * rowWords + newX] = SK_ColorGRAY;
    558             }
    559         }
    560     }
    561 
    562   }
    563   canvas->restore();
    564 }
    565 ##
    566 
    567 #ToDo there are no callers of this that I can find. Deprecate? ##
    568 #ToDo fiddle should show both CPU and GPU out ##
    569 
    570 #SeeAlso SkImageInfo SkPixmap
    571 
    572 ##
    573 
    574 # ------------------------------------------------------------------------------
    575 
    576 #Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
    577 #In Utility
    578 #In Property
    579 #Line # returns context that tracks Clip and Matrix ##
    580 #Populate
    581 
    582 #Example
    583 #Description
    584 #ToDo ##
    585 ##
    586 #Function
    587     static void DeleteCallback(void*, void* context) {
    588         delete (char*) context;
    589     }
    590 
    591     class CustomAllocator : public SkRasterHandleAllocator {
    592     public:
    593         bool allocHandle(const SkImageInfo& info, Rec* rec) override {
    594             char* context = new char[4]{'s', 'k', 'i', 'a'};
    595             rec->fReleaseProc = DeleteCallback;
    596             rec->fReleaseCtx = context;
    597             rec->fHandle = context;
    598             rec->fPixels = context;
    599             rec->fRowBytes = 4;
    600             return true;
    601         }
    602 
    603         void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
    604             // apply canvas matrix and clip to custom environment
    605         }
    606     };
    607 
    608 ##
    609     void draw(SkCanvas* canvas) {
    610         const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    611         std::unique_ptr<SkCanvas> c2 =
    612                 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
    613                 new CustomAllocator()), info);
    614         char* context = (char*) c2->accessTopRasterHandle();
    615         SkDebugf("context = %.4s\n", context);
    616 
    617     }
    618     #StdOut
    619         context = skia
    620     ##
    621     #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
    622 ##
    623 
    624 #SeeAlso SkRasterHandleAllocator
    625 
    626 ##
    627 
    628 # ------------------------------------------------------------------------------
    629 #Subtopic Pixels
    630 #Line # read and write pixel values ##
    631 ##
    632 
    633 #Method bool peekPixels(SkPixmap* pixmap)
    634 #In Pixels
    635 #Line # returns if Canvas has direct access to its pixels ##
    636 #Populate
    637 
    638 #Example
    639     SkPixmap pixmap;
    640     if (canvas->peekPixels(&pixmap)) {
    641         SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
    642     }
    643     #StdOut
    644         width=256 height=256
    645     ##
    646 ##
    647 
    648 #SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels
    649 
    650 ##
    651 
    652 # ------------------------------------------------------------------------------
    653 
    654 #Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
    655                     int srcX, int srcY)
    656 #In Pixels
    657 #Line # copies and converts rectangle of pixels from Canvas ##
    658 
    659 Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are
    660 ignored.
    661 
    662 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
    663 Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
    664 Copies each readable pixel intersecting both rectangles, without scaling,
    665 converting to dstInfo.colorType() and dstInfo.alphaType() if required.
    666 
    667 Pixels are readable when Device is raster, or backed by a GPU.
    668 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
    669 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
    670 class like SkDebugCanvas.
    671 
    672 The destination pixel storage must be allocated by the caller.
    673 
    674 Pixel values are converted only if Color_Type and Alpha_Type
    675 do not match. Only pixels within both source and destination rectangles
    676 are copied. dstPixels contents outside Rect intersection are unchanged.
    677 
    678 Pass negative values for srcX or srcY to offset pixels across or down destination.
    679 
    680 Does not copy, and returns false if:
    681 
    682 #List
    683 # Source and destination rectangles do not intersect. ##
    684 # Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
    685 # Canvas pixels are not readable; for instance, Canvas is document-based. ##
    686 # dstRowBytes is too small to contain one row of pixels. ##
    687 ##
    688 
    689 #Param dstInfo  width, height, Color_Type, and Alpha_Type of dstPixels ##
    690 #Param dstPixels  storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
    691 #Param dstRowBytes  size of one destination row; dstInfo.width() times pixel size, or larger ##
    692 #Param srcX  offset into readable pixels on x-axis; may be negative ##
    693 #Param srcY  offset into readable pixels on y-axis; may be negative ##
    694 
    695 #Return  true if pixels were copied ##
    696 
    697 #Example
    698 #Width 64
    699 #Height 64
    700 #Description
    701     A black circle drawn on a blue background provides an image to copy.
    702     readPixels copies one quarter of the canvas into each of the four corners.
    703     The copied quarter circles overdraw the original circle.
    704 ##
    705     canvas->clear(SK_ColorBLUE);
    706     SkPaint paint;
    707     canvas->drawCircle(32, 32, 28, paint);
    708     SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
    709     sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
    710     sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
    711     for (int x : { 32, -32 } ) {
    712         for (int y : { 32, -32 } ) {
    713             canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
    714         }
    715     }
    716     sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
    717     canvas->drawImage(image, 0, 0);
    718 ##
    719 
    720 #Example
    721 #Description
    722     Canvas returned by Raster_Surface has Premultiplied pixel values.
    723     clear() takes Unpremultiplied input with Color_Alpha equal 0x80
    724     and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
    725     to generate Premultiplied value 0x802B5580. readPixels converts pixel back
    726     to Unpremultiplied value 0x8056A9FF, introducing error.
    727 ##
    728     canvas->clear(0x8055aaff);
    729     for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
    730         uint32_t pixel = 0;
    731         SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
    732         if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
    733             SkDebugf("pixel = %08x\n", pixel);
    734         }
    735     }
    736 
    737     #StdOut
    738         pixel = 802b5580
    739         pixel = 8056a9ff
    740     ##
    741 ##
    742 
    743 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
    744 
    745 ##
    746 
    747 # ------------------------------------------------------------------------------
    748 
    749 #Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
    750 
    751 Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are
    752 ignored.
    753 
    754 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
    755 Destination Rect corners are (0, 0) and (pixmap.width(), pixmap.height()).
    756 Copies each readable pixel intersecting both rectangles, without scaling,
    757 converting to pixmap.colorType() and pixmap.alphaType() if required.
    758 
    759 Pixels are readable when Device is raster, or backed by a GPU.
    760 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
    761 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
    762 class like SkDebugCanvas.
    763 
    764 Caller must allocate pixel storage in pixmap if needed.
    765 
    766 Pixel values are converted only if Color_Type and Alpha_Type
    767 do not match. Only pixels within both source and destination Rects
    768 are copied. pixmap pixels contents outside Rect intersection are unchanged.
    769 
    770 Pass negative values for srcX or srcY to offset pixels across or down pixmap.
    771 
    772 Does not copy, and returns false if:
    773 
    774 #List
    775 # Source and destination rectangles do not intersect. ##
    776 # Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
    777 # Canvas pixels are not readable; for instance, Canvas is document-based. ##
    778 # Pixmap pixels could not be allocated. ##
    779 # pixmap.rowBytes() is too small to contain one row of pixels. ##
    780 ##
    781 
    782 #Param pixmap  storage for pixels copied from Canvas ##
    783 #Param srcX    offset into readable pixels on x-axis; may be negative ##
    784 #Param srcY    offset into readable pixels on y-axis; may be negative ##
    785 
    786 #Return  true if pixels were copied ##
    787 
    788 #Example
    789     #Description
    790         clear() takes Unpremultiplied input with Color_Alpha equal 0x80
    791         and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
    792         to generate Premultiplied value 0x802B5580.
    793     ##
    794     void draw(SkCanvas* canvas) {
    795         canvas->clear(0x8055aaff);
    796         uint32_t pixels[1] = { 0 };
    797         SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
    798         canvas->readPixels(pixmap, 0, 0);
    799         SkDebugf("pixel = %08x\n", pixels[0]);
    800     }
    801     #StdOut
    802         pixel = 802b5580
    803     ##
    804 ##
    805 
    806 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
    807 
    808 ##
    809 
    810 # ------------------------------------------------------------------------------
    811 
    812 #Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
    813 
    814 Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are
    815 ignored.
    816 
    817 Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
    818 Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
    819 Copies each readable pixel intersecting both rectangles, without scaling,
    820 converting to bitmap.colorType() and bitmap.alphaType() if required.
    821 
    822 Pixels are readable when Device is raster, or backed by a GPU.
    823 Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
    824 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
    825 class like SkDebugCanvas.
    826 
    827 Caller must allocate pixel storage in bitmap if needed.
    828 
    829 Bitmap values are converted only if Color_Type and Alpha_Type
    830 do not match. Only pixels within both source and destination rectangles
    831 are copied. Bitmap pixels outside Rect intersection are unchanged.
    832 
    833 Pass negative values for srcX or srcY to offset pixels across or down bitmap.
    834 
    835 Does not copy, and returns false if:
    836 
    837 #List
    838 # Source and destination rectangles do not intersect. ##
    839 # Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
    840 # Canvas pixels are not readable; for instance, Canvas is document-based. ##
    841 # bitmap pixels could not be allocated. ##
    842 # bitmap.rowBytes() is too small to contain one row of pixels. ##
    843 ##
    844 
    845 #Param bitmap  storage for pixels copied from Canvas ##
    846 #Param srcX    offset into readable pixels on x-axis; may be negative ##
    847 #Param srcY    offset into readable pixels on y-axis; may be negative ##
    848 
    849 #Return  true if pixels were copied ##
    850 
    851 #Example
    852     #Description
    853         clear() takes Unpremultiplied input with Color_Alpha equal 0x80
    854         and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
    855         to generate Premultiplied value 0x802B5580.
    856     ##
    857 void draw(SkCanvas* canvas) {
    858     canvas->clear(0x8055aaff);
    859     SkBitmap bitmap;
    860     bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
    861     canvas->readPixels(bitmap, 0, 0);
    862     SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
    863 }
    864     #StdOut
    865         pixel = 802b5580
    866     ##
    867 ##
    868 
    869 #SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
    870 
    871 ##
    872 
    873 # ------------------------------------------------------------------------------
    874 
    875 #Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
    876 #In Pixels
    877 #Line # copies and converts rectangle of pixels to Canvas ##
    878 Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
    879 Source Rect corners are (0, 0) and (info.width(), info.height()).
    880 Destination Rect corners are (x, y) and
    881 (imageInfo().width(), imageInfo().height()).
    882 
    883 Copies each readable pixel intersecting both rectangles, without scaling,
    884 converting to imageInfo().colorType() and imageInfo().alphaType() if required.
    885 
    886 Pixels are writable when Device is raster, or backed by a GPU.
    887 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
    888 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
    889 class like SkDebugCanvas.
    890 
    891 Pixel values are converted only if Color_Type and Alpha_Type
    892 do not match. Only pixels within both source and destination rectangles
    893 are copied. Canvas pixels outside Rect intersection are unchanged.
    894 
    895 Pass negative values for x or y to offset pixels to the left or
    896 above Canvas pixels.
    897 
    898 Does not copy, and returns false if:
    899 
    900 #List
    901 # Source and destination rectangles do not intersect. ##
    902 # pixels could not be converted to Canvas imageInfo().colorType() or
    903   imageInfo().alphaType(). ##
    904 # Canvas pixels are not writable; for instance, Canvas is document-based. ##
    905 # rowBytes is too small to contain one row of pixels. ##
    906 ##
    907 
    908 #Param info  width, height, Color_Type, and Alpha_Type of pixels ##
    909 #Param pixels  pixels to copy, of size info.height() times rowBytes, or larger ##
    910 #Param rowBytes  size of one row of pixels; info.width() times pixel size, or larger ##
    911 #Param x  offset into Canvas writable pixels on x-axis; may be negative ##
    912 #Param y  offset into Canvas writable pixels on y-axis; may be negative ##
    913 
    914 #Return  true if pixels were written to Canvas ##
    915 
    916 #Example
    917     SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
    918     for (int y = 0; y < 256; ++y) {
    919         uint32_t pixels[256];
    920         for (int x = 0; x < 256; ++x) {
    921             pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
    922         }
    923         canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
    924     }
    925 ##
    926 
    927 #SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
    928 
    929 ##
    930 
    931 # ------------------------------------------------------------------------------
    932 
    933 #Method bool writePixels(const SkBitmap& bitmap, int x, int y)
    934 
    935 Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
    936 Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
    937 
    938 Destination Rect corners are (x, y) and
    939 (imageInfo().width(), imageInfo().height()).
    940 
    941 Copies each readable pixel intersecting both rectangles, without scaling,
    942 converting to imageInfo().colorType() and imageInfo().alphaType() if required.
    943 
    944 Pixels are writable when Device is raster, or backed by a GPU.
    945 Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
    946 returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
    947 class like SkDebugCanvas.
    948 
    949 Pixel values are converted only if Color_Type and Alpha_Type
    950 do not match. Only pixels within both source and destination rectangles
    951 are copied. Canvas pixels outside Rect intersection are unchanged.
    952 
    953 Pass negative values for x or y to offset pixels to the left or
    954 above Canvas pixels.
    955 
    956 Does not copy, and returns false if:
    957 
    958 #List
    959 # Source and destination rectangles do not intersect. ##
    960 # bitmap does not have allocated pixels. ##
    961 # bitmap pixels could not be converted to Canvas imageInfo().colorType() or
    962   imageInfo().alphaType(). ##
    963 # Canvas pixels are not writable; for instance, Canvas is document based. ##
    964 # bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
    965 ##
    966 
    967 #Param bitmap  contains pixels copied to Canvas ##
    968 #Param x       offset into Canvas writable pixels in x; may be negative ##
    969 #Param y       offset into Canvas writable pixels in y; may be negative ##
    970 
    971 #Return  true if pixels were written to Canvas ##
    972 
    973 #Example
    974 void draw(SkCanvas* canvas) {
    975     SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
    976     SkBitmap bitmap;
    977     bitmap.setInfo(imageInfo);
    978     uint32_t pixels[4];
    979     bitmap.setPixels(pixels);
    980     for (int y = 0; y < 256; y += 2) {
    981         for (int x = 0; x < 256;  x += 2) {
    982             pixels[0] = SkColorSetRGB(x, y, x | y);
    983             pixels[1] = SkColorSetRGB(x ^ y, y, x);
    984             pixels[2] = SkColorSetRGB(x, x & y, y);
    985             pixels[3] = SkColorSetRGB(~x, ~y, x);
    986             canvas->writePixels(bitmap, x, y);
    987         }
    988     }
    989 }
    990 ##
    991 
    992 #SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
    993 
    994 ##
    995 
    996 # ------------------------------------------------------------------------------
    997 #Subtopic State_Stack
    998 #Line # stack of state for hierarchical drawing ##
    999 
   1000 Canvas maintains a stack of state that allows hierarchical drawing, commonly used
   1001 to implement windows and views. The initial state has an identity matrix and and
   1002 an infinite clip. Even with a wide-open clip, drawing is constrained by the
   1003 bounds of the Canvas Surface or Device.
   1004 
   1005 Canvas savable state consists of Clip and Matrix.
   1006 Clip describes the area that may be drawn to.
   1007 Matrix transforms the geometry.
   1008 
   1009 save(), saveLayer, and saveLayerAlpha
   1010 save state and return the depth of the stack.
   1011 
   1012 restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
   1013 
   1014 Each state on the stack intersects Clip with the previous Clip,
   1015 and concatenates Matrix with the previous Matrix.
   1016 The intersected Clip makes the drawing area the same or smaller;
   1017 the concatenated Matrix may move the origin and potentially scale or rotate
   1018 the coordinate space.
   1019 
   1020 Canvas does not require balancing the state stack but it is a good idea
   1021 to do so. Calling save() without restore() will eventually cause Skia to fail;
   1022 mismatched save() and restore() create hard to find bugs.
   1023 
   1024 It is not possible to use state to draw outside of the clip defined by the
   1025 previous state.
   1026 
   1027 #Example
   1028 #Description
   1029 Draw to ever smaller clips; then restore drawing to full canvas.
   1030 Note that the second clipRect is not permitted to enlarge Clip.
   1031 ##
   1032 #Height 160
   1033 void draw(SkCanvas* canvas) {
   1034     SkPaint paint;
   1035     canvas->save();                             // records stack depth to restore
   1036     canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
   1037     canvas->clear(SK_ColorRED);                 // draws to limit of clip
   1038     canvas->save();                             // records stack depth to restore
   1039     canvas->clipRect(SkRect::MakeWH(50, 150));  // Rect below 100 is ignored
   1040     canvas->clear(SK_ColorBLUE);                // draws to smaller clip
   1041     canvas->restore();                          // enlarges clip
   1042     canvas->drawLine(20, 20, 150, 150, paint);  // line below 100 is not drawn
   1043     canvas->restore();                          // enlarges clip
   1044     canvas->drawLine(150, 20, 50, 120, paint);  // line below 100 is drawn
   1045 }
   1046 ##
   1047 
   1048 Each Clip uses the current Matrix for its coordinates.
   1049 
   1050 #Example
   1051 #Description
   1052 While clipRect is given the same rectangle twice, Matrix makes the second
   1053 clipRect draw at half the size of the first.
   1054 ##
   1055 #Height 128
   1056 void draw(SkCanvas* canvas) {
   1057     canvas->clipRect(SkRect::MakeWH(100, 100));
   1058     canvas->clear(SK_ColorRED);
   1059     canvas->scale(.5, .5);
   1060     canvas->clipRect(SkRect::MakeWH(100, 100));
   1061     canvas->clear(SK_ColorBLUE);
   1062 }
   1063 ##
   1064 
   1065 #SeeAlso save saveLayer saveLayerAlpha restore() restoreToCount
   1066 
   1067 #Method int save()
   1068 
   1069 #In State_Stack
   1070 #Line # saves Clip and Matrix on stack ##
   1071 #Populate
   1072 
   1073 #Example
   1074 #Description
   1075 The black square is translated 50 pixels down and to the right.
   1076 Restoring Canvas state removes translate() from Canvas stack;
   1077 the red square is not translated, and is drawn at the origin.
   1078 ##
   1079 #Height 100
   1080 void draw(SkCanvas* canvas) {
   1081     SkPaint paint;
   1082     SkRect rect = { 0, 0, 25, 25 };
   1083     canvas->drawRect(rect, paint);
   1084     canvas->save();
   1085     canvas->translate(50, 50);
   1086     canvas->drawRect(rect, paint);
   1087     canvas->restore();
   1088     paint.setColor(SK_ColorRED);
   1089     canvas->drawRect(rect, paint);
   1090 }
   1091 ##
   1092 
   1093 #SeeAlso saveLayer saveLayerAlpha restore restoreToCount
   1094 
   1095 ##
   1096 
   1097 # ------------------------------------------------------------------------------
   1098 
   1099 #Method void restore()
   1100 
   1101 #In State_Stack
   1102 #Line # restores changes to Clip and Matrix, pops save stack ##
   1103 #Populate
   1104 
   1105 #Example
   1106 void draw(SkCanvas* canvas) {
   1107     SkCanvas simple;
   1108     SkDebugf("depth = %d\n", simple.getSaveCount());
   1109     simple.restore();
   1110     SkDebugf("depth = %d\n", simple.getSaveCount());
   1111 }
   1112 ##
   1113 
   1114 #SeeAlso save saveLayer saveLayerAlpha restoreToCount
   1115 
   1116 ##
   1117 
   1118 # ------------------------------------------------------------------------------
   1119 
   1120 #Method int getSaveCount() const
   1121 
   1122 #In State_Stack
   1123 #Line # returns depth of stack containing Clip and Matrix ##
   1124 #Populate
   1125 
   1126 #Example
   1127 void draw(SkCanvas* canvas) {
   1128     SkCanvas simple;
   1129     SkDebugf("depth = %d\n", simple.getSaveCount());
   1130     simple.save();
   1131     SkDebugf("depth = %d\n", simple.getSaveCount());
   1132     simple.restore();
   1133     SkDebugf("depth = %d\n", simple.getSaveCount());
   1134 }
   1135 #StdOut
   1136 depth = 1
   1137 depth = 2
   1138 depth = 1
   1139 ##
   1140 ##
   1141 
   1142 #SeeAlso save restore restoreToCount
   1143 
   1144 ##
   1145 
   1146 # ------------------------------------------------------------------------------
   1147 
   1148 #Method void restoreToCount(int saveCount)
   1149 
   1150 #In State_Stack
   1151 #Line # restores changes to Clip and Matrix to given depth ##
   1152 #Populate
   1153 
   1154 #Example
   1155 void draw(SkCanvas* canvas) {
   1156     SkDebugf("depth = %d\n", canvas->getSaveCount());
   1157     canvas->save();
   1158     canvas->save();
   1159     SkDebugf("depth = %d\n", canvas->getSaveCount());
   1160     canvas->restoreToCount(0);
   1161     SkDebugf("depth = %d\n", canvas->getSaveCount());
   1162 }
   1163 #StdOut
   1164 depth = 1
   1165 depth = 3
   1166 depth = 1
   1167 ##
   1168 ##
   1169 
   1170 #SeeAlso restore getSaveCount save
   1171 
   1172 ##
   1173 
   1174 #Subtopic State_Stack ##
   1175 
   1176 # ------------------------------------------------------------------------------
   1177 
   1178 #Subtopic Layer
   1179 #Substitute layer
   1180 #Alias Layers
   1181 #Substitute layers
   1182 ##
   1183 #Line # temporary Bitmap to draw into ##
   1184 
   1185 Layer allocates a temporary Bitmap to draw into. When the drawing is
   1186 complete, the Bitmap is drawn into the Canvas.
   1187 
   1188 Layer is saved in a stack along with other saved state. When state with a Layer
   1189 is restored, the Bitmap is drawn into the previous Layer.
   1190 
   1191 Layer may be initialized with the contents of the previous Layer. When Layer is
   1192 restored, its Bitmap can be modified by Paint passed to Layer to apply
   1193 Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
   1194 
   1195 #Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
   1196 
   1197 #In Layer
   1198 #Line # saves Clip and Matrix on stack; creates Layer ##
   1199 #Populate
   1200 
   1201 #Example
   1202 #Description
   1203 Rectangles are blurred by Image_Filter when restore() draws Layer to main
   1204 Canvas.
   1205 ##
   1206 #Height 128
   1207 #Function
   1208 ###$
   1209 #include "SkBlurImageFilter.h"
   1210 $$$#
   1211 ##
   1212 
   1213 void draw(SkCanvas* canvas) {
   1214     SkPaint paint, blur;
   1215     blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
   1216     canvas->saveLayer(nullptr, &blur);
   1217     SkRect rect = { 25, 25, 50, 50};
   1218     canvas->drawRect(rect, paint);
   1219     canvas->translate(50, 50);
   1220     paint.setColor(SK_ColorRED);
   1221     canvas->drawRect(rect, paint);
   1222     canvas->restore();
   1223 }
   1224 ##
   1225 
   1226 #SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
   1227 
   1228 ##
   1229 
   1230 #Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
   1231 
   1232 #In Layer
   1233 #Populate
   1234 
   1235 #Example
   1236 #Description
   1237 Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
   1238 The red rectangle is clipped; it does not fully fit on Layer.
   1239 Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
   1240 ##
   1241 #Height 128
   1242 #Function
   1243 ###$
   1244 #include "SkBlurImageFilter.h"
   1245 $$$#
   1246 ##
   1247 
   1248 void draw(SkCanvas* canvas) {
   1249     SkPaint paint, blur;
   1250     blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
   1251     canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
   1252     SkRect rect = { 25, 25, 50, 50};
   1253     canvas->drawRect(rect, paint);
   1254     canvas->translate(50, 50);
   1255     paint.setColor(SK_ColorRED);
   1256     canvas->drawRect(rect, paint);
   1257     canvas->restore();
   1258 }
   1259 ##
   1260 
   1261 #SeeAlso save restore saveLayerAlpha SaveLayerRec
   1262 
   1263 ##
   1264 
   1265 #Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
   1266 
   1267 #In Layer
   1268 #Line # saves Clip and Matrix on stack; creates Layer; sets opacity ##
   1269 #Populate
   1270 
   1271 #Example
   1272     SkPaint paint;
   1273     paint.setColor(SK_ColorRED);
   1274     canvas->drawCircle(50, 50, 50, paint);
   1275     canvas->saveLayerAlpha(nullptr, 128);
   1276     paint.setColor(SK_ColorBLUE);
   1277     canvas->drawCircle(100, 50, 50, paint);
   1278     paint.setColor(SK_ColorGREEN);
   1279     paint.setAlpha(128);
   1280     canvas->drawCircle(75, 90, 50, paint);
   1281     canvas->restore();
   1282 ##
   1283 
   1284 #SeeAlso save restore saveLayer SaveLayerRec
   1285 
   1286 ##
   1287 
   1288 #Enum SaveLayerFlagsSet
   1289 #Line # sets SaveLayerRec options ##
   1290 #Code
   1291 #Populate
   1292 ##
   1293 
   1294 
   1295 #Typedef uint32_t SaveLayerFlags
   1296 #Line # options for SaveLayerRec ##
   1297 ##
   1298 
   1299 SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
   1300 defining how Layer allocated by saveLayer operates. It may be set to zero or
   1301 kInitWithPrevious_SaveLayerFlag.
   1302 
   1303 #Const kInitWithPrevious_SaveLayerFlag 4
   1304 #Line # initializes with previous contents ##
   1305   Initializes Layer with the contents of the previous Layer.
   1306 ##
   1307 
   1308 #Example
   1309 #Height 160
   1310 #Description
   1311 Canvas Layer captures red and blue circles scaled up by four.
   1312 scalePaint blends Layer back with transparency.
   1313 ##
   1314 void draw(SkCanvas* canvas) {
   1315     SkPaint redPaint, bluePaint, scalePaint;
   1316     redPaint.setColor(SK_ColorRED);
   1317     canvas->drawCircle(21, 21, 8, redPaint);
   1318     bluePaint.setColor(SK_ColorBLUE);
   1319     canvas->drawCircle(31, 21, 8, bluePaint);
   1320     SkMatrix matrix;
   1321     matrix.setScale(4, 4);
   1322     scalePaint.setAlpha(0x40);
   1323     scalePaint.setImageFilter(
   1324             SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
   1325     SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
   1326             SkCanvas::kInitWithPrevious_SaveLayerFlag);
   1327     canvas->saveLayer(saveLayerRec);
   1328     canvas->restore();
   1329 }
   1330 ##
   1331 
   1332 #SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
   1333 
   1334 #Enum ##
   1335 
   1336 #Subtopic SaveLayerRec
   1337 #Line # contains the state used to create the Layer ##
   1338 
   1339 #Struct SaveLayerRec
   1340 #Line # contains the state used to create the Layer ##
   1341 
   1342 #Code
   1343 #Populate
   1344 ##
   1345 
   1346 SaveLayerRec contains the state used to create the Layer.
   1347 
   1348 #Member const SkRect*           fBounds
   1349 #Line # hints at Layer size limit ##
   1350     fBounds is used as a hint to limit the size of Layer; may be nullptr.
   1351     fBounds suggests but does not define Layer size. To clip drawing to
   1352     a specific rectangle, use clipRect.
   1353 ##
   1354 
   1355 #Member const SkPaint*          fPaint
   1356 #Line # modifies overlay ##
   1357     fPaint modifies how Layer overlays the prior Layer; may be nullptr.
   1358     Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
   1359     Mask_Filter affect Layer draw.
   1360 ##
   1361 
   1362 #Member const SkImageFilter*    fBackdrop
   1363 #Line # applies Image_Filter to prior Layer ##
   1364     fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
   1365     may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
   1366     prior Layer without an Image_Filter.
   1367 ##
   1368 
   1369 #Member const SkImage*          fClipMask
   1370 #Line # clips Layer with Mask_Alpha ##
   1371   restore() clips Layer by the Color_Alpha channel of fClipMask when
   1372   Layer is copied to Device. fClipMask may be nullptr.    .
   1373 ##
   1374 
   1375 #Member const SkMatrix*         fClipMatrix
   1376 #Line # transforms Mask_Alpha used to clip ##
   1377   fClipMatrix transforms fClipMask before it clips Layer. If
   1378   fClipMask describes a translucent gradient, it may be scaled and rotated
   1379   without introducing artifacts. fClipMatrix may be nullptr.
   1380 ##
   1381 
   1382 #Member SaveLayerFlags          fSaveLayerFlags
   1383 #Line # creates with prior Layer contents ##
   1384     fSaveLayerFlags are used to create Layer without transparency,
   1385     and to create Layer with the ontents of the previous Layer.
   1386 ##
   1387 
   1388 #Example
   1389 #Height 160
   1390 #Description
   1391 Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled
   1392 up by four. After drawing another red circle without scaling on top, the Layer is
   1393 transferred to the main canvas.
   1394 ##
   1395 void draw(SkCanvas* canvas) {
   1396     SkPaint redPaint, bluePaint;
   1397     redPaint.setAntiAlias(true);
   1398     redPaint.setColor(SK_ColorRED);
   1399     canvas->drawCircle(21, 21, 8, redPaint);
   1400     bluePaint.setColor(SK_ColorBLUE);
   1401     canvas->drawCircle(31, 21, 8, bluePaint);
   1402     SkMatrix matrix;
   1403     matrix.setScale(4, 4);
   1404     auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
   1405     SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
   1406     canvas->saveLayer(saveLayerRec);
   1407     canvas->drawCircle(125, 85, 8, redPaint);
   1408     canvas->restore();
   1409 }
   1410 ##
   1411 
   1412 #Subtopic Constructors
   1413 ##
   1414 
   1415 #Method SaveLayerRec()
   1416 #Line # constructs SaveLayerRec ##
   1417 #Populate
   1418 
   1419 #Example
   1420     SkCanvas::SaveLayerRec rec1;
   1421     rec1.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
   1422     SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kInitWithPrevious_SaveLayerFlag);
   1423     SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
   1424             && rec1.fPaint == rec2.fPaint
   1425             && rec1.fBackdrop == rec2.fBackdrop
   1426             && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
   1427     #StdOut
   1428         rec1 == rec2
   1429     ##
   1430 ##
   1431 
   1432 #SeeAlso save restore saveLayer saveLayerAlpha
   1433 
   1434 ##
   1435 
   1436 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
   1437 #Populate
   1438 
   1439 #Example
   1440     SkCanvas::SaveLayerRec rec1;
   1441     SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
   1442     SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
   1443             && rec1.fPaint == rec2.fPaint
   1444             && rec1.fBackdrop == rec2.fBackdrop
   1445             && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
   1446     #StdOut
   1447         rec1 == rec2
   1448     ##
   1449 ##
   1450 
   1451 #SeeAlso save restore saveLayer saveLayerAlpha
   1452 
   1453 ##
   1454 
   1455 #Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
   1456                      SaveLayerFlags saveLayerFlags)
   1457 #Populate
   1458 
   1459 #Example
   1460     SkCanvas::SaveLayerRec rec1;
   1461     SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
   1462     SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
   1463             && rec1.fPaint == rec2.fPaint
   1464             && rec1.fBackdrop == rec2.fBackdrop
   1465             && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
   1466     #StdOut
   1467         rec1 == rec2
   1468     ##
   1469 ##
   1470 
   1471 #SeeAlso save restore saveLayer saveLayerAlpha
   1472 
   1473 ##
   1474 
   1475 #Struct ##
   1476 
   1477 #Subtopic ##
   1478 
   1479 #Method int saveLayer(const SaveLayerRec& layerRec)
   1480 
   1481 #In Layer
   1482 #Populate
   1483 
   1484 #Example
   1485 #Description
   1486 The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
   1487 Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
   1488 Where Layer was cleared, the original image will draw unchanged.
   1489 Outside of the circle the mandrill is brightened.
   1490 ##
   1491     #Image 3
   1492     // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png");
   1493     canvas->drawImage(image, 0, 0, nullptr);
   1494     SkCanvas::SaveLayerRec rec;
   1495     SkPaint paint;
   1496     paint.setBlendMode(SkBlendMode::kPlus);
   1497     rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
   1498     rec.fPaint = &paint;
   1499     canvas->saveLayer(rec);
   1500     paint.setBlendMode(SkBlendMode::kClear);
   1501     canvas->drawCircle(128, 128, 96, paint);
   1502     canvas->restore();
   1503 ##
   1504 
   1505 #ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
   1506 
   1507 #SeeAlso save restore saveLayer saveLayerAlpha
   1508 
   1509 ##
   1510 
   1511 #Subtopic Layer ##
   1512 
   1513 # ------------------------------------------------------------------------------
   1514 #Subtopic Matrix
   1515 #Line # coordinate transformation ##
   1516 
   1517 #Method void translate(SkScalar dx, SkScalar dy)
   1518 
   1519 #In Matrix
   1520 #Line # translates Matrix ##
   1521 #Populate
   1522 
   1523 #Example
   1524 #Height 128
   1525 #Description
   1526 scale() followed by translate() produces different results from translate() followed
   1527 by scale().
   1528 
   1529 The blue stroke follows translate of (50, 50); a black
   1530 fill follows scale of (2, 1/2.f). After restoring the clip, which resets
   1531 Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
   1532 follows translate of (50, 50).
   1533 ##
   1534 void draw(SkCanvas* canvas) {
   1535     SkPaint filledPaint;
   1536     SkPaint outlinePaint;
   1537     outlinePaint.setStyle(SkPaint::kStroke_Style);
   1538     outlinePaint.setColor(SK_ColorBLUE);
   1539     canvas->save();
   1540     canvas->translate(50, 50);
   1541     canvas->drawCircle(28, 28, 15, outlinePaint);  // blue center: (50+28, 50+28)
   1542     canvas->scale(2, 1/2.f);
   1543     canvas->drawCircle(28, 28, 15, filledPaint);   // black center: (50+(28*2), 50+(28/2))
   1544     canvas->restore();
   1545     filledPaint.setColor(SK_ColorGRAY);
   1546     outlinePaint.setColor(SK_ColorRED);
   1547     canvas->scale(2, 1/2.f);
   1548     canvas->drawCircle(28, 28, 15, outlinePaint);  // red center: (28*2, 28/2)
   1549     canvas->translate(50, 50);
   1550     canvas->drawCircle(28, 28, 15, filledPaint);   // gray center: ((50+28)*2, (50+28)/2)
   1551 }
   1552 ##
   1553 
   1554 #SeeAlso concat() scale() skew() rotate() setMatrix
   1555 
   1556 ##
   1557 
   1558 # ------------------------------------------------------------------------------
   1559 
   1560 #Method void scale(SkScalar sx, SkScalar sy)
   1561 
   1562 #In Matrix
   1563 #Line # scales Matrix ##
   1564 #Populate
   1565 
   1566 #Example
   1567 #Height 160
   1568 void draw(SkCanvas* canvas) {
   1569     SkPaint paint;
   1570     SkRect rect = { 10, 20, 60, 120 };
   1571     canvas->translate(20, 20);
   1572     canvas->drawRect(rect, paint);
   1573     canvas->scale(2, .5f);
   1574     paint.setColor(SK_ColorGRAY);
   1575     canvas->drawRect(rect, paint);
   1576 }
   1577 ##
   1578 
   1579 #SeeAlso concat() translate() skew() rotate() setMatrix
   1580 
   1581 ##
   1582 
   1583 # ------------------------------------------------------------------------------
   1584 
   1585 #Method void rotate(SkScalar degrees)
   1586 
   1587 #In Matrix
   1588 #Line # rotates Matrix ##
   1589 #Populate
   1590 
   1591 #Example
   1592 #Description
   1593 Draw clock hands at time 5:10. The hour hand and minute hand point up and
   1594 are rotated clockwise.
   1595 ##
   1596 void draw(SkCanvas* canvas) {
   1597     SkPaint paint;
   1598     paint.setStyle(SkPaint::kStroke_Style);
   1599     canvas->translate(128, 128);
   1600     canvas->drawCircle(0, 0, 60, paint);
   1601     canvas->save();
   1602     canvas->rotate(10 * 360 / 60);   // 10 minutes of 60 scaled to 360 degrees
   1603     canvas->drawLine(0, 0, 0, -50, paint);
   1604     canvas->restore();
   1605     canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
   1606     canvas->drawLine(0, 0, 0, -30, paint);
   1607 }
   1608 ##
   1609 
   1610 #SeeAlso concat() translate() skew() scale() setMatrix
   1611 
   1612 ##
   1613 
   1614 # ------------------------------------------------------------------------------
   1615 
   1616 #Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
   1617 
   1618 #In Matrix
   1619 #Populate
   1620 
   1621 #Example
   1622 #Height 192
   1623 void draw(SkCanvas* canvas) {
   1624     SkPaint paint;
   1625     SkFont font(nullptr, 96);
   1626     canvas->drawString("A1", 130, 100, font, paint);
   1627     canvas->rotate(180, 130, 100);
   1628     canvas->drawString("A1", 130, 100, font, paint);
   1629 }
   1630 ##
   1631 
   1632 #SeeAlso concat() translate() skew() scale() setMatrix
   1633 
   1634 ##
   1635 
   1636 # ------------------------------------------------------------------------------
   1637 
   1638 #Method void skew(SkScalar sx, SkScalar sy)
   1639 
   1640 #In Matrix
   1641 #Line # skews Matrix ##
   1642 #Populate
   1643 
   1644 #Example
   1645     #Description
   1646         Black text mimics an oblique text style by using a negative skew on x-axis
   1647         that shifts the geometry to the right as the y-axis values decrease.
   1648         Red text uses a positive skew on y-axis to shift the geometry down
   1649         as the x-axis values increase.
   1650         Blue text combines sx and sy skew to rotate and scale.
   1651     ##
   1652     SkPaint paint;
   1653     SkFont font(nullptr, 128);
   1654     canvas->translate(30, 130);
   1655     canvas->save();
   1656     canvas->skew(-.5, 0);
   1657     canvas->drawString("A1", 0, 0, font, paint);
   1658     canvas->restore();
   1659     canvas->save();
   1660     canvas->skew(0, .5);
   1661     paint.setColor(SK_ColorRED);
   1662     canvas->drawString("A1", 0, 0, font, paint);
   1663     canvas->restore();
   1664     canvas->skew(-.5, .5);
   1665     paint.setColor(SK_ColorBLUE);
   1666     canvas->drawString("A1", 0, 0, font, paint);
   1667 ##
   1668 
   1669 #SeeAlso concat() translate() rotate() scale() setMatrix
   1670 
   1671 ##
   1672 
   1673 # ------------------------------------------------------------------------------
   1674 
   1675 #Method void concat(const SkMatrix& matrix)
   1676 
   1677 #In Matrix
   1678 #Line # multiplies Matrix by Matrix ##
   1679 #Populate
   1680 
   1681 #Example
   1682 void draw(SkCanvas* canvas) {
   1683     SkPaint paint;
   1684     SkFont font(nullptr, 80);
   1685     font.setScaleX(.3);
   1686     SkMatrix matrix;
   1687     SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
   1688     matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
   1689     canvas->drawRect(rect[0], paint);
   1690     canvas->drawRect(rect[1], paint);
   1691     paint.setColor(SK_ColorWHITE);
   1692     canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint);
   1693     canvas->concat(matrix);
   1694     canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint);
   1695 }
   1696 ##
   1697 
   1698 #SeeAlso translate() rotate() scale() skew() setMatrix
   1699 
   1700 ##
   1701 
   1702 # ------------------------------------------------------------------------------
   1703 
   1704 #Method void setMatrix(const SkMatrix& matrix)
   1705 
   1706 #In Matrix
   1707 #Line # sets Matrix ##
   1708 #Populate
   1709 
   1710 #Example
   1711 #Height 128
   1712 void draw(SkCanvas* canvas) {
   1713     SkPaint paint;
   1714     SkFont font;
   1715     canvas->scale(4, 6);
   1716     canvas->drawString("truth", 2, 10, font, paint);
   1717     SkMatrix matrix;
   1718     matrix.setScale(2.8f, 6);
   1719     canvas->setMatrix(matrix);
   1720     canvas->drawString("consequences", 2, 20, font, paint);
   1721 }
   1722 ##
   1723 
   1724 #SeeAlso resetMatrix concat() translate() rotate() scale() skew()
   1725 
   1726 ##
   1727 
   1728 # ------------------------------------------------------------------------------
   1729 
   1730 #Method void resetMatrix()
   1731 
   1732 #In Matrix
   1733 #Line # resets Matrix to identity ##
   1734 #Populate
   1735 
   1736 #Example
   1737 #Height 128
   1738 void draw(SkCanvas* canvas) {
   1739     SkPaint paint;
   1740     SkFont font;
   1741     canvas->scale(4, 6);
   1742     canvas->drawString("truth", 2, 10, font, paint);
   1743     canvas->resetMatrix();
   1744     canvas->scale(2.8f, 6);
   1745     canvas->drawString("consequences", 2, 20, font, paint);
   1746 }
   1747 ##
   1748 
   1749 #SeeAlso setMatrix concat() translate() rotate() scale() skew()
   1750 
   1751 ##
   1752 
   1753 # ------------------------------------------------------------------------------
   1754 
   1755 #Method const SkMatrix& getTotalMatrix() const
   1756 
   1757 #In Matrix
   1758 #Line # returns Matrix ##
   1759 #Populate
   1760 
   1761 #Example
   1762     SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
   1763     #StdOut
   1764         isIdentity true
   1765     ##
   1766 ##
   1767 
   1768 #SeeAlso setMatrix resetMatrix concat()
   1769 
   1770 ##
   1771 
   1772 #Subtopic Matrix ##
   1773 
   1774 # ------------------------------------------------------------------------------
   1775 #Subtopic Clip
   1776 #Line # stack of clipping Paths ##
   1777 
   1778 Clip is built from a stack of clipping paths. Each Path in the
   1779 stack can be constructed from one or more Path_Contour elements. The
   1780 Path_Contour may be composed of any number of Path_Verb segments. Each
   1781 Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
   1782 by Path_Contour.
   1783 
   1784 Clip stack of Path elements successfully restrict the Path area. Each
   1785 Path is transformed by Matrix, then intersected with or subtracted from the
   1786 prior Clip to form the replacement Clip. Use SkClipOp::kDifference
   1787 to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
   1788 with Clip.
   1789 
   1790 A clipping Path may be Anti_Aliased; if Path, after transformation, is
   1791 composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels
   1792 to either be inside or outside the clip. The fastest drawing has a Aliased,
   1793 rectangular clip.
   1794 
   1795 If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring
   1796 that drawing blend partially with the destination along the edge. A rotated
   1797 rectangular Anti_Aliased clip looks smoother but draws slower.
   1798 
   1799 Clip can combine with Rect and Round_Rect primitives; like
   1800 Path, these are transformed by Matrix before they are combined with Clip.
   1801 
   1802 Clip can combine with Region. Region is assumed to be in Device coordinates
   1803 and is unaffected by Matrix.
   1804 
   1805 #Example
   1806 #Height 90
   1807     #Description
   1808         Draw a red circle with an Aliased clip and an Anti_Aliased clip.
   1809         Use an image filter to zoom into the pixels drawn.
   1810         The edge of the Aliased clip fully draws pixels in the red circle.
   1811         The edge of the Anti_Aliased clip partially draws pixels in the red circle.
   1812     ##
   1813     SkPaint redPaint, scalePaint;
   1814     redPaint.setAntiAlias(true);
   1815     redPaint.setColor(SK_ColorRED);
   1816     canvas->save();
   1817     for (bool antialias : { false, true } ) {
   1818         canvas->save();
   1819         canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
   1820         canvas->drawCircle(17, 11, 8, redPaint);
   1821         canvas->restore();
   1822         canvas->translate(16, 0);
   1823     }
   1824     canvas->restore();
   1825     SkMatrix matrix;
   1826     matrix.setScale(6, 6);
   1827     scalePaint.setImageFilter(
   1828             SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
   1829     SkCanvas::SaveLayerRec saveLayerRec(
   1830             nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
   1831     canvas->saveLayer(saveLayerRec);
   1832     canvas->restore();
   1833 ##
   1834 
   1835 #Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
   1836 
   1837 #In Clip
   1838 #Line # combines Clip with Rect ##
   1839 #Populate
   1840 
   1841 #Example
   1842 #Height 128
   1843 void draw(SkCanvas* canvas) {
   1844     canvas->rotate(10);
   1845     SkPaint paint;
   1846     paint.setAntiAlias(true);
   1847     for (auto alias: { false, true } ) {
   1848         canvas->save();
   1849         canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
   1850         canvas->drawCircle(100, 60, 60, paint);
   1851         canvas->restore();
   1852         canvas->translate(80, 0);
   1853     }
   1854 }
   1855 ##
   1856 
   1857 #SeeAlso clipRRect clipPath clipRegion
   1858 
   1859 ##
   1860 
   1861 #Method void clipRect(const SkRect& rect, SkClipOp op)
   1862 
   1863 #In Clip
   1864 #Populate
   1865 
   1866 #Example
   1867 #Height 192
   1868 #Width 280
   1869 void draw(SkCanvas* canvas) {
   1870     SkPaint paint;
   1871     for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
   1872         canvas->save();
   1873         canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
   1874         canvas->drawCircle(100, 100, 60, paint);
   1875         canvas->restore();
   1876         canvas->translate(80, 0);
   1877     }
   1878 }
   1879 ##
   1880 
   1881 #SeeAlso clipRRect clipPath clipRegion
   1882 
   1883 ##
   1884 
   1885 #Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
   1886 
   1887 #In Clip
   1888 #Populate
   1889 
   1890 #Example
   1891 #Height 133
   1892     #Description
   1893         A circle drawn in pieces looks uniform when drawn Aliased.
   1894         The same circle pieces blend with pixels more than once when Anti_Aliased,
   1895         visible as a thin pair of lines through the right circle.
   1896     ##
   1897 void draw(SkCanvas* canvas) {
   1898     canvas->clear(SK_ColorWHITE);
   1899     SkPaint paint;
   1900     paint.setAntiAlias(true);
   1901     paint.setColor(0x8055aaff);
   1902     SkRect clipRect = { 0, 0, 87.4f, 87.4f };
   1903     for (auto alias: { false, true } ) {
   1904         canvas->save();
   1905         canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
   1906         canvas->drawCircle(67, 67, 60, paint);
   1907         canvas->restore();
   1908         canvas->save();
   1909         canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
   1910         canvas->drawCircle(67, 67, 60, paint);
   1911         canvas->restore();
   1912         canvas->translate(120, 0);
   1913     }
   1914 }
   1915 ##
   1916 
   1917 #SeeAlso clipRRect clipPath clipRegion
   1918 
   1919 ##
   1920 
   1921 #Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
   1922 
   1923 #In Clip
   1924 #Line # combines Clip with Round_Rect ##
   1925 #Populate
   1926 
   1927 #Example
   1928 #Height 128
   1929 void draw(SkCanvas* canvas) {
   1930     canvas->clear(SK_ColorWHITE);
   1931     SkPaint paint;
   1932     paint.setAntiAlias(true);
   1933     paint.setColor(0x8055aaff);
   1934     SkRRect oval;
   1935     oval.setOval({10, 20, 90, 100});
   1936     canvas->clipRRect(oval, SkClipOp::kIntersect, true);
   1937     canvas->drawCircle(70, 100, 60, paint);
   1938 }
   1939 ##
   1940 
   1941 #SeeAlso clipRect clipPath clipRegion
   1942 
   1943 ##
   1944 
   1945 #Method void clipRRect(const SkRRect& rrect, SkClipOp op)
   1946 
   1947 #In Clip
   1948 #Populate
   1949 
   1950 #Example
   1951 #Height 128
   1952 void draw(SkCanvas* canvas) {
   1953     SkPaint paint;
   1954     paint.setColor(0x8055aaff);
   1955     auto oval = SkRRect::MakeOval({10, 20, 90, 100});
   1956     canvas->clipRRect(oval, SkClipOp::kIntersect);
   1957     canvas->drawCircle(70, 100, 60, paint);
   1958 }
   1959 ##
   1960 
   1961 #SeeAlso clipRect clipPath clipRegion
   1962 
   1963 ##
   1964 
   1965 #Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
   1966 
   1967 #In Clip
   1968 #Populate
   1969 
   1970 #Example
   1971 #Height 128
   1972 void draw(SkCanvas* canvas) {
   1973     SkPaint paint;
   1974     paint.setAntiAlias(true);
   1975     auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
   1976     canvas->clipRRect(oval, true);
   1977     canvas->drawCircle(70, 100, 60, paint);
   1978 }
   1979 ##
   1980 
   1981 #SeeAlso clipRect clipPath clipRegion
   1982 
   1983 ##
   1984 
   1985 #Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
   1986 
   1987 #In Clip
   1988 #Line # combines Clip with Path ##
   1989 #Populate
   1990 
   1991 #Example
   1992 #Description
   1993 Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
   1994 area outside clip is subtracted from circle.
   1995 
   1996 Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
   1997 area inside clip is intersected with circle.
   1998 ##
   1999 void draw(SkCanvas* canvas) {
   2000     SkPaint paint;
   2001     paint.setAntiAlias(true);
   2002     SkPath path;
   2003     path.addRect({20, 30, 100, 110});
   2004     path.setFillType(SkPath::kInverseWinding_FillType);
   2005     canvas->save();
   2006     canvas->clipPath(path, SkClipOp::kDifference, false);
   2007     canvas->drawCircle(70, 100, 60, paint);
   2008     canvas->restore();
   2009     canvas->translate(100, 100);
   2010     path.setFillType(SkPath::kWinding_FillType);
   2011     canvas->clipPath(path, SkClipOp::kIntersect, false);
   2012     canvas->drawCircle(70, 100, 60, paint);
   2013 }
   2014 ##
   2015 
   2016 #SeeAlso clipRect clipRRect clipRegion
   2017 
   2018 ##
   2019 
   2020 #Method void clipPath(const SkPath& path, SkClipOp op)
   2021 
   2022 #In Clip
   2023 #Populate
   2024 
   2025 #Example
   2026 #Description
   2027 Overlapping Rects form a clip. When clip Path_Fill_Type is set to
   2028 SkPath::kWinding_FillType, the overlap is included. Set to
   2029 SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
   2030 ##
   2031 void draw(SkCanvas* canvas) {
   2032     SkPaint paint;
   2033     paint.setAntiAlias(true);
   2034     SkPath path;
   2035     path.addRect({20, 15, 100, 95});
   2036     path.addRect({50, 65, 130, 135});
   2037     path.setFillType(SkPath::kWinding_FillType);
   2038     canvas->save();
   2039     canvas->clipPath(path, SkClipOp::kIntersect);
   2040     canvas->drawCircle(70, 85, 60, paint);
   2041     canvas->restore();
   2042     canvas->translate(100, 100);
   2043     path.setFillType(SkPath::kEvenOdd_FillType);
   2044     canvas->clipPath(path, SkClipOp::kIntersect);
   2045     canvas->drawCircle(70, 85, 60, paint);
   2046 }
   2047 ##
   2048 
   2049 #SeeAlso clipRect clipRRect clipRegion
   2050 
   2051 ##
   2052 
   2053 #Method void clipPath(const SkPath& path, bool doAntiAlias = false)
   2054 
   2055 #In Clip
   2056 #Populate
   2057 
   2058 #Example
   2059 #Height 212
   2060 #Description
   2061 Clip loops over itself covering its center twice. When clip Path_Fill_Type
   2062 is set to SkPath::kWinding_FillType, the overlap is included. Set to
   2063 SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
   2064 ##
   2065 void draw(SkCanvas* canvas) {
   2066     SkPaint paint;
   2067     paint.setAntiAlias(true);
   2068     SkPath path;
   2069     SkPoint poly[] = {{20, 20}, { 80, 20}, { 80,  80}, {40,  80},
   2070                       {40, 40}, {100, 40}, {100, 100}, {20, 100}};
   2071     path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
   2072     path.setFillType(SkPath::kWinding_FillType);
   2073     canvas->save();
   2074     canvas->clipPath(path, SkClipOp::kIntersect);
   2075     canvas->drawCircle(50, 50, 45, paint);
   2076     canvas->restore();
   2077     canvas->translate(100, 100);
   2078     path.setFillType(SkPath::kEvenOdd_FillType);
   2079     canvas->clipPath(path, SkClipOp::kIntersect);
   2080     canvas->drawCircle(50, 50, 45, paint);
   2081 }
   2082 ##
   2083 
   2084 #SeeAlso clipRect clipRRect clipRegion
   2085 
   2086 ##
   2087 
   2088 # ------------------------------------------------------------------------------
   2089 
   2090 #Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
   2091 
   2092 #In Clip
   2093 #Line # combines Clip with Region ##
   2094 #Populate
   2095 
   2096 #Example
   2097 #Description
   2098     region is unaffected by canvas rotation; iRect is affected by canvas rotation.
   2099     Both clips are Aliased; this is not noticeable on Region clip because it
   2100     aligns to pixel boundaries.
   2101 ##
   2102 void draw(SkCanvas* canvas) {
   2103     SkPaint paint;
   2104     paint.setAntiAlias(true);
   2105     SkIRect iRect = {30, 40, 120, 130 };
   2106     SkRegion region(iRect);
   2107     canvas->rotate(10);
   2108     canvas->save();
   2109     canvas->clipRegion(region, SkClipOp::kIntersect);
   2110     canvas->drawCircle(50, 50, 45, paint);
   2111     canvas->restore();
   2112     canvas->translate(100, 100);
   2113     canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
   2114     canvas->drawCircle(50, 50, 45, paint);
   2115 }
   2116 ##
   2117 
   2118 #SeeAlso clipRect clipRRect clipPath
   2119 
   2120 ##
   2121 
   2122 #Method bool quickReject(const SkRect& rect) const
   2123 
   2124 #In Clip
   2125 #Line # returns if Rect is outside Clip ##
   2126 #Populate
   2127 
   2128 #Example
   2129 void draw(SkCanvas* canvas) {
   2130     SkRect testRect = {30, 30, 120, 129 };
   2131     SkRect clipRect = {30, 130, 120, 230 };
   2132     canvas->save();
   2133     canvas->clipRect(clipRect);
   2134     SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
   2135     canvas->restore();
   2136     canvas->rotate(10);
   2137     canvas->clipRect(clipRect);
   2138     SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
   2139 }
   2140     #StdOut
   2141         quickReject true
   2142         quickReject false
   2143     ##
   2144 ##
   2145 
   2146 #SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
   2147 
   2148 ##
   2149 
   2150 #Method bool quickReject(const SkPath& path) const
   2151 
   2152 #In Clip
   2153 #Populate
   2154 
   2155 #Example
   2156 void draw(SkCanvas* canvas) {
   2157     SkPoint testPoints[] = {{30,  30}, {120,  30}, {120, 129} };
   2158     SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
   2159     SkPath testPath, clipPath;
   2160     testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
   2161     clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
   2162     canvas->save();
   2163     canvas->clipPath(clipPath);
   2164     SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
   2165     canvas->restore();
   2166     canvas->rotate(10);
   2167     canvas->clipPath(clipPath);
   2168     SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
   2169     #StdOut
   2170         quickReject true
   2171         quickReject false
   2172     ##
   2173 }
   2174 ##
   2175 
   2176 #SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
   2177 
   2178 ##
   2179 
   2180 #Method SkRect getLocalClipBounds() const
   2181 
   2182 #In Clip
   2183 #Line # returns Clip bounds in source coordinates ##
   2184 #Populate
   2185 
   2186 #Example
   2187     #Description
   2188         Initial bounds is device bounds outset by 1 on all sides.
   2189         Clipped bounds is clipPath bounds outset by 1 on all sides.
   2190         Scaling the canvas by two on both axes scales the local bounds by 1/2
   2191         on both axes.
   2192     ##
   2193     SkCanvas local(256, 256);
   2194     canvas = &local;
   2195     SkRect bounds = canvas->getLocalClipBounds();
   2196     SkDebugf("left:%g  top:%g  right:%g  bottom:%g\n",
   2197             bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
   2198     SkPoint clipPoints[]  = {{30, 130}, {120, 130}, {120, 230} };
   2199     SkPath clipPath;
   2200     clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
   2201     canvas->clipPath(clipPath);
   2202     bounds = canvas->getLocalClipBounds();
   2203     SkDebugf("left:%g  top:%g  right:%g  bottom:%g\n",
   2204             bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
   2205     canvas->scale(2, 2);
   2206     bounds = canvas->getLocalClipBounds();
   2207     SkDebugf("left:%g  top:%g  right:%g  bottom:%g\n",
   2208             bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
   2209     #StdOut
   2210         left:-1  top:-1  right:257  bottom:257
   2211         left:29  top:129  right:121  bottom:231
   2212         left:14.5  top:64.5  right:60.5  bottom:115.5
   2213     ##
   2214 ##
   2215 
   2216 # local canvas in example works around bug in fiddle ##
   2217 #Bug 6524
   2218 #SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
   2219 
   2220 ##
   2221 
   2222 #Method bool getLocalClipBounds(SkRect* bounds) const
   2223 
   2224 #In Clip
   2225 #Populate
   2226 
   2227 #Example
   2228     void draw(SkCanvas* canvas) {
   2229         SkCanvas local(256, 256);
   2230         canvas = &local;
   2231         SkRect bounds;
   2232         SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
   2233                  ? "false" : "true");
   2234         SkPath path;
   2235         canvas->clipPath(path);
   2236         SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
   2237                  ? "false" : "true");
   2238     }
   2239     #StdOut
   2240         local bounds empty = false
   2241         local bounds empty = true
   2242     ##
   2243 ##
   2244 
   2245 # local canvas in example works around bug in fiddle ##
   2246 #Bug 6524
   2247 #SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
   2248 
   2249 ##
   2250 
   2251 #Method SkIRect getDeviceClipBounds() const
   2252 
   2253 #In Clip
   2254 #Line # returns IRect bounds of Clip ##
   2255 #Populate
   2256 
   2257 #Example
   2258 void draw(SkCanvas* canvas) {
   2259     #Description
   2260         Initial bounds is device bounds, not outset.
   2261         Clipped bounds is clipPath bounds, not outset.
   2262         Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2
   2263         on both axes.
   2264     ##
   2265     SkCanvas device(256, 256);
   2266     canvas = &device;
   2267     SkIRect bounds = canvas->getDeviceClipBounds();
   2268     SkDebugf("left:%d  top:%d  right:%d  bottom:%d\n",
   2269             bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
   2270     SkPoint clipPoints[]  = {{30, 130}, {120, 130}, {120, 230} };
   2271     SkPath clipPath;
   2272     clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
   2273     canvas->save();
   2274     canvas->clipPath(clipPath);
   2275     bounds = canvas->getDeviceClipBounds();
   2276     SkDebugf("left:%d  top:%d  right:%d  bottom:%d\n",
   2277             bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
   2278     canvas->restore();
   2279     canvas->scale(1.f/2, 1.f/2);
   2280     canvas->clipPath(clipPath);
   2281     bounds = canvas->getDeviceClipBounds();
   2282     SkDebugf("left:%d  top:%d  right:%d  bottom:%d\n",
   2283             bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
   2284     #StdOut
   2285         left:0  top:0  right:256  bottom:256
   2286         left:30  top:130  right:120  bottom:230
   2287         left:15  top:65  right:60  bottom:115
   2288     ##
   2289 }
   2290 ##
   2291 
   2292 #ToDo some confusion on why with an identity Matrix local and device are different ##
   2293 #SeeAlso getLocalClipBounds getBaseLayerSize quickReject
   2294 
   2295 # device canvas in example works around bug in fiddle ##
   2296 #Bug 6524
   2297 
   2298 ##
   2299 
   2300 #Method bool getDeviceClipBounds(SkIRect* bounds) const
   2301 
   2302 #In Clip
   2303 #Populate
   2304 
   2305 #Example
   2306     void draw(SkCanvas* canvas) {
   2307         SkIRect bounds;
   2308         SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
   2309                  ? "false" : "true");
   2310         SkPath path;
   2311         canvas->clipPath(path);
   2312         SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
   2313                  ? "false" : "true");
   2314     }
   2315     #StdOut
   2316         device bounds empty = false
   2317         device bounds empty = true
   2318     ##
   2319 ##
   2320 
   2321 #SeeAlso getLocalClipBounds getBaseLayerSize quickReject
   2322 
   2323 ##
   2324 
   2325 #Subtopic Clip ##
   2326 
   2327 # ------------------------------------------------------------------------------
   2328 #Subtopic Draw
   2329 #Line # draws into Canvas ##
   2330 ##
   2331 
   2332 #Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
   2333 #In Draw
   2334 #Line # fills Clip with Color and Blend_Mode ##
   2335 #Populate
   2336 
   2337 #Example
   2338     canvas->drawColor(SK_ColorRED);
   2339     canvas->clipRect(SkRect::MakeWH(150, 150));
   2340     canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
   2341     canvas->clipRect(SkRect::MakeWH(75, 75));
   2342     canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
   2343 ##
   2344 
   2345 #SeeAlso clear SkBitmap::erase drawPaint
   2346 
   2347 ##
   2348 
   2349 # ------------------------------------------------------------------------------
   2350 
   2351 #Method void clear(SkColor color)
   2352 #In Draw
   2353 #Line # fills Clip with Color ##
   2354 #Populate
   2355 
   2356 #Example
   2357 void draw(SkCanvas* canvas) {
   2358     canvas->save();
   2359     canvas->clipRect(SkRect::MakeWH(256, 128));
   2360     canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
   2361     canvas->restore();
   2362     canvas->save();
   2363     canvas->clipRect(SkRect::MakeWH(150, 192));
   2364     canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
   2365     canvas->restore();
   2366     canvas->clipRect(SkRect::MakeWH(75, 256));
   2367     canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
   2368 }
   2369 ##
   2370 
   2371 #SeeAlso drawColor SkBitmap::erase drawPaint
   2372 
   2373 ##
   2374 
   2375 # ------------------------------------------------------------------------------
   2376 
   2377 #Method void discard()
   2378 #In Utility
   2379 #Line # makes Canvas contents undefined ##
   2380 #Populate
   2381 
   2382 #NoExample
   2383 ##
   2384 
   2385 #SeeAlso flush() GrContext::abandonContext
   2386 
   2387 ##
   2388 
   2389 # ------------------------------------------------------------------------------
   2390 
   2391 #Method void drawPaint(const SkPaint& paint)
   2392 #In Draw
   2393 #Line # fills Clip with Paint ##
   2394 #Populate
   2395 
   2396 #Example
   2397 void draw(SkCanvas* canvas) {
   2398     SkColor     colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
   2399     SkScalar    pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
   2400     SkPaint     paint;
   2401     paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
   2402     canvas->drawPaint(paint);
   2403 }
   2404 ##
   2405 
   2406 #SeeAlso clear drawColor SkBitmap::erase
   2407 
   2408 ##
   2409 
   2410 # ------------------------------------------------------------------------------
   2411 
   2412 #Enum PointMode
   2413 #Line # sets drawPoints options ##
   2414 
   2415 #Code
   2416 #Populate
   2417 ##
   2418 
   2419 Selects if an array of points are drawn as discrete points, as lines, or as
   2420 an open polygon.
   2421 
   2422 #Const kPoints_PointMode 0
   2423 #Line # draw each point separately ##
   2424 ##
   2425 
   2426 #Const kLines_PointMode 1
   2427 #Line # draw each pair of points as a line segment ##
   2428 ##
   2429 
   2430 #Const kPolygon_PointMode 2
   2431 #Line # draw the array of points as a open polygon ##
   2432 ##
   2433 
   2434 #Example
   2435     #Description
   2436         The upper left corner shows three squares when drawn as points.
   2437         The upper right corner shows one line; when drawn as lines, two points are required per line.
   2438         The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
   2439         The lower left corner shows two lines with a miter when path contains polygon.
   2440     ##
   2441 void draw(SkCanvas* canvas) {
   2442   SkPaint paint;
   2443   paint.setStyle(SkPaint::kStroke_Style);
   2444   paint.setStrokeWidth(10);
   2445   SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
   2446   canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
   2447   canvas->translate(128, 0);
   2448   canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
   2449   canvas->translate(0, 128);
   2450   canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
   2451   SkPath path;
   2452   path.addPoly(points, 3, false);
   2453   canvas->translate(-128, 0);
   2454   canvas->drawPath(path, paint);
   2455 }
   2456 ##
   2457 
   2458 #SeeAlso drawLine drawPoint drawPath
   2459 
   2460 ##
   2461 
   2462 # ------------------------------------------------------------------------------
   2463 
   2464 #Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
   2465 #In Draw
   2466 #Line # draws array as points, lines, polygon ##
   2467 #Populate
   2468 
   2469 #Example
   2470 #Height 200
   2471     #Description
   2472     #List
   2473     # The first column draws points. ##
   2474     # The second column draws points as lines. ##
   2475     # The third column draws points as a polygon. ##
   2476     # The fourth column draws points as a polygonal path. ##
   2477     # The first row uses a round cap and round join. ##
   2478     # The second row uses a square cap and a miter join. ##
   2479     # The third row uses a butt cap and a bevel join. ##
   2480     ##
   2481     The transparent color makes multiple line draws visible;
   2482     the path is drawn all at once.
   2483     ##
   2484 void draw(SkCanvas* canvas) {
   2485     SkPaint paint;
   2486     paint.setAntiAlias(true);
   2487     paint.setStyle(SkPaint::kStroke_Style);
   2488     paint.setStrokeWidth(10);
   2489     paint.setColor(0x80349a45);
   2490     const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
   2491     const SkPaint::Join join[] = { SkPaint::kRound_Join,
   2492                                    SkPaint::kMiter_Join,
   2493                                    SkPaint::kBevel_Join };
   2494     int joinIndex = 0;
   2495     SkPath path;
   2496     path.addPoly(points, 3, false);
   2497     for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
   2498         paint.setStrokeCap(cap);
   2499         paint.setStrokeJoin(join[joinIndex++]);
   2500         for (const auto mode : { SkCanvas::kPoints_PointMode,
   2501                                  SkCanvas::kLines_PointMode,
   2502                                  SkCanvas::kPolygon_PointMode } ) {
   2503             canvas->drawPoints(mode, 3, points, paint);
   2504             canvas->translate(64, 0);
   2505         }
   2506         canvas->drawPath(path, paint);
   2507         canvas->translate(-192, 64);
   2508     }
   2509 }
   2510 ##
   2511 
   2512 #SeeAlso drawLine drawPoint drawPath
   2513 
   2514 ##
   2515 
   2516 # ------------------------------------------------------------------------------
   2517 
   2518 #Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
   2519 #In Draw
   2520 #Line # draws point at (x, y) position ##
   2521 #Populate
   2522 
   2523 #Example
   2524 void draw(SkCanvas* canvas) {
   2525   SkPaint paint;
   2526   paint.setAntiAlias(true);
   2527   paint.setColor(0x80349a45);
   2528   paint.setStyle(SkPaint::kStroke_Style);
   2529   paint.setStrokeWidth(100);
   2530   paint.setStrokeCap(SkPaint::kRound_Cap);
   2531   canvas->scale(1, 1.2f);
   2532   canvas->drawPoint(64, 96, paint);
   2533   canvas->scale(.6f, .8f);
   2534   paint.setColor(SK_ColorWHITE);
   2535   canvas->drawPoint(106, 120, paint);
   2536 }
   2537 ##
   2538 
   2539 #SeeAlso drawPoints drawCircle drawRect drawLine drawPath
   2540 
   2541 ##
   2542 
   2543 #Method void drawPoint(SkPoint p, const SkPaint& paint)
   2544 #Populate
   2545 
   2546 #Example
   2547 void draw(SkCanvas* canvas) {
   2548   SkPaint paint;
   2549   paint.setAntiAlias(true);
   2550   paint.setColor(0x80349a45);
   2551   paint.setStyle(SkPaint::kStroke_Style);
   2552   paint.setStrokeWidth(100);
   2553   paint.setStrokeCap(SkPaint::kSquare_Cap);
   2554   canvas->scale(1, 1.2f);
   2555   canvas->drawPoint({64, 96}, paint);
   2556   canvas->scale(.6f, .8f);
   2557   paint.setColor(SK_ColorWHITE);
   2558   canvas->drawPoint(106, 120, paint);
   2559 }
   2560 ##
   2561 
   2562 #SeeAlso drawPoints drawCircle drawRect drawLine drawPath
   2563 
   2564 ##
   2565 
   2566 # ------------------------------------------------------------------------------
   2567 
   2568 #Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
   2569 #In Draw
   2570 #Line # draws line segment between two points ##
   2571 #Populate
   2572 
   2573 #Example
   2574   SkPaint paint;
   2575   paint.setAntiAlias(true);
   2576   paint.setColor(0xFF9a67be);
   2577   paint.setStrokeWidth(20);
   2578   canvas->skew(1, 0);
   2579   canvas->drawLine(32, 96, 32, 160, paint);
   2580   canvas->skew(-2, 0);
   2581   canvas->drawLine(288, 96, 288, 160, paint);
   2582 ##
   2583 
   2584 #SeeAlso drawPoint drawCircle drawRect drawPath
   2585 
   2586 ##
   2587 
   2588 #Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
   2589 #Populate
   2590 
   2591 #Example
   2592   SkPaint paint;
   2593   paint.setAntiAlias(true);
   2594   paint.setColor(0xFF9a67be);
   2595   paint.setStrokeWidth(20);
   2596   canvas->skew(1, 0);
   2597   canvas->drawLine({32, 96}, {32, 160}, paint);
   2598   canvas->skew(-2, 0);
   2599   canvas->drawLine({288, 96}, {288, 160}, paint);
   2600 ##
   2601 
   2602 #SeeAlso drawPoint drawCircle drawRect drawPath
   2603 
   2604 ##
   2605 
   2606 # ------------------------------------------------------------------------------
   2607 
   2608 #Method void drawRect(const SkRect& rect, const SkPaint& paint)
   2609 #In Draw
   2610 #Line # draws Rect using Clip, Matrix, and Paint ##
   2611 #Populate
   2612 
   2613 #Example
   2614 void draw(SkCanvas* canvas) {
   2615     SkPoint rectPts[] = { {64, 48}, {192, 160} };
   2616     SkPaint paint;
   2617     paint.setAntiAlias(true);
   2618     paint.setStyle(SkPaint::kStroke_Style);
   2619     paint.setStrokeWidth(20);
   2620     paint.setStrokeJoin(SkPaint::kRound_Join);
   2621     SkMatrix rotator;
   2622     rotator.setRotate(30, 128, 128);
   2623     for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
   2624         paint.setColor(color);
   2625         SkRect rect;
   2626         rect.set(rectPts[0], rectPts[1]);
   2627         canvas->drawRect(rect, paint);
   2628         rotator.mapPoints(rectPts, 2);
   2629     }
   2630 }
   2631 ##
   2632 
   2633 #SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine
   2634 
   2635 ##
   2636 
   2637 # ------------------------------------------------------------------------------
   2638 
   2639 #Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
   2640 #In Draw
   2641 #Line # draws IRect using Clip, Matrix, and Paint ##
   2642 #Populate
   2643 
   2644 #Example
   2645     SkIRect rect = { 64, 48, 192, 160 };
   2646     SkPaint paint;
   2647     paint.setAntiAlias(true);
   2648     paint.setStyle(SkPaint::kStroke_Style);
   2649     paint.setStrokeWidth(20);
   2650     paint.setStrokeJoin(SkPaint::kRound_Join);
   2651     for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
   2652         paint.setColor(color);
   2653         canvas->drawIRect(rect, paint);
   2654         canvas->rotate(30, 128, 128);
   2655     }
   2656 ##
   2657 
   2658 #SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine
   2659 
   2660 ##
   2661 
   2662 # ------------------------------------------------------------------------------
   2663 
   2664 #Method void drawRegion(const SkRegion& region, const SkPaint& paint)
   2665 #In Draw
   2666 #Line # draws Region using Clip, Matrix, and Paint ##
   2667 #Populate
   2668 
   2669 #Example
   2670 void draw(SkCanvas* canvas) {
   2671     SkRegion region;
   2672     region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
   2673     region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
   2674     SkPaint paint;
   2675     paint.setAntiAlias(true);
   2676     paint.setStyle(SkPaint::kStroke_Style);
   2677     paint.setStrokeWidth(20);
   2678     paint.setStrokeJoin(SkPaint::kRound_Join);
   2679     canvas->drawRegion(region, paint);
   2680 }
   2681 ##
   2682 
   2683 #SeeAlso drawRect drawIRect drawPath
   2684 
   2685 ##
   2686 
   2687 # ------------------------------------------------------------------------------
   2688 
   2689 #Method void drawOval(const SkRect& oval, const SkPaint& paint)
   2690 #In Draw
   2691 #Line # draws Oval using Clip, Matrix, and Paint ##
   2692 #Populate
   2693 
   2694 #Example
   2695 void draw(SkCanvas* canvas) {
   2696     canvas->clear(0xFF3f5f9f);
   2697     SkColor  kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
   2698     SkColor  g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
   2699     SkPoint  g1Points[] = { { 0, 0 }, { 0, 100 } };
   2700     SkScalar pos[] = { 0.2f, 1.0f };
   2701     SkRect bounds = SkRect::MakeWH(80, 70);
   2702     SkPaint paint;
   2703     paint.setAntiAlias(true);
   2704     paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
   2705             SkShader::kClamp_TileMode));
   2706     canvas->drawOval(bounds , paint);
   2707 }
   2708 ##
   2709 
   2710 #SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect
   2711 
   2712 ##
   2713 
   2714 # ------------------------------------------------------------------------------
   2715 
   2716 #Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
   2717 #In Draw
   2718 #Line # draws Round_Rect using Clip, Matrix, and Paint ##
   2719 #Populate
   2720 
   2721 #Example
   2722 void draw(SkCanvas* canvas) {
   2723     SkPaint paint;
   2724     paint.setAntiAlias(true);
   2725     SkRect outer = {30, 40, 210, 220};
   2726     SkRect radii = {30, 50, 70, 90 };
   2727     SkRRect rRect;
   2728     rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
   2729     canvas->drawRRect(rRect, paint);
   2730     paint.setColor(SK_ColorWHITE);
   2731     canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
   2732                      outer.fLeft + radii.fLeft, outer.fBottom, paint);
   2733     canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
   2734                      outer.fRight - radii.fRight, outer.fBottom, paint);
   2735     canvas->drawLine(outer.fLeft,  outer.fTop + radii.fTop,
   2736                      outer.fRight, outer.fTop + radii.fTop, paint);
   2737     canvas->drawLine(outer.fLeft,  outer.fBottom - radii.fBottom,
   2738                      outer.fRight, outer.fBottom - radii.fBottom, paint);
   2739 }
   2740 ##
   2741 
   2742 #SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath
   2743 
   2744 ##
   2745 
   2746 # ------------------------------------------------------------------------------
   2747 
   2748 #Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
   2749 #In Draw
   2750 #Line # draws double Round_Rect stroked or filled ##
   2751 #Populate
   2752 
   2753 #Example
   2754 void draw(SkCanvas* canvas) {
   2755    SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
   2756    SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
   2757    SkPaint paint;
   2758    canvas->drawDRRect(outer, inner, paint);
   2759 }
   2760 ##
   2761 
   2762 #Example
   2763 #Description
   2764     Outer Rect has no corner radii, but stroke join is rounded.
   2765     Inner Round_Rect has corner radii; outset stroke increases radii of corners.
   2766     Stroke join does not affect inner Round_Rect since it has no sharp corners.
   2767 ##
   2768 void draw(SkCanvas* canvas) {
   2769    SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
   2770    SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
   2771    SkPaint paint;
   2772    paint.setAntiAlias(true);
   2773    paint.setStyle(SkPaint::kStroke_Style);
   2774    paint.setStrokeWidth(20);
   2775    paint.setStrokeJoin(SkPaint::kRound_Join);
   2776    canvas->drawDRRect(outer, inner, paint);
   2777    paint.setStrokeWidth(1);
   2778    paint.setColor(SK_ColorWHITE);
   2779    canvas->drawDRRect(outer, inner, paint);
   2780 }
   2781 ##
   2782 
   2783 #SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath
   2784 
   2785 ##
   2786 
   2787 # ------------------------------------------------------------------------------
   2788 
   2789 #Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
   2790 #In Draw
   2791 #Line # draws Circle using Clip, Matrix, and Paint ##
   2792 #Populate
   2793 
   2794 #Example
   2795     void draw(SkCanvas* canvas) {
   2796         SkPaint paint;
   2797         paint.setAntiAlias(true);
   2798         canvas->drawCircle(128, 128, 90, paint);
   2799         paint.setColor(SK_ColorWHITE);
   2800         canvas->drawCircle(86, 86, 20, paint);
   2801         canvas->drawCircle(160, 76, 20, paint);
   2802         canvas->drawCircle(140, 150, 35, paint);
   2803     }
   2804 ##
   2805 
   2806 #SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
   2807 
   2808 ##
   2809 
   2810 #Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
   2811 #Populate
   2812 
   2813 #Example
   2814     void draw(SkCanvas* canvas) {
   2815         SkPaint paint;
   2816         paint.setAntiAlias(true);
   2817         canvas->drawCircle(128, 128, 90, paint);
   2818         paint.setColor(SK_ColorWHITE);
   2819         canvas->drawCircle({86, 86}, 20, paint);
   2820         canvas->drawCircle({160, 76}, 20, paint);
   2821         canvas->drawCircle({140, 150}, 35, paint);
   2822     }
   2823 ##
   2824 
   2825 #SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
   2826 
   2827 ##
   2828 
   2829 # ------------------------------------------------------------------------------
   2830 
   2831 #Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
   2832                  bool useCenter, const SkPaint& paint)
   2833 #In Draw
   2834 #Line # draws Arc using Clip, Matrix, and Paint ##
   2835 #Populate
   2836 
   2837 #Example
   2838     void draw(SkCanvas* canvas) {
   2839         SkPaint paint;
   2840         paint.setAntiAlias(true);
   2841         SkRect oval = { 4, 4, 60, 60};
   2842         for (auto useCenter : { false, true } ) {
   2843             for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
   2844                 paint.setStyle(style);
   2845                 for (auto degrees : { 45, 90, 180, 360} ) {
   2846                     canvas->drawArc(oval, 0, degrees , useCenter, paint);
   2847                     canvas->translate(64, 0);
   2848                 }
   2849                 canvas->translate(-256, 64);
   2850             }
   2851         }
   2852     }
   2853 ##
   2854 
   2855 #Example
   2856 #Height 64
   2857     void draw(SkCanvas* canvas) {
   2858         SkPaint paint;
   2859         paint.setAntiAlias(true);
   2860         paint.setStyle(SkPaint::kStroke_Style);
   2861         paint.setStrokeWidth(4);
   2862         SkRect oval = { 4, 4, 60, 60};
   2863         float intervals[] = { 5, 5 };
   2864         paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
   2865         for (auto degrees : { 270, 360, 540, 720 } ) {
   2866             canvas->drawArc(oval, 0, degrees, false, paint);
   2867             canvas->translate(64, 0);
   2868         }
   2869     }
   2870 ##
   2871 
   2872 #SeeAlso SkPath::arcTo drawCircle drawOval drawPath
   2873 
   2874 ##
   2875 
   2876 # ------------------------------------------------------------------------------
   2877 
   2878 #Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
   2879 #In Draw
   2880 #Line # draws Round_Rect using Clip, Matrix, and Paint ##
   2881 #Populate
   2882 
   2883 #Example
   2884 #Description
   2885     Top row has a zero radius a generates a rectangle.
   2886     Second row radii sum to less than sides.
   2887     Third row radii sum equals sides.
   2888     Fourth row radii sum exceeds sides; radii are scaled to fit.
   2889 ##
   2890     void draw(SkCanvas* canvas) {
   2891         SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
   2892         SkPaint paint;
   2893         paint.setStrokeWidth(15);
   2894         paint.setStrokeJoin(SkPaint::kRound_Join);
   2895         paint.setAntiAlias(true);
   2896         for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style  } ) {
   2897             paint.setStyle(style );
   2898             for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
   2899                canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
   2900                canvas->translate(0, 60);
   2901             }
   2902             canvas->translate(80, -240);
   2903         }
   2904     }
   2905 ##
   2906 
   2907 #SeeAlso drawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint
   2908 
   2909 ##
   2910 
   2911 # ------------------------------------------------------------------------------
   2912 
   2913 #Method void drawPath(const SkPath& path, const SkPaint& paint)
   2914 #In Draw
   2915 #Line # draws Path using Clip, Matrix, and Paint ##
   2916 #Populate
   2917 
   2918 #Example
   2919 #Description
   2920     Top rows draw stroked path with combinations of joins and caps. The open contour
   2921     is affected by caps; the closed contour is affected by joins.
   2922     Bottom row draws fill the same for open and closed contour.
   2923     First bottom column shows winding fills overlap.
   2924     Second bottom column shows even odd fills exclude overlap.
   2925     Third bottom column shows inverse winding fills area outside both contours.
   2926 ##
   2927 void draw(SkCanvas* canvas) {
   2928     SkPath path;
   2929     path.moveTo(20, 20);
   2930     path.quadTo(60, 20, 60, 60);
   2931     path.close();
   2932     path.moveTo(60, 20);
   2933     path.quadTo(60, 60, 20, 60);
   2934     SkPaint paint;
   2935     paint.setStrokeWidth(10);
   2936     paint.setAntiAlias(true);
   2937     paint.setStyle(SkPaint::kStroke_Style);
   2938     for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
   2939         paint.setStrokeJoin(join);
   2940         for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap  } ) {
   2941             paint.setStrokeCap(cap);
   2942             canvas->drawPath(path, paint);
   2943             canvas->translate(80, 0);
   2944         }
   2945         canvas->translate(-240, 60);
   2946     }
   2947     paint.setStyle(SkPaint::kFill_Style);
   2948     for (auto fill : { SkPath::kWinding_FillType,
   2949                        SkPath::kEvenOdd_FillType,
   2950                        SkPath::kInverseWinding_FillType } ) {
   2951         path.setFillType(fill);
   2952         canvas->save();
   2953         canvas->clipRect({0, 10, 80, 70});
   2954         canvas->drawPath(path, paint);
   2955         canvas->restore();
   2956         canvas->translate(80, 0);
   2957     }
   2958 }
   2959 ##
   2960 
   2961 #SeeAlso SkPath drawLine drawArc drawRect drawPoints
   2962 
   2963 ##
   2964 
   2965 # ------------------------------------------------------------------------------
   2966 #Subtopic Draw_Image
   2967 #Line # draws Image to Canvas ##
   2968 
   2969 drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
   2970 a smart pointer as a convenience. The pairs of calls are otherwise identical.
   2971 
   2972 #Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
   2973 #In Draw_Image
   2974 #In Draw
   2975 #Line # draws Image at (x, y) position ##
   2976 #Populate
   2977 
   2978 #Example
   2979 #Height 64
   2980 #Image 4
   2981 void draw(SkCanvas* canvas) {
   2982    // sk_sp<SkImage> image;
   2983    SkImage* imagePtr = image.get();
   2984    canvas->drawImage(imagePtr, 0, 0);
   2985    SkPaint paint;
   2986    canvas->drawImage(imagePtr, 80, 0, &paint);
   2987    paint.setAlpha(0x80);
   2988    canvas->drawImage(imagePtr, 160, 0, &paint);
   2989 }
   2990 ##
   2991 
   2992 #SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
   2993 
   2994 ##
   2995 
   2996 # ------------------------------------------------------------------------------
   2997 
   2998 #Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
   2999                    const SkPaint* paint = nullptr)
   3000 #Populate
   3001 
   3002 #Example
   3003 #Height 64
   3004 #Image 4
   3005 void draw(SkCanvas* canvas) {
   3006    // sk_sp<SkImage> image;
   3007    canvas->drawImage(image, 0, 0);
   3008    SkPaint paint;
   3009    canvas->drawImage(image, 80, 0, &paint);
   3010    paint.setAlpha(0x80);
   3011    canvas->drawImage(image, 160, 0, &paint);
   3012 }
   3013 ##
   3014 
   3015 #SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
   3016 
   3017 ##
   3018 
   3019 # ------------------------------------------------------------------------------
   3020 
   3021 #Enum SrcRectConstraint
   3022 #Line # sets drawImageRect options ##
   3023 
   3024 #Code
   3025 #Populate
   3026 ##
   3027 
   3028 SrcRectConstraint controls the behavior at the edge of source Rect,
   3029 provided to drawImageRect, trading off speed for precision.
   3030 
   3031 Image_Filter in Paint may sample multiple pixels in the image. Source Rect
   3032 restricts the bounds of pixels that may be read. Image_Filter may slow down if
   3033 it cannot read outside the bounds, when sampling near the edge of source Rect.
   3034 SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
   3035 outside source Rect.
   3036 
   3037 #Const kStrict_SrcRectConstraint 0
   3038 #Line # sample only inside bounds; slower ##
   3039     Requires Image_Filter to respect source Rect,
   3040     sampling only inside of its bounds, possibly with a performance penalty.
   3041 ##
   3042 
   3043 #Const kFast_SrcRectConstraint 1
   3044 #Line # sample outside bounds; faster ##
   3045     Permits Image_Filter to sample outside of source Rect
   3046     by half the width of Image_Filter, permitting it to run faster but with
   3047     error at the image edges.
   3048 ##
   3049 
   3050 #Example
   3051 #Height 64
   3052 #Description
   3053     redBorder contains a black and white checkerboard bordered by red.
   3054     redBorder is drawn scaled by 16 on the left.
   3055     The middle and right bitmaps are filtered checkerboards.
   3056     Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
   3057     Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
   3058 ##
   3059 void draw(SkCanvas* canvas) {
   3060     SkBitmap redBorder;
   3061     redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
   3062     SkCanvas checkRed(redBorder);
   3063     checkRed.clear(SK_ColorRED);
   3064     uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
   3065                                { SK_ColorWHITE, SK_ColorBLACK } };
   3066     checkRed.writePixels(
   3067             SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
   3068     canvas->scale(16, 16);
   3069     canvas->drawBitmap(redBorder, 0, 0, nullptr);
   3070     canvas->resetMatrix();
   3071     sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
   3072     SkPaint lowPaint;
   3073     lowPaint.setFilterQuality(kLow_SkFilterQuality);
   3074     for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
   3075                              SkCanvas::kFast_SrcRectConstraint } ) {
   3076         canvas->translate(80, 0);
   3077         canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
   3078                 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
   3079     }
   3080 }
   3081 ##
   3082 
   3083 #SeeAlso drawImageRect drawImage SkPaint::setImageFilter
   3084 
   3085 ##
   3086 
   3087 # ------------------------------------------------------------------------------
   3088 
   3089 #Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
   3090                        const SkPaint* paint,
   3091                        SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3092 #In Draw_Image
   3093 #In Draw
   3094 #Line # draws Image, source Rect to destination Rect ##
   3095 #Populate
   3096 
   3097 #Example
   3098 #Height 64
   3099 #Description
   3100     The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
   3101     its bounds; there is no bleeding with kFast_SrcRectConstraint.
   3102     the middle and right bitmaps draw with kLow_SkFilterQuality; with
   3103     kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
   3104     with kFast_SrcRectConstraint red bleeds on the edges.
   3105 ##
   3106 void draw(SkCanvas* canvas) {
   3107     uint32_t pixels[][4] = {
   3108             { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
   3109             { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
   3110             { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
   3111             { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
   3112     SkBitmap redBorder;
   3113     redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
   3114             (void*) pixels, sizeof(pixels[0]));
   3115     sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
   3116     SkPaint lowPaint;
   3117     for (auto constraint : {
   3118             SkCanvas::kFast_SrcRectConstraint,
   3119             SkCanvas::kStrict_SrcRectConstraint,
   3120             SkCanvas::kFast_SrcRectConstraint } ) {
   3121         canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
   3122                 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
   3123         lowPaint.setFilterQuality(kLow_SkFilterQuality);
   3124         canvas->translate(80, 0);
   3125     }
   3126 }
   3127 ##
   3128 
   3129 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
   3130 
   3131 ##
   3132 
   3133 # ------------------------------------------------------------------------------
   3134 
   3135 #Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
   3136                        const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3137 #In Draw_Image
   3138 #In Draw
   3139 #Populate
   3140 
   3141 #Example
   3142 #Image 4
   3143 void draw(SkCanvas* canvas) {
   3144     // sk_sp<SkImage> image;
   3145     for (auto i : { 1, 2, 4, 8 } ) {
   3146         canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
   3147                 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
   3148     }
   3149 }
   3150 ##
   3151 
   3152 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
   3153 
   3154 ##
   3155 
   3156 # ------------------------------------------------------------------------------
   3157 
   3158 #Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint)
   3159 #In Draw_Image
   3160 #In Draw
   3161 #Populate
   3162 
   3163 #Example
   3164 #Image 4
   3165 void draw(SkCanvas* canvas) {
   3166     // sk_sp<SkImage> image;
   3167     for (auto i : { 20, 40, 80, 160 } ) {
   3168         canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
   3169     }
   3170 }
   3171 ##
   3172 
   3173 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
   3174 
   3175 ##
   3176 
   3177 # ------------------------------------------------------------------------------
   3178 
   3179 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
   3180                        const SkPaint* paint,
   3181                        SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3182 #In Draw_Image
   3183 #In Draw
   3184 #Populate
   3185 
   3186 #Example
   3187 #Height 64
   3188 #Description
   3189     Canvas scales and translates; transformation from src to dst also scales.
   3190     The two matrices are concatenated to create the final transformation.
   3191 ##
   3192 void draw(SkCanvas* canvas) {
   3193     uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
   3194                              { SK_ColorWHITE, SK_ColorBLACK } };
   3195     SkBitmap bitmap;
   3196     bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
   3197             (void*) pixels, sizeof(pixels[0]));
   3198     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
   3199     SkPaint paint;
   3200     canvas->scale(4, 4);
   3201     for (auto alpha : { 50, 100, 150, 255 } ) {
   3202         paint.setAlpha(alpha);
   3203         canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
   3204         canvas->translate(8, 0);
   3205     }
   3206 }
   3207 ##
   3208 
   3209 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
   3210 
   3211 ##
   3212 
   3213 # ------------------------------------------------------------------------------
   3214 
   3215 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
   3216                        const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3217 #In Draw_Image
   3218 #In Draw
   3219 #Populate
   3220 
   3221 #Example
   3222 #Height 64
   3223 void draw(SkCanvas* canvas) {
   3224     uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
   3225                              { 0xAAAAAAAA, 0xFFFFFFFF} };
   3226     SkBitmap bitmap;
   3227     bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
   3228             (void*) pixels, sizeof(pixels[0]));
   3229     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
   3230     SkPaint paint;
   3231     canvas->scale(4, 4);
   3232     for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
   3233         paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
   3234         canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
   3235         canvas->translate(8, 0);
   3236     }
   3237 }
   3238 ##
   3239 
   3240 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
   3241 
   3242 ##
   3243 
   3244 # ------------------------------------------------------------------------------
   3245 
   3246 #Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint)
   3247 #In Draw_Image
   3248 #In Draw
   3249 #Populate
   3250 
   3251 #Example
   3252 #Height 64
   3253 void draw(SkCanvas* canvas) {
   3254     uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
   3255                              { 0xAAAA0000, 0xFFFF0000} };
   3256     SkBitmap bitmap;
   3257     bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
   3258             (void*) pixels, sizeof(pixels[0]));
   3259     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
   3260     SkPaint paint;
   3261     canvas->scale(4, 4);
   3262     for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
   3263         paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
   3264         canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
   3265         canvas->translate(8, 0);
   3266     }
   3267 }
   3268 ##
   3269 
   3270 #SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
   3271 
   3272 ##
   3273 
   3274 # ------------------------------------------------------------------------------
   3275 
   3276 #Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
   3277                        const SkPaint* paint = nullptr)
   3278 #In Draw_Image
   3279 #In Draw
   3280 #Line # draws Nine_Patch Image ##
   3281 
   3282 Draws Image image stretched proportionally to fit into Rect dst.
   3283 IRect center divides the image into nine sections: four sides, four corners, and
   3284 the center. Corners are unmodified or scaled down proportionately if their sides
   3285 are larger than dst; center and four sides are scaled to fit remaining space, if any.
   3286 
   3287 Additionally transform draw using Clip, Matrix, and optional Paint paint.
   3288 
   3289 #paint_as_used_by_draw_lattice_or_draw_nine(image)#
   3290 
   3291 If generated mask extends beyond image bounds, replicate image edge colors, just
   3292 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
   3293 replicates the image edge color when it samples outside of its bounds.
   3294 
   3295 #Param  image      Image containing pixels, dimensions, and format ##
   3296 #Param  center     IRect edge of image corners and sides ##
   3297 #Param  dst        destination Rect of image to draw to ##
   3298 #Param  paint      Paint containing Blend_Mode, Color_Filter, Image_Filter,
   3299                    and so on; or nullptr
   3300 ##
   3301 
   3302 #Example
   3303 #Height 128
   3304 #Description
   3305     The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
   3306     The second image equals the size of center; only corners are drawn without scaling.
   3307     The remaining images are larger than center. All corners draw without scaling.
   3308     The sides and center are scaled if needed to take up the remaining space.
   3309 ##
   3310 void draw(SkCanvas* canvas) {
   3311     SkIRect center = { 20, 10, 50, 40 };
   3312     SkBitmap bitmap;
   3313     bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
   3314     SkCanvas bitCanvas(bitmap);
   3315     SkPaint paint;
   3316     SkColor gray = 0xFF000000;
   3317     int left = 0;
   3318     for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
   3319         int top = 0;
   3320         for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
   3321             paint.setColor(gray);
   3322             bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
   3323             gray += 0x001f1f1f;
   3324             top = bottom;
   3325         }
   3326         left = right;
   3327     }
   3328     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
   3329     SkImage* imagePtr = image.get();
   3330     for (auto dest: { 20, 30, 40, 60, 90 } ) {
   3331         canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
   3332         canvas->translate(dest + 4, 0);
   3333     }
   3334 }
   3335 ##
   3336 
   3337 #SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
   3338 
   3339 ##
   3340 
   3341 # ------------------------------------------------------------------------------
   3342 
   3343 #Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
   3344                        const SkPaint* paint = nullptr)
   3345 #In Draw_Image
   3346 #In Draw
   3347 Draws Image image stretched proportionally to fit into Rect dst.
   3348 IRect center divides the image into nine sections: four sides, four corners, and
   3349 the center. Corners are not scaled, or scaled down proportionately if their sides
   3350 are larger than dst; center and four sides are scaled to fit remaining space, if any.
   3351 
   3352 Additionally transform draw using Clip, Matrix, and optional Paint paint.
   3353 
   3354 #paint_as_used_by_draw_lattice_or_draw_nine(image)#
   3355 
   3356 If generated mask extends beyond image bounds, replicate image edge colors, just
   3357 as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
   3358 replicates the image edge color when it samples outside of its bounds.
   3359 
   3360 #Param  image      Image containing pixels, dimensions, and format ##
   3361 #Param  center     IRect edge of image corners and sides ##
   3362 #Param  dst        destination Rect of image to draw to ##
   3363 #Param  paint      Paint containing Blend_Mode, Color_Filter, Image_Filter,
   3364                    and so on; or nullptr
   3365 ##
   3366 
   3367 #Example
   3368 #Height 128
   3369 #Description
   3370     The two leftmost images has four corners and sides to the left and right of center.
   3371     The leftmost image scales the width of corners proportionately to fit.
   3372     The third and fourth image corners are not scaled; the sides and center are scaled to
   3373     fill the remaining space.
   3374     The rightmost image has four corners scaled vertically to fit, and uses sides above
   3375     and below center to fill the remaining space.
   3376 ##
   3377 void draw(SkCanvas* canvas) {
   3378     SkIRect center = { 20, 10, 50, 40 };
   3379     SkBitmap bitmap;
   3380     bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
   3381     SkCanvas bitCanvas(bitmap);
   3382     SkPaint paint;
   3383     SkColor gray = 0xFF000000;
   3384     int left = 0;
   3385     for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
   3386         int top = 0;
   3387         for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
   3388             paint.setColor(gray);
   3389             bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
   3390             gray += 0x001f1f1f;
   3391             top = bottom;
   3392         }
   3393         left = right;
   3394     }
   3395     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
   3396     for (auto dest: { 20, 30, 40, 60, 90 } ) {
   3397         canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
   3398         canvas->translate(dest + 4, 0);
   3399     }
   3400 }
   3401 ##
   3402 
   3403 #SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
   3404 
   3405 ##
   3406 
   3407 # ------------------------------------------------------------------------------
   3408 
   3409 #Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
   3410                     const SkPaint* paint = nullptr)
   3411 #In Draw_Image
   3412 #In Draw
   3413 #Line # draws Bitmap at (x, y) position ##
   3414 #Populate
   3415 
   3416 #Example
   3417 #Height 64
   3418 void draw(SkCanvas* canvas) {
   3419     uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
   3420                             { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
   3421                             { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
   3422                             { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
   3423                             { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
   3424                             { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
   3425                             { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
   3426                             { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
   3427     SkBitmap bitmap;
   3428     bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
   3429             (void*) pixels, sizeof(pixels[0]));
   3430     SkPaint paint;
   3431     canvas->scale(4, 4);
   3432     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
   3433         paint.setColor(color);
   3434         canvas->drawBitmap(bitmap, 0, 0, &paint);
   3435         canvas->translate(12, 0);
   3436     }
   3437 }
   3438 ##
   3439 
   3440 #SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels
   3441 
   3442 ##
   3443 
   3444 # ------------------------------------------------------------------------------
   3445 
   3446 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
   3447                         const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3448 #In Draw_Image
   3449 #In Draw
   3450 #Line # draws Bitmap, source Rect to destination Rect ##
   3451 #Populate
   3452 
   3453 #Example
   3454 #Height 64
   3455 void draw(SkCanvas* canvas) {
   3456     uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
   3457                             { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
   3458                             { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
   3459                             { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
   3460                             { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
   3461                             { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
   3462                             { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
   3463                             { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
   3464     SkBitmap bitmap;
   3465     bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
   3466             (void*) pixels, sizeof(pixels[0]));
   3467     SkPaint paint;
   3468     paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6));
   3469     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
   3470         paint.setColor(color);
   3471         canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
   3472         canvas->translate(48, 0);
   3473     }
   3474 }
   3475 ##
   3476 
   3477 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
   3478 
   3479 ##
   3480 
   3481 # ------------------------------------------------------------------------------
   3482 
   3483 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
   3484                         const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3485 #In Draw_Image
   3486 #In Draw
   3487 #Populate
   3488 
   3489 #Example
   3490 #Height 64
   3491 void draw(SkCanvas* canvas) {
   3492     uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
   3493                             { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
   3494                             { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
   3495                             { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
   3496                             { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
   3497                             { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
   3498                             { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
   3499                             { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
   3500     SkBitmap bitmap;
   3501     bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
   3502             (void*) pixels, sizeof(pixels[0]));
   3503     SkPaint paint;
   3504     paint.setFilterQuality(kHigh_SkFilterQuality);
   3505     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
   3506         paint.setColor(color);
   3507         canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
   3508         canvas->translate(48.25f, 0);
   3509     }
   3510 }
   3511 ##
   3512 
   3513 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
   3514 
   3515 ##
   3516 
   3517 # ------------------------------------------------------------------------------
   3518 
   3519 #Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
   3520                         SrcRectConstraint constraint = kStrict_SrcRectConstraint)
   3521 #In Draw_Image
   3522 #In Draw
   3523 #Populate
   3524 
   3525 #Example
   3526 #Height 64
   3527 void draw(SkCanvas* canvas) {
   3528     uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
   3529                              { 0xAAAA0000, 0xFFFF0000} };
   3530     SkBitmap bitmap;
   3531     bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
   3532             (void*) pixels, sizeof(pixels[0]));
   3533     SkPaint paint;
   3534     canvas->scale(4, 4);
   3535     for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
   3536         paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
   3537         canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
   3538         canvas->translate(8, 0);
   3539     }
   3540 }
   3541 ##
   3542 
   3543 #SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
   3544 
   3545 ##
   3546 
   3547 # ------------------------------------------------------------------------------
   3548 
   3549 #PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image)
   3550 If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
   3551 Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader.
   3552 If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint
   3553 Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all
   3554 other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels.
   3555 Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state.
   3556 ##
   3557 
   3558 #Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
   3559                         const SkPaint* paint = nullptr)
   3560 #In Draw_Image
   3561 #In Draw
   3562 #Line # draws Nine_Patch Bitmap ##
   3563 
   3564 Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
   3565 IRect center divides the bitmap into nine sections: four sides, four corners,
   3566 and the center. Corners are not scaled, or scaled down proportionately if their
   3567 sides are larger than dst; center and four sides are scaled to fit remaining
   3568 space, if any.
   3569 
   3570 Additionally transform draw using Clip, Matrix, and optional Paint paint.
   3571 
   3572 #paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
   3573 
   3574 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
   3575 just as Shader made from SkShader::MakeBitmapShader with
   3576 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
   3577 outside of its bounds.
   3578 
   3579 #Param  bitmap     Bitmap containing pixels, dimensions, and format ##
   3580 #Param  center     IRect edge of image corners and sides ##
   3581 #Param  dst        destination Rect of image to draw to ##
   3582 #Param  paint    Paint containing Blend_Mode, Color_Filter, Image_Filter,
   3583                  and so on; or nullptr
   3584 ##
   3585 
   3586 #Example
   3587 #Height 128
   3588 #Description
   3589     The two leftmost bitmap draws has four corners and sides to the left and right of center.
   3590     The leftmost bitmap draw scales the width of corners proportionately to fit.
   3591     The third and fourth draw corners are not scaled; the sides and center are scaled to
   3592     fill the remaining space.
   3593     The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
   3594     and below center to fill the remaining space.
   3595 ##
   3596 void draw(SkCanvas* canvas) {
   3597     SkIRect center = { 20, 10, 50, 40 };
   3598     SkBitmap bitmap;
   3599     bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
   3600     SkCanvas bitCanvas(bitmap);
   3601     SkPaint paint;
   3602     SkColor gray = 0xFF000000;
   3603     int left = 0;
   3604     for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
   3605         int top = 0;
   3606         for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
   3607             paint.setColor(gray);
   3608             bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
   3609             gray += 0x001f1f1f;
   3610             top = bottom;
   3611         }
   3612         left = right;
   3613     }
   3614     for (auto dest: { 20, 30, 40, 60, 90 } ) {
   3615         canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
   3616         canvas->translate(dest + 4, 0);
   3617     }
   3618 }
   3619 ##
   3620 
   3621 #SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect
   3622 
   3623 ##
   3624 
   3625 # ------------------------------------------------------------------------------
   3626 #Subtopic Lattice
   3627 #Line # divides Bitmap or Image into a rectangular grid ##
   3628 
   3629 #Struct Lattice
   3630 #Line # divides Bitmap or Image into a rectangular grid ##
   3631 
   3632 #Code
   3633 #Populate
   3634 ##
   3635 
   3636 Lattice divides Bitmap or Image into a rectangular grid.
   3637 Grid entries on even columns and even rows are fixed; these entries are
   3638 always drawn at their original size if the destination is large enough.
   3639 If the destination side is too small to hold the fixed entries, all fixed
   3640 entries are proportionately scaled down to fit.
   3641 The grid entries not on even columns and rows are scaled to fit the
   3642 remaining space, if any.
   3643 
   3644     #Enum RectType
   3645     #Line # optional setting per rectangular grid entry ##
   3646         #Code
   3647         #Populate
   3648         ##
   3649 
   3650         Optional setting per rectangular grid entry to make it transparent,
   3651         or to fill the grid entry with a color.
   3652 
   3653         #Const kDefault 0
   3654         #Line # draws Bitmap into lattice rectangle ##
   3655         ##
   3656 
   3657         #Const kTransparent 1
   3658         #Line # skips lattice rectangle by making it transparent ##
   3659         ##
   3660 
   3661         #Const kFixedColor 2
   3662         #Line # draws one of fColors into lattice rectangle ##
   3663         ##
   3664     ##
   3665 
   3666 #Subtopic Members
   3667 ##
   3668 
   3669     #Member const int*   fXDivs
   3670     #Line # x-axis values dividing bitmap ##
   3671         Array of x-axis values that divide the bitmap vertically.
   3672         Array entries must be unique, increasing, greater than or equal to
   3673         fBounds left edge, and less than fBounds right edge.
   3674         Set the first element to fBounds left to collapse the left column of
   3675         fixed grid entries.
   3676     ##
   3677 
   3678     #Member const int*   fYDivs
   3679     #Line # y-axis values dividing bitmap ##
   3680         Array of y-axis values that divide the bitmap horizontally.
   3681         Array entries must be unique, increasing, greater than or equal to
   3682         fBounds top edge, and less than fBounds bottom edge.
   3683         Set the first element to fBounds top to collapse the top row of fixed
   3684         grid entries.
   3685     ##
   3686 
   3687     #Member const RectType* fRectTypes
   3688     #Line # array of fill types ##
   3689         Optional array of fill types, one per rectangular grid entry:
   3690         array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
   3691 
   3692         Each RectType is one of: kDefault, kTransparent, kFixedColor.
   3693 
   3694         Array entries correspond to the rectangular grid entries, ascending
   3695         left to right and then top to bottom.
   3696     ##
   3697 
   3698     #Member int   fXCount
   3699     #Line # number of x-coordinates ##
   3700         Number of entries in fXDivs array; one less than the number of
   3701         horizontal divisions.
   3702     ##
   3703 
   3704     #Member int   fYCount
   3705     #Line # number of y-coordinates ##
   3706         Number of entries in fYDivs array; one less than the number of vertical
   3707         divisions.
   3708     ##
   3709 
   3710     #Member const SkIRect*   fBounds
   3711     #Line # source bounds to draw from ##
   3712        Optional subset IRect source to draw from.
   3713        If nullptr, source bounds is dimensions of Bitmap or Image.
   3714     ##
   3715 
   3716     #Member const SkColor*   fColors
   3717     #Line # array of colors ##
   3718        Optional array of colors, one per rectangular grid entry.
   3719        Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
   3720 
   3721        Array entries correspond to the rectangular grid entries, ascending
   3722        left to right, then top to bottom.
   3723     ##
   3724 
   3725 #Struct Lattice ##
   3726 
   3727 #Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
   3728                            const SkPaint* paint = nullptr)
   3729 #In Draw_Image
   3730 #In Draw
   3731 #Line # draws proportionally stretched Bitmap ##
   3732 
   3733 Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
   3734 
   3735 Lattice lattice divides bitmap into a rectangular grid.
   3736 Each intersection of an even-numbered row and column is fixed; like the corners
   3737 of drawBitmapNine, fixed lattice elements never scale larger than their initial
   3738 size and shrink proportionately when all fixed elements exceed the bitmap
   3739 dimension. All other grid elements scale to fill the available space, if any.
   3740 
   3741 Additionally transform draw using Clip, Matrix, and optional Paint paint.
   3742 
   3743 #paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
   3744 
   3745 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
   3746 just as Shader made from SkShader::MakeBitmapShader with
   3747 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
   3748 outside of its bounds.
   3749 
   3750 #Param  bitmap     Bitmap containing pixels, dimensions, and format ##
   3751 #Param  lattice    division of bitmap into fixed and variable rectangles ##
   3752 #Param  dst        destination Rect of image to draw to ##
   3753 #Param  paint    Paint containing Blend_Mode, Color_Filter, Image_Filter,
   3754                  and so on; or nullptr
   3755 ##
   3756 
   3757 #Example
   3758 #Height 128
   3759 #Description
   3760     The two leftmost bitmap draws has four corners and sides to the left and right of center.
   3761     The leftmost bitmap draw scales the width of corners proportionately to fit.
   3762     The third and fourth draw corners are not scaled; the sides are scaled to
   3763     fill the remaining space; the center is transparent.
   3764     The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
   3765     and below center to fill the remaining space.
   3766 ##
   3767 void draw(SkCanvas* canvas) {
   3768     SkIRect center = { 20, 10, 50, 40 };
   3769     SkBitmap bitmap;
   3770     bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
   3771     SkCanvas bitCanvas(bitmap);
   3772     SkPaint paint;
   3773     SkColor gray = 0xFF000000;
   3774     int left = 0;
   3775     for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
   3776         int top = 0;
   3777         for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
   3778             paint.setColor(gray);
   3779             bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
   3780             gray += 0x001f1f1f;
   3781             top = bottom;
   3782         }
   3783         left = right;
   3784     }
   3785     const int xDivs[] = { center.fLeft, center.fRight };
   3786     const int yDivs[] = { center.fTop, center.fBottom };
   3787     SkCanvas::Lattice::RectType fillTypes[3][3];
   3788     memset(fillTypes, 0, sizeof(fillTypes));
   3789     fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
   3790     SkColor dummy[9];  // temporary pending bug fix
   3791     SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs),
   3792          SK_ARRAY_COUNT(yDivs), nullptr, dummy };
   3793     for (auto dest: { 20, 30, 40, 60, 90 } ) {
   3794         canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr);
   3795         canvas->translate(dest + 4, 0);
   3796     }
   3797 }
   3798 ##
   3799 
   3800 #SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice
   3801 
   3802 ##
   3803 
   3804 # ------------------------------------------------------------------------------
   3805 
   3806 #Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
   3807                           const SkPaint* paint = nullptr)
   3808 #In Draw_Image
   3809 #In Draw
   3810 #Line # draws proportionally stretched Image ##
   3811 
   3812 Draws Image image stretched proportionally to fit into Rect dst.
   3813 
   3814 Lattice lattice divides image into a rectangular grid.
   3815 Each intersection of an even-numbered row and column is fixed; like the corners
   3816 of drawBitmapNine, fixed lattice elements never scale larger than their initial
   3817 size and shrink proportionately when all fixed elements exceed the bitmap
   3818 dimension. All other grid elements scale to fill the available space, if any.
   3819 
   3820 Additionally transform draw using Clip, Matrix, and optional Paint paint.
   3821 
   3822 #paint_as_used_by_draw_lattice_or_draw_nine(image)#
   3823 
   3824 If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
   3825 just as Shader made from SkShader::MakeBitmapShader with
   3826 SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
   3827 outside of its bounds.
   3828 
   3829 #Param  image      Image containing pixels, dimensions, and format ##
   3830 #Param  lattice    division of bitmap into fixed and variable rectangles ##
   3831 #Param  dst        destination Rect of image to draw to ##
   3832 #Param  paint    Paint containing Blend_Mode, Color_Filter, Image_Filter,
   3833                  and so on; or nullptr
   3834 ##
   3835 
   3836 #Example
   3837 #Height 128
   3838 #Description
   3839     The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
   3840     The second image equals the size of center; only corners are drawn without scaling.
   3841     The remaining images are larger than center. All corners draw without scaling. The sides
   3842     are scaled if needed to take up the remaining space; the center is transparent.
   3843 ##
   3844 void draw(SkCanvas* canvas) {
   3845     SkIRect center = { 20, 10, 50, 40 };
   3846     SkBitmap bitmap;
   3847     bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
   3848     SkCanvas bitCanvas(bitmap);
   3849     SkPaint paint;
   3850     SkColor gray = 0xFF000000;
   3851     int left = 0;
   3852     for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
   3853         int top = 0;
   3854         for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
   3855             paint.setColor(gray);
   3856             bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
   3857             gray += 0x001f1f1f;
   3858             top = bottom;
   3859         }
   3860         left = right;
   3861     }
   3862     sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
   3863     SkImage* imagePtr = image.get();
   3864     for (auto dest: { 20, 30, 40, 60, 90 } ) {
   3865         canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
   3866         canvas->translate(dest + 4, 0);
   3867     }
   3868 }
   3869 ##
   3870 
   3871 #SeeAlso drawBitmapLattice drawImage drawImageNine Lattice
   3872 
   3873 ##
   3874 
   3875 #Subtopic Lattice ##
   3876 
   3877 #Subtopic Draw_Image ##
   3878 
   3879 # ------------------------------------------------------------------------------
   3880 #Subtopic Draw_Text
   3881 #Line # draws text into Canvas ##
   3882 ##
   3883 
   3884 #Method void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
   3885                             SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint)
   3886 #In Draw_Text
   3887 #In Draw
   3888 #Line # draws text at (x, y), using font advance ##
   3889 #Populate
   3890 
   3891 #Example
   3892 #Height 200
   3893 #Description
   3894 The same text is drawn varying Paint_Text_Size and varying
   3895 Matrix.
   3896 ##
   3897 void draw(SkCanvas* canvas) {
   3898     SkPaint paint;
   3899     SkFont font;
   3900     float textSizes[] = { 12, 18, 24, 36 };
   3901     for (auto size: textSizes ) {
   3902         font.setSize(size);
   3903         canvas->drawSimpleText("Aa", 2, kUTF8_SkTextEncoding, 10, 20, font, paint);
   3904         canvas->translate(0, size * 2);
   3905     }
   3906     font.setSize(12);
   3907     float yPos = 20;
   3908     for (auto size: textSizes ) {
   3909         float scale = size / 12.f;
   3910         canvas->resetMatrix();
   3911         canvas->translate(100, 0);
   3912         canvas->scale(scale, scale);
   3913         canvas->drawSimpleText("Aa", 2, kUTF8_SkTextEncoding,
   3914                                10 / scale, yPos / scale, font, paint);
   3915         yPos += size * 2;
   3916     }
   3917 }
   3918 ##
   3919 
   3920 #SeeAlso drawString drawTextBlob
   3921 
   3922 ##
   3923 
   3924 # ------------------------------------------------------------------------------
   3925 
   3926 #Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
   3927 #In Draw_Text
   3928 #In Draw
   3929 #Line # draws text with arrays of positions and Paint ##
   3930 Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
   3931 
   3932 blob contains Glyphs, their positions, and paint attributes specific to text:
   3933 #font_metrics#.
   3934 
   3935 Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
   3936 
   3937 Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha,
   3938 Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and
   3939 Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style:
   3940 Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width;
   3941 apply to Path created from blob.
   3942 
   3943 #Param  blob     Glyphs, positions, and their paints' text size, typeface, and so on ##
   3944 #Param  x        horizontal offset applied to blob ##
   3945 #Param  y        vertical offset applied to blob ##
   3946 #Param  paint    blend, color, stroking, and so on, used to draw ##
   3947 
   3948 #Example
   3949 #Height 120
   3950 void draw(SkCanvas* canvas) {
   3951     SkTextBlobBuilder textBlobBuilder;
   3952     const char bunny[] = "/(^x^)\\";
   3953     const int len = sizeof(bunny) - 1;
   3954     uint16_t glyphs[len];
   3955     SkFont font;
   3956     font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, len);
   3957     int runs[] = { 3, 1, 3 };
   3958     SkPoint textPos = { 20, 100 };
   3959     int glyphIndex = 0;
   3960     for (auto runLen : runs) {
   3961         font.setSize(1 == runLen ? 20 : 50);
   3962         const SkTextBlobBuilder::RunBuffer& run =
   3963                 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY);
   3964         memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
   3965         font.setSize(1 == runLen ? 20 : 50);
   3966         textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen,
   3967                 SkTextEncoding::kGlyphID);
   3968         glyphIndex += runLen;
   3969     }
   3970     sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
   3971     canvas->drawTextBlob(blob.get(), 0, 0, SkPaint());
   3972 }
   3973 ##
   3974 
   3975 #SeeAlso drawText
   3976 
   3977 ##
   3978 
   3979 # ------------------------------------------------------------------------------
   3980 
   3981 #Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
   3982 
   3983 Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
   3984 
   3985 blob contains Glyphs, their positions, and paint attributes specific to text:
   3986 #font_metrics#.
   3987 
   3988 Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
   3989 
   3990 Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter,
   3991 Image_Filter, and Draw_Looper; apply to blob.
   3992 
   3993 #Param  blob     Glyphs, positions, and their paints' text size, typeface, and so on ##
   3994 #Param  x        horizontal offset applied to blob ##
   3995 #Param  y        vertical offset applied to blob ##
   3996 #Param  paint    blend, color, stroking, and so on, used to draw ##
   3997 
   3998 #Example
   3999 #Height 120
   4000 #Description
   4001 Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
   4002 ##
   4003     void draw(SkCanvas* canvas) {
   4004         SkTextBlobBuilder textBlobBuilder;
   4005         SkFont font;
   4006         font.setSize(50);
   4007         const SkTextBlobBuilder::RunBuffer& run =
   4008                 textBlobBuilder.allocRun(font, 1, 20, 100);
   4009         run.glyphs[0] = 20;
   4010         sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
   4011         SkPaint paint;
   4012         paint.setTextSize(10);
   4013         paint.setColor(SK_ColorBLUE);
   4014         canvas->drawTextBlob(blob.get(), 0, 0, paint);
   4015     }
   4016 ##
   4017 
   4018 #SeeAlso drawText
   4019 
   4020 ##
   4021 
   4022 # ------------------------------------------------------------------------------
   4023 
   4024 #Method void drawPicture(const SkPicture* picture)
   4025 #In Draw
   4026 #Line # draws Picture using Clip and Matrix ##
   4027 #Populate
   4028 
   4029 #Example
   4030 void draw(SkCanvas* canvas) {
   4031     SkPictureRecorder recorder;
   4032     SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
   4033     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
   4034         SkPaint paint;
   4035         paint.setColor(color);
   4036         recordingCanvas->drawRect({10, 10, 30, 40}, paint);
   4037         recordingCanvas->translate(10, 10);
   4038         recordingCanvas->scale(1.2f, 1.4f);
   4039     }
   4040     sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
   4041     canvas->drawPicture(playback);
   4042     canvas->scale(2, 2);
   4043     canvas->translate(50, 0);
   4044     canvas->drawPicture(playback);
   4045 }
   4046 ##
   4047 
   4048 #SeeAlso drawDrawable SkPicture SkPicture::playback
   4049 
   4050 ##
   4051 
   4052 # ------------------------------------------------------------------------------
   4053 
   4054 #Method void drawPicture(const sk_sp<SkPicture>& picture)
   4055 #Populate
   4056 
   4057 #Example
   4058 void draw(SkCanvas* canvas) {
   4059     SkPictureRecorder recorder;
   4060     SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
   4061     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
   4062         SkPaint paint;
   4063         paint.setColor(color);
   4064         recordingCanvas->drawRect({10, 10, 30, 40}, paint);
   4065         recordingCanvas->translate(10, 10);
   4066         recordingCanvas->scale(1.2f, 1.4f);
   4067     }
   4068     sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
   4069     canvas->drawPicture(playback);
   4070     canvas->scale(2, 2);
   4071     canvas->translate(50, 0);
   4072     canvas->drawPicture(playback);
   4073 }
   4074 ##
   4075 
   4076 #SeeAlso drawDrawable SkPicture SkPicture::playback
   4077 
   4078 ##
   4079 
   4080 # ------------------------------------------------------------------------------
   4081 
   4082 #Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
   4083 #Populate
   4084 
   4085 #Example
   4086 void draw(SkCanvas* canvas) {
   4087     SkPaint paint;
   4088     SkPictureRecorder recorder;
   4089     SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
   4090     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
   4091         paint.setColor(color);
   4092         recordingCanvas->drawRect({10, 10, 30, 40}, paint);
   4093         recordingCanvas->translate(10, 10);
   4094         recordingCanvas->scale(1.2f, 1.4f);
   4095     }
   4096     sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
   4097     const SkPicture* playbackPtr = playback.get();
   4098     SkMatrix matrix;
   4099     matrix.reset();
   4100     for (auto alpha : { 70, 140, 210 } ) {
   4101     paint.setAlpha(alpha);
   4102     canvas->drawPicture(playbackPtr, &matrix, &paint);
   4103     matrix.preTranslate(70, 70);
   4104     }
   4105 }
   4106 ##
   4107 
   4108 #SeeAlso drawDrawable SkPicture SkPicture::playback
   4109 
   4110 ##
   4111 
   4112 # ------------------------------------------------------------------------------
   4113 
   4114 #Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
   4115 #Populate
   4116 
   4117 #Example
   4118 void draw(SkCanvas* canvas) {
   4119     SkPaint paint;
   4120     SkPictureRecorder recorder;
   4121     SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
   4122     for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
   4123         paint.setColor(color);
   4124         recordingCanvas->drawRect({10, 10, 30, 40}, paint);
   4125         recordingCanvas->translate(10, 10);
   4126         recordingCanvas->scale(1.2f, 1.4f);
   4127     }
   4128     sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
   4129     SkMatrix matrix;
   4130     matrix.reset();
   4131     for (auto alpha : { 70, 140, 210 } ) {
   4132     paint.setAlpha(alpha);
   4133     canvas->drawPicture(playback, &matrix, &paint);
   4134     matrix.preTranslate(70, 70);
   4135     }
   4136 }
   4137 ##
   4138 
   4139 #SeeAlso drawDrawable SkPicture SkPicture::playback
   4140 
   4141 ##
   4142 
   4143 # ------------------------------------------------------------------------------
   4144 
   4145 #Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
   4146 #In Draw
   4147 #Line # draws Vertices, a triangle mesh ##
   4148 #Populate
   4149 
   4150 #Example
   4151 void draw(SkCanvas* canvas) {
   4152     SkPaint paint;
   4153     SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
   4154     SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
   4155     auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
   4156             SK_ARRAY_COUNT(points), points, nullptr, colors);
   4157     canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
   4158 }
   4159 ##
   4160 
   4161 #SeeAlso drawPatch drawPicture
   4162 
   4163 ##
   4164 
   4165 # ------------------------------------------------------------------------------
   4166 
   4167 #Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
   4168 #Populate
   4169 
   4170 #Example
   4171 void draw(SkCanvas* canvas) {
   4172     SkPaint paint;
   4173     SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
   4174     SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
   4175     SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
   4176     paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
   4177             SkShader::kClamp_TileMode));
   4178     auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
   4179             SK_ARRAY_COUNT(points), points, texs, colors);
   4180     canvas->drawVertices(vertices, SkBlendMode::kDarken, paint);
   4181 }
   4182 ##
   4183 
   4184 #SeeAlso drawPatch drawPicture
   4185 
   4186 ##
   4187 
   4188 # ------------------------------------------------------------------------------
   4189 
   4190 #Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
   4191                           int boneCount, SkBlendMode mode, const SkPaint& paint)
   4192 #Populate
   4193 
   4194 #NoExample
   4195 void draw(SkCanvas* canvas) {
   4196     SkPaint paint;
   4197     SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
   4198     SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
   4199     SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
   4200     SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
   4201                                               { 1, 0, 0, 0 },
   4202                                               { 2, 0, 0, 0 },
   4203                                               { 3, 0, 0, 0 } };
   4204     SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
   4205                                               { 1.0f, 0.0f, 0.0f, 0.0f },
   4206                                               { 1.0f, 0.0f, 0.0f, 0.0f },
   4207                                               { 1.0f, 0.0f, 0.0f, 0.0f } };
   4208     SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
   4209                                  {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
   4210                                  {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
   4211                                  {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
   4212     paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
   4213             SkShader::kClamp_TileMode));
   4214     auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
   4215             SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
   4216     canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
   4217 }
   4218 ##
   4219 
   4220 #SeeAlso drawPatch drawPicture
   4221 
   4222 ##
   4223 
   4224 # ------------------------------------------------------------------------------
   4225 
   4226 #Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
   4227                           int boneCount, SkBlendMode mode, const SkPaint& paint)
   4228 #Populate
   4229 
   4230 #NoExample
   4231 void draw(SkCanvas* canvas) {
   4232     SkPaint paint;
   4233     SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
   4234     SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
   4235     SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
   4236     SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
   4237                                               { 1, 0, 0, 0 },
   4238                                               { 2, 0, 0, 0 },
   4239                                               { 3, 0, 0, 0 } };
   4240     SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
   4241                                               { 1.0f, 0.0f, 0.0f, 0.0f },
   4242                                               { 1.0f, 0.0f, 0.0f, 0.0f },
   4243                                               { 1.0f, 0.0f, 0.0f, 0.0f } };
   4244     SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
   4245                                  {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
   4246                                  {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
   4247                                  {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
   4248     paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
   4249             SkShader::kClamp_TileMode));
   4250     auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
   4251             SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
   4252     canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
   4253 }
   4254 ##
   4255 
   4256 #SeeAlso drawPatch drawPicture
   4257 
   4258 ##
   4259 
   4260 # ------------------------------------------------------------------------------
   4261 
   4262 #Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
   4263                    const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
   4264 #In Draw
   4265 #Line # draws Coons_Patch ##
   4266 #Populate
   4267 
   4268 #Example
   4269 #Image 5
   4270 void draw(SkCanvas* canvas) {
   4271     // SkBitmap source = cmbkygk;
   4272     SkPaint paint;
   4273     paint.setFilterQuality(kLow_SkFilterQuality);
   4274     paint.setAntiAlias(true);
   4275     SkPoint cubics[] = { { 3, 1 },    { 4, 2 }, { 5, 1 },    { 7, 3 },
   4276                       /* { 7, 3 }, */ { 6, 4 }, { 7, 5 },    { 5, 7 },
   4277                       /* { 5, 7 }, */ { 4, 6 }, { 3, 7 },    { 1, 5 },
   4278                       /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
   4279     SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
   4280     SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
   4281     paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
   4282                                                        SkShader::kClamp_TileMode, nullptr));
   4283     canvas->scale(15, 15);
   4284     for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
   4285         canvas->drawPatch(cubics, colors, texCoords, blend, paint);
   4286         canvas->translate(4, 4);
   4287     }
   4288 }
   4289 ##
   4290 
   4291 #ToDo can patch use image filter? ##
   4292 #SeeAlso drawVertices drawPicture
   4293 
   4294 ##
   4295 
   4296 # ------------------------------------------------------------------------------
   4297 
   4298 #Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
   4299                    const SkPoint texCoords[4], const SkPaint& paint)
   4300 #Populate
   4301 
   4302 #Example
   4303 void draw(SkCanvas* canvas) {
   4304     SkPaint paint;
   4305     paint.setAntiAlias(true);
   4306     SkPoint cubics[] = { { 3, 1 },    { 4, 2 }, { 5, 1 },    { 7, 3 },
   4307                       /* { 7, 3 }, */ { 6, 4 }, { 7, 5 },    { 5, 7 },
   4308                       /* { 5, 7 }, */ { 4, 6 }, { 3, 7 },    { 1, 5 },
   4309                       /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
   4310     SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
   4311     canvas->scale(30, 30);
   4312     canvas->drawPatch(cubics, colors, nullptr, paint);
   4313     SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
   4314             {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
   4315             {0.5f,3.2f} };
   4316 
   4317     SkFont font(nullptr, 18.f / 30);
   4318     for (int i = 0; i< 10; ++i) {
   4319        char digit = '0' + i;
   4320        canvas->drawSimpleText(&digit, kUTF8_SkTextEncoding, 1, text[i].fX, text[i].fY, font, paint);
   4321     }
   4322     canvas->drawString("10", text[10].fX, text[10].fY, font, paint);
   4323     canvas->drawString("11", text[11].fX, text[11].fY, font, paint);
   4324     paint.setStyle(SkPaint::kStroke_Style);
   4325     canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
   4326     canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
   4327 }
   4328 ##
   4329 
   4330 #Example
   4331 #Image 6
   4332 void draw(SkCanvas* canvas) {
   4333     // SkBitmap source = checkerboard;
   4334     SkPaint paint;
   4335     paint.setFilterQuality(kLow_SkFilterQuality);
   4336     paint.setAntiAlias(true);
   4337     SkPoint cubics[] = { { 3, 1 },    { 4, 2 }, { 5, 1 },    { 7, 3 },
   4338                       /* { 7, 3 }, */ { 6, 4 }, { 7, 5 },    { 5, 7 },
   4339                       /* { 5, 7 }, */ { 4, 6 }, { 3, 7 },    { 1, 5 },
   4340                       /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
   4341     SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
   4342     paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
   4343                                                        SkShader::kClamp_TileMode, nullptr));
   4344     canvas->scale(30, 30);
   4345     canvas->drawPatch(cubics, nullptr, texCoords, paint);
   4346 }
   4347 ##
   4348 
   4349 #ToDo can patch use image filter? ##
   4350 #SeeAlso drawVertices drawPicture
   4351 
   4352 ##
   4353 
   4354 # ------------------------------------------------------------------------------
   4355 
   4356 #Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
   4357                    const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
   4358                    const SkPaint* paint)
   4359 #In Draw
   4360 #Line # draws sprites using Clip, Matrix, and Paint ##
   4361 #Populate
   4362 
   4363 #Example
   4364 #Image 3
   4365 void draw(SkCanvas* canvas) {
   4366   // SkBitmap source = mandrill;
   4367   SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
   4368   SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
   4369   SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
   4370   const SkImage* imagePtr = image.get();
   4371   canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
   4372 }
   4373 ##
   4374 
   4375 #SeeAlso drawBitmap drawImage
   4376 
   4377 ##
   4378 
   4379 # ------------------------------------------------------------------------------
   4380 
   4381 #Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
   4382                    const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
   4383                    const SkPaint* paint)
   4384 #Populate
   4385 
   4386 #Example
   4387 #Image 3
   4388 void draw(SkCanvas* canvas) {
   4389   // SkBitmap source = mandrill;
   4390   SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
   4391   SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
   4392   SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
   4393   SkPaint paint;
   4394   paint.setAlpha(127);
   4395   canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
   4396 }
   4397 ##
   4398 
   4399 #ToDo bug in example on cpu side, gpu looks ok ##
   4400 
   4401 #SeeAlso drawBitmap drawImage
   4402 
   4403 ##
   4404 
   4405 # ------------------------------------------------------------------------------
   4406 
   4407 #Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
   4408                    const SkRect* cullRect, const SkPaint* paint)
   4409 #Populate
   4410 
   4411 #Example
   4412 #Image 3
   4413 void draw(SkCanvas* canvas) {
   4414   // sk_sp<SkImage> image = mandrill;
   4415   SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
   4416   SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
   4417   const SkImage* imagePtr = image.get();
   4418   canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
   4419 }
   4420 ##
   4421 
   4422 #SeeAlso drawBitmap drawImage
   4423 
   4424 ##
   4425 
   4426 # ------------------------------------------------------------------------------
   4427 
   4428 #Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
   4429                    int count, const SkRect* cullRect, const SkPaint* paint)
   4430 #Populate
   4431 
   4432 #Example
   4433 #Image 3
   4434 void draw(SkCanvas* canvas) {
   4435   // sk_sp<SkImage> image = mandrill;
   4436   SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
   4437   SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
   4438   canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
   4439 }
   4440 ##
   4441 
   4442 #SeeAlso drawBitmap drawImage
   4443 
   4444 ##
   4445 
   4446 # ------------------------------------------------------------------------------
   4447 
   4448 #Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
   4449 #In Draw
   4450 #Line # draws Drawable, encapsulated drawing commands ##
   4451 #Populate
   4452 
   4453 #Example
   4454 #Height 100
   4455 #Function
   4456 struct MyDrawable : public SkDrawable {
   4457     SkRect onGetBounds() override { return SkRect::MakeWH(50, 100);  }
   4458 
   4459     void onDraw(SkCanvas* canvas) override {
   4460        SkPath path;
   4461        path.conicTo(10, 90, 50, 90, 0.9f);
   4462        SkPaint paint;
   4463        paint.setColor(SK_ColorBLUE);
   4464        canvas->drawRect(path.getBounds(), paint);
   4465        paint.setAntiAlias(true);
   4466        paint.setColor(SK_ColorWHITE);
   4467        canvas->drawPath(path, paint);
   4468     }
   4469 };
   4470 
   4471 #Function ##
   4472 void draw(SkCanvas* canvas) {
   4473     sk_sp<SkDrawable> drawable(new MyDrawable);
   4474   SkMatrix matrix;
   4475   matrix.setTranslate(10, 10);
   4476   canvas->drawDrawable(drawable.get(), &matrix);
   4477 }
   4478 ##
   4479 
   4480 #SeeAlso SkDrawable drawPicture
   4481 
   4482 ##
   4483 
   4484 # ------------------------------------------------------------------------------
   4485 
   4486 #Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
   4487 #Populate
   4488 
   4489 #Example
   4490 #Height 100
   4491 #Function
   4492 struct MyDrawable : public SkDrawable {
   4493     SkRect onGetBounds() override { return SkRect::MakeWH(50, 100);  }
   4494 
   4495     void onDraw(SkCanvas* canvas) override {
   4496        SkPath path;
   4497        path.conicTo(10, 90, 50, 90, 0.9f);
   4498        SkPaint paint;
   4499        paint.setColor(SK_ColorBLUE);
   4500        canvas->drawRect(path.getBounds(), paint);
   4501        paint.setAntiAlias(true);
   4502        paint.setColor(SK_ColorWHITE);
   4503        canvas->drawPath(path, paint);
   4504     }
   4505 };
   4506 
   4507 #Function ##
   4508 void draw(SkCanvas* canvas) {
   4509     sk_sp<SkDrawable> drawable(new MyDrawable);
   4510   canvas->drawDrawable(drawable.get(), 10, 10);
   4511 }
   4512 ##
   4513 
   4514 #SeeAlso SkDrawable drawPicture
   4515 
   4516 ##
   4517 
   4518 # ------------------------------------------------------------------------------
   4519 
   4520 #Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
   4521 #In Draw
   4522 #In Utility
   4523 #Line # associates a Rect with a key-value pair ##
   4524 #Populate
   4525 
   4526 #Example
   4527     #Height 1
   4528     const char text[] = "Click this link!";
   4529     SkRect bounds;
   4530     SkPaint paint;
   4531     SkFont font(nullptr, 40);
   4532     (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
   4533     const char url[] = "https://www.google.com/";
   4534     sk_sp<SkData> urlData(SkData::MakeWithCString(url));
   4535     canvas->drawAnnotation(bounds, "url_key", urlData.get());
   4536 ##
   4537 
   4538 #SeeAlso SkPicture SkDocument
   4539 
   4540 ##
   4541 
   4542 # ------------------------------------------------------------------------------
   4543 
   4544 #Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
   4545 #Populate
   4546 
   4547 #Example
   4548 #Height 1
   4549     const char text[] = "Click this link!";
   4550     SkRect bounds;
   4551     SkPaint paint;
   4552     SkFont font(nullptr, 40);
   4553     (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
   4554     const char url[] = "https://www.google.com/";
   4555     sk_sp<SkData> urlData(SkData::MakeWithCString(url));
   4556     canvas->drawAnnotation(bounds, "url_key", urlData.get());
   4557 ##
   4558 
   4559 #SeeAlso SkPicture SkDocument
   4560 
   4561 ##
   4562 
   4563 # ------------------------------------------------------------------------------
   4564 
   4565 #Method virtual bool isClipEmpty() const
   4566 #In Property
   4567 #Line # returns if Clip is empty ##
   4568 #Populate
   4569 
   4570 #Example
   4571     void draw(SkCanvas* canvas) {
   4572         SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
   4573         SkPath path;
   4574         canvas->clipPath(path);
   4575         SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
   4576     }
   4577     #StdOut
   4578         clip is not empty
   4579         clip is empty
   4580     ##
   4581 ##
   4582 
   4583 #SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds
   4584 
   4585 ##
   4586 
   4587 # ------------------------------------------------------------------------------
   4588 
   4589 #Method virtual bool isClipRect() const
   4590 #In Property
   4591 #Line # returns if Clip is Rect and not empty ##
   4592 #Populate
   4593 
   4594 #Example
   4595     void draw(SkCanvas* canvas) {
   4596         SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
   4597         canvas->clipRect({0, 0, 0, 0});
   4598         SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
   4599     }
   4600     #StdOut
   4601         clip is rect
   4602         clip is not rect
   4603     ##
   4604 ##
   4605 
   4606 #SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds
   4607 
   4608 ##
   4609 
   4610 #Class SkCanvas ##
   4611 
   4612 #Topic Canvas ##
   4613