Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkCanvas_DEFINED
     11 #define SkCanvas_DEFINED
     12 
     13 #include "SkTypes.h"
     14 #include "SkBitmap.h"
     15 #include "SkDeque.h"
     16 #include "SkClipStack.h"
     17 #include "SkPaint.h"
     18 #include "SkRefCnt.h"
     19 #include "SkPath.h"
     20 #include "SkRegion.h"
     21 #include "SkScalarCompare.h"
     22 #include "SkXfermode.h"
     23 
     24 class SkBounder;
     25 class SkDevice;
     26 class SkDraw;
     27 class SkDrawFilter;
     28 class SkMetaData;
     29 class SkPicture;
     30 class SkRRect;
     31 class SkSurface_Base;
     32 
     33 /** \class SkCanvas
     34 
     35     A Canvas encapsulates all of the state about drawing into a device (bitmap).
     36     This includes a reference to the device itself, and a stack of matrix/clip
     37     values. For any given draw call (e.g. drawRect), the geometry of the object
     38     being drawn is transformed by the concatenation of all the matrices in the
     39     stack. The transformed geometry is clipped by the intersection of all of
     40     the clips in the stack.
     41 
     42     While the Canvas holds the state of the drawing device, the state (style)
     43     of the object being drawn is held by the Paint, which is provided as a
     44     parameter to each of the draw() methods. The Paint holds attributes such as
     45     color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
     46     etc.
     47 */
     48 class SK_API SkCanvas : public SkRefCnt {
     49 public:
     50     SK_DECLARE_INST_COUNT(SkCanvas)
     51 
     52     SkCanvas();
     53 
     54     /** Construct a canvas with the specified device to draw into.
     55 
     56         @param device   Specifies a device for the canvas to draw into.
     57     */
     58     explicit SkCanvas(SkDevice* device);
     59 
     60     /** Deprecated - Construct a canvas with the specified bitmap to draw into.
     61         @param bitmap   Specifies a bitmap for the canvas to draw into. Its
     62                         structure are copied to the canvas.
     63     */
     64     explicit SkCanvas(const SkBitmap& bitmap);
     65     virtual ~SkCanvas();
     66 
     67     SkMetaData& getMetaData();
     68 
     69     ///////////////////////////////////////////////////////////////////////////
     70 
     71     /**
     72      *  Trigger the immediate execution of all pending draw operations.
     73      */
     74     void flush();
     75 
     76     /**
     77      *  Return the width/height of the underlying device. The current drawable
     78      *  area may be small (due to clipping or saveLayer). For a canvas with
     79      *  no device, 0,0 will be returned.
     80      */
     81     SkISize getDeviceSize() const;
     82 
     83     /** Return the canvas' device object, which may be null. The device holds
     84         the bitmap of the pixels that the canvas draws into. The reference count
     85         of the returned device is not changed by this call.
     86     */
     87     SkDevice* getDevice() const;
     88 
     89     /**
     90      *  saveLayer() can create another device (which is later drawn onto
     91      *  the previous device). getTopDevice() returns the top-most device current
     92      *  installed. Note that this can change on other calls like save/restore,
     93      *  so do not access this device after subsequent canvas calls.
     94      *  The reference count of the device is not changed.
     95      *
     96      * @param updateMatrixClip If this is true, then before the device is
     97      *        returned, we ensure that its has been notified about the current
     98      *        matrix and clip. Note: this happens automatically when the device
     99      *        is drawn to, but is optional here, as there is a small perf hit
    100      *        sometimes.
    101      */
    102     SkDevice* getTopDevice(bool updateMatrixClip = false) const;
    103 
    104     /**
    105      *  Shortcut for getDevice()->createCompatibleDevice(...).
    106      *  If getDevice() == NULL, this method does nothing, and returns NULL.
    107      */
    108     SkDevice* createCompatibleDevice(SkBitmap::Config config,
    109                                     int width, int height,
    110                                     bool isOpaque);
    111 
    112     ///////////////////////////////////////////////////////////////////////////
    113 
    114     /**
    115      * This enum can be used with read/writePixels to perform a pixel ops to or
    116      * from an 8888 config other than Skia's native config (SkPMColor). There
    117      * are three byte orders supported: native, BGRA, and RGBA. Each has a
    118      * premultiplied and unpremultiplied variant.
    119      *
    120      * Components of a 8888 pixel can be packed/unpacked from a 32bit word using
    121      * either byte offsets or shift values. Byte offsets are endian-invariant
    122      * while shifts are not. BGRA and RGBA configs are defined by byte
    123      * orderings. The native config is defined by shift values (SK_A32_SHIFT,
    124      * ..., SK_B32_SHIFT).
    125      */
    126     enum Config8888 {
    127         /**
    128          * Skia's native order specified by:
    129          *      SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
    130          *
    131          * kNative_Premul_Config8888 is equivalent to SkPMColor
    132          * kNative_Unpremul_Config8888 has the same component order as SkPMColor
    133          * but is not premultiplied.
    134          */
    135         kNative_Premul_Config8888,
    136         kNative_Unpremul_Config8888,
    137         /**
    138          * low byte to high byte: B, G, R, A.
    139          */
    140         kBGRA_Premul_Config8888,
    141         kBGRA_Unpremul_Config8888,
    142         /**
    143          * low byte to high byte: R, G, B, A.
    144          */
    145         kRGBA_Premul_Config8888,
    146         kRGBA_Unpremul_Config8888
    147     };
    148 
    149     /**
    150      *  On success (returns true), copy the canvas pixels into the bitmap.
    151      *  On failure, the bitmap parameter is left unchanged and false is
    152      *  returned.
    153      *
    154      *  The canvas' pixels are converted to the bitmap's config. The only
    155      *  supported config is kARGB_8888_Config, though this is likely to be
    156      *  relaxed in  the future. The meaning of config kARGB_8888_Config is
    157      *  modified by the enum param config8888. The default value interprets
    158      *  kARGB_8888_Config as SkPMColor
    159      *
    160      *  If the bitmap has pixels already allocated, the canvas pixels will be
    161      *  written there. If not, bitmap->allocPixels() will be called
    162      *  automatically. If the bitmap is backed by a texture readPixels will
    163      *  fail.
    164      *
    165      *  The actual pixels written is the intersection of the canvas' bounds, and
    166      *  the rectangle formed by the bitmap's width,height and the specified x,y.
    167      *  If bitmap pixels extend outside of that intersection, they will not be
    168      *  modified.
    169      *
    170      *  Other failure conditions:
    171      *    * If the canvas is backed by a non-raster device (e.g. PDF) then
    172      *       readPixels will fail.
    173      *    * If bitmap is texture-backed then readPixels will fail. (This may be
    174      *       relaxed in the future.)
    175      *
    176      *  Example that reads the entire canvas into a bitmap using the native
    177      *  SkPMColor:
    178      *    SkISize size = canvas->getDeviceSize();
    179      *    bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
    180      *                                                   size.fHeight);
    181      *    if (canvas->readPixels(bitmap, 0, 0)) {
    182      *       // use the pixels
    183      *    }
    184      */
    185     bool readPixels(SkBitmap* bitmap,
    186                     int x, int y,
    187                     Config8888 config8888 = kNative_Premul_Config8888);
    188 
    189     /**
    190      * DEPRECATED: This will be removed as soon as webkit is no longer relying
    191      * on it. The bitmap is resized to the intersection of srcRect and the
    192      * canvas bounds. New pixels are always allocated on success. Bitmap is
    193      * unmodified on failure.
    194      */
    195     bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
    196 
    197     /**
    198      *  Similar to draw sprite, this method will copy the pixels in bitmap onto
    199      *  the canvas, with the top/left corner specified by (x, y). The canvas'
    200      *  pixel values are completely replaced: there is no blending.
    201      *
    202      *  Currently if bitmap is backed by a texture this is a no-op. This may be
    203      *  relaxed in the future.
    204      *
    205      *  If the bitmap has config kARGB_8888_Config then the config8888 param
    206      *  will determines how the pixel valuess are intepreted. If the bitmap is
    207      *  not kARGB_8888_Config then this parameter is ignored.
    208      *
    209      *  Note: If you are recording drawing commands on this canvas to
    210      *  SkPicture, writePixels() is ignored!
    211      */
    212     void writePixels(const SkBitmap& bitmap,
    213                      int x, int y,
    214                      Config8888 config8888 = kNative_Premul_Config8888);
    215 
    216     ///////////////////////////////////////////////////////////////////////////
    217 
    218     enum SaveFlags {
    219         /** save the matrix state, restoring it on restore() */
    220         kMatrix_SaveFlag            = 0x01,
    221         /** save the clip state, restoring it on restore() */
    222         kClip_SaveFlag              = 0x02,
    223         /** the layer needs to support per-pixel alpha */
    224         kHasAlphaLayer_SaveFlag     = 0x04,
    225         /** the layer needs to support 8-bits per color component */
    226         kFullColorLayer_SaveFlag    = 0x08,
    227         /** the layer should clip against the bounds argument */
    228         kClipToLayer_SaveFlag       = 0x10,
    229 
    230         // helper masks for common choices
    231         kMatrixClip_SaveFlag        = 0x03,
    232         kARGB_NoClipLayer_SaveFlag  = 0x0F,
    233         kARGB_ClipLayer_SaveFlag    = 0x1F
    234     };
    235 
    236     /** This call saves the current matrix, clip, and drawFilter, and pushes a
    237         copy onto a private stack. Subsequent calls to translate, scale,
    238         rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
    239         operate on this copy.
    240         When the balancing call to restore() is made, the previous matrix, clip,
    241         and drawFilter are restored.
    242         @return The value to pass to restoreToCount() to balance this save()
    243     */
    244     virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
    245 
    246     /** This behaves the same as save(), but in addition it allocates an
    247         offscreen bitmap. All drawing calls are directed there, and only when
    248         the balancing call to restore() is made is that offscreen transfered to
    249         the canvas (or the previous layer).
    250         @param bounds (may be null) This rect, if non-null, is used as a hint to
    251                       limit the size of the offscreen, and thus drawing may be
    252                       clipped to it, though that clipping is not guaranteed to
    253                       happen. If exact clipping is desired, use clipRect().
    254         @param paint (may be null) This is copied, and is applied to the
    255                      offscreen when restore() is called
    256         @param flags  LayerFlags
    257         @return The value to pass to restoreToCount() to balance this save()
    258     */
    259     virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
    260                           SaveFlags flags = kARGB_ClipLayer_SaveFlag);
    261 
    262     /** This behaves the same as save(), but in addition it allocates an
    263         offscreen bitmap. All drawing calls are directed there, and only when
    264         the balancing call to restore() is made is that offscreen transfered to
    265         the canvas (or the previous layer).
    266         @param bounds (may be null) This rect, if non-null, is used as a hint to
    267                       limit the size of the offscreen, and thus drawing may be
    268                       clipped to it, though that clipping is not guaranteed to
    269                       happen. If exact clipping is desired, use clipRect().
    270         @param alpha  This is applied to the offscreen when restore() is called.
    271         @param flags  LayerFlags
    272         @return The value to pass to restoreToCount() to balance this save()
    273     */
    274     int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
    275                        SaveFlags flags = kARGB_ClipLayer_SaveFlag);
    276 
    277     /** This call balances a previous call to save(), and is used to remove all
    278         modifications to the matrix/clip/drawFilter state since the last save
    279         call.
    280         It is an error to call restore() more times than save() was called.
    281     */
    282     virtual void restore();
    283 
    284     /** Returns the number of matrix/clip states on the SkCanvas' private stack.
    285         This will equal # save() calls - # restore() calls.
    286     */
    287     int getSaveCount() const;
    288 
    289     /** Efficient way to pop any calls to save() that happened after the save
    290         count reached saveCount. It is an error for saveCount to be less than
    291         getSaveCount()
    292         @param saveCount    The number of save() levels to restore from
    293     */
    294     void restoreToCount(int saveCount);
    295 
    296     /** Returns true if drawing is currently going to a layer (from saveLayer)
    297      *  rather than to the root device.
    298      */
    299     virtual bool isDrawingToLayer() const;
    300 
    301     /** Preconcat the current matrix with the specified translation
    302         @param dx   The distance to translate in X
    303         @param dy   The distance to translate in Y
    304         returns true if the operation succeeded (e.g. did not overflow)
    305     */
    306     virtual bool translate(SkScalar dx, SkScalar dy);
    307 
    308     /** Preconcat the current matrix with the specified scale.
    309         @param sx   The amount to scale in X
    310         @param sy   The amount to scale in Y
    311         returns true if the operation succeeded (e.g. did not overflow)
    312     */
    313     virtual bool scale(SkScalar sx, SkScalar sy);
    314 
    315     /** Preconcat the current matrix with the specified rotation.
    316         @param degrees  The amount to rotate, in degrees
    317         returns true if the operation succeeded (e.g. did not overflow)
    318     */
    319     virtual bool rotate(SkScalar degrees);
    320 
    321     /** Preconcat the current matrix with the specified skew.
    322         @param sx   The amount to skew in X
    323         @param sy   The amount to skew in Y
    324         returns true if the operation succeeded (e.g. did not overflow)
    325     */
    326     virtual bool skew(SkScalar sx, SkScalar sy);
    327 
    328     /** Preconcat the current matrix with the specified matrix.
    329         @param matrix   The matrix to preconcatenate with the current matrix
    330         @return true if the operation succeeded (e.g. did not overflow)
    331     */
    332     virtual bool concat(const SkMatrix& matrix);
    333 
    334     /** Replace the current matrix with a copy of the specified matrix.
    335         @param matrix The matrix that will be copied into the current matrix.
    336     */
    337     virtual void setMatrix(const SkMatrix& matrix);
    338 
    339     /** Helper for setMatrix(identity). Sets the current matrix to identity.
    340     */
    341     void resetMatrix();
    342 
    343     /**
    344      *  Modify the current clip with the specified rectangle.
    345      *  @param rect The rect to combine with the current clip
    346      *  @param op The region op to apply to the current clip
    347      *  @param doAntiAlias true if the clip should be antialiased
    348      *  @return true if the canvas' clip is non-empty
    349      */
    350     virtual bool clipRect(const SkRect& rect,
    351                           SkRegion::Op op = SkRegion::kIntersect_Op,
    352                           bool doAntiAlias = false);
    353 
    354     /**
    355      *  Modify the current clip with the specified SkRRect.
    356      *  @param rrect The rrect to combine with the current clip
    357      *  @param op The region op to apply to the current clip
    358      *  @param doAntiAlias true if the clip should be antialiased
    359      *  @return true if the canvas' clip is non-empty
    360      */
    361     virtual bool clipRRect(const SkRRect& rrect,
    362                            SkRegion::Op op = SkRegion::kIntersect_Op,
    363                            bool doAntiAlias = false);
    364 
    365     /**
    366      *  Modify the current clip with the specified path.
    367      *  @param path The path to combine with the current clip
    368      *  @param op The region op to apply to the current clip
    369      *  @param doAntiAlias true if the clip should be antialiased
    370      *  @return true if the canvas' new clip is non-empty
    371      */
    372     virtual bool clipPath(const SkPath& path,
    373                           SkRegion::Op op = SkRegion::kIntersect_Op,
    374                           bool doAntiAlias = false);
    375 
    376     /** EXPERIMENTAL -- only used for testing
    377         Set to false to force clips to be hard, even if doAntiAlias=true is
    378         passed to clipRect or clipPath.
    379      */
    380     void setAllowSoftClip(bool allow) {
    381         fAllowSoftClip = allow;
    382     }
    383 
    384     /** EXPERIMENTAL -- only used for testing
    385         Set to simplify clip stack using path ops.
    386      */
    387     void setAllowSimplifyClip(bool allow) {
    388         fAllowSimplifyClip = allow;
    389     }
    390 
    391     /** Modify the current clip with the specified region. Note that unlike
    392         clipRect() and clipPath() which transform their arguments by the current
    393         matrix, clipRegion() assumes its argument is already in device
    394         coordinates, and so no transformation is performed.
    395         @param deviceRgn    The region to apply to the current clip
    396         @param op The region op to apply to the current clip
    397         @return true if the canvas' new clip is non-empty
    398     */
    399     virtual bool clipRegion(const SkRegion& deviceRgn,
    400                             SkRegion::Op op = SkRegion::kIntersect_Op);
    401 
    402     /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
    403         specified region. This does not intersect or in any other way account
    404         for the existing clip region.
    405         @param deviceRgn The region to copy into the current clip.
    406         @return true if the new clip region is non-empty
    407     */
    408     bool setClipRegion(const SkRegion& deviceRgn) {
    409         return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
    410     }
    411 
    412     /** Return true if the specified rectangle, after being transformed by the
    413         current matrix, would lie completely outside of the current clip. Call
    414         this to check if an area you intend to draw into is clipped out (and
    415         therefore you can skip making the draw calls).
    416         @param rect the rect to compare with the current clip
    417         @return true if the rect (transformed by the canvas' matrix) does not
    418                      intersect with the canvas' clip
    419     */
    420     bool quickReject(const SkRect& rect) const;
    421 
    422     /** Return true if the specified path, after being transformed by the
    423         current matrix, would lie completely outside of the current clip. Call
    424         this to check if an area you intend to draw into is clipped out (and
    425         therefore you can skip making the draw calls). Note, for speed it may
    426         return false even if the path itself might not intersect the clip
    427         (i.e. the bounds of the path intersects, but the path does not).
    428         @param path The path to compare with the current clip
    429         @return true if the path (transformed by the canvas' matrix) does not
    430                      intersect with the canvas' clip
    431     */
    432     bool quickReject(const SkPath& path) const;
    433 
    434     /** Return true if the horizontal band specified by top and bottom is
    435         completely clipped out. This is a conservative calculation, meaning
    436         that it is possible that if the method returns false, the band may still
    437         in fact be clipped out, but the converse is not true. If this method
    438         returns true, then the band is guaranteed to be clipped out.
    439         @param top  The top of the horizontal band to compare with the clip
    440         @param bottom The bottom of the horizontal and to compare with the clip
    441         @return true if the horizontal band is completely clipped out (i.e. does
    442                      not intersect the current clip)
    443     */
    444     bool quickRejectY(SkScalar top, SkScalar bottom) const {
    445         SkASSERT(SkScalarToCompareType(top) <= SkScalarToCompareType(bottom));
    446         const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
    447         // In the case where the clip is empty and we are provided with a
    448         // negative top and positive bottom parameter then this test will return
    449         // false even though it will be clipped. We have chosen to exclude that
    450         // check as it is rare and would result double the comparisons.
    451         return SkScalarToCompareType(top) >= clipR.fBottom
    452             || SkScalarToCompareType(bottom) <= clipR.fTop;
    453     }
    454 
    455     /** Return the bounds of the current clip (in local coordinates) in the
    456         bounds parameter, and return true if it is non-empty. This can be useful
    457         in a way similar to quickReject, in that it tells you that drawing
    458         outside of these bounds will be clipped out.
    459     */
    460     bool getClipBounds(SkRect* bounds) const;
    461 
    462     /** Return the bounds of the current clip, in device coordinates; returns
    463         true if non-empty. Maybe faster than getting the clip explicitly and
    464         then taking its bounds.
    465     */
    466     bool getClipDeviceBounds(SkIRect* bounds) const;
    467 
    468 
    469     /** Fill the entire canvas' bitmap (restricted to the current clip) with the
    470         specified ARGB color, using the specified mode.
    471         @param a    the alpha component (0..255) of the color to fill the canvas
    472         @param r    the red component (0..255) of the color to fill the canvas
    473         @param g    the green component (0..255) of the color to fill the canvas
    474         @param b    the blue component (0..255) of the color to fill the canvas
    475         @param mode the mode to apply the color in (defaults to SrcOver)
    476     */
    477     void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
    478                   SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
    479 
    480     /** Fill the entire canvas' bitmap (restricted to the current clip) with the
    481         specified color and mode.
    482         @param color    the color to draw with
    483         @param mode the mode to apply the color in (defaults to SrcOver)
    484     */
    485     void drawColor(SkColor color,
    486                    SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
    487 
    488     /**
    489      *  This erases the entire drawing surface to the specified color,
    490      *  irrespective of the clip. It does not blend with the previous pixels,
    491      *  but always overwrites them.
    492      *
    493      *  It is roughly equivalent to the following:
    494      *      canvas.save();
    495      *      canvas.clipRect(hugeRect, kReplace_Op);
    496      *      paint.setColor(color);
    497      *      paint.setXfermodeMode(kSrc_Mode);
    498      *      canvas.drawPaint(paint);
    499      *      canvas.restore();
    500      *  though it is almost always much more efficient.
    501      */
    502     virtual void clear(SkColor);
    503 
    504     /**
    505      *  Fill the entire canvas' bitmap (restricted to the current clip) with the
    506      *  specified paint.
    507      *  @param paint    The paint used to fill the canvas
    508      */
    509     virtual void drawPaint(const SkPaint& paint);
    510 
    511     enum PointMode {
    512         /** drawPoints draws each point separately */
    513         kPoints_PointMode,
    514         /** drawPoints draws each pair of points as a line segment */
    515         kLines_PointMode,
    516         /** drawPoints draws the array of points as a polygon */
    517         kPolygon_PointMode
    518     };
    519 
    520     /** Draw a series of points, interpreted based on the PointMode mode. For
    521         all modes, the count parameter is interpreted as the total number of
    522         points. For kLine mode, count/2 line segments are drawn.
    523         For kPoint mode, each point is drawn centered at its coordinate, and its
    524         size is specified by the paint's stroke-width. It draws as a square,
    525         unless the paint's cap-type is round, in which the points are drawn as
    526         circles.
    527         For kLine mode, each pair of points is drawn as a line segment,
    528         respecting the paint's settings for cap/join/width.
    529         For kPolygon mode, the entire array is drawn as a series of connected
    530         line segments.
    531         Note that, while similar, kLine and kPolygon modes draw slightly
    532         differently than the equivalent path built with a series of moveto,
    533         lineto calls, in that the path will draw all of its contours at once,
    534         with no interactions if contours intersect each other (think XOR
    535         xfermode). drawPoints always draws each element one at a time.
    536         @param mode     PointMode specifying how to draw the array of points.
    537         @param count    The number of points in the array
    538         @param pts      Array of points to draw
    539         @param paint    The paint used to draw the points
    540     */
    541     virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
    542                             const SkPaint& paint);
    543 
    544     /** Helper method for drawing a single point. See drawPoints() for a more
    545         details.
    546     */
    547     void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
    548 
    549     /** Draws a single pixel in the specified color.
    550         @param x        The X coordinate of which pixel to draw
    551         @param y        The Y coordiante of which pixel to draw
    552         @param color    The color to draw
    553     */
    554     void drawPoint(SkScalar x, SkScalar y, SkColor color);
    555 
    556     /** Draw a line segment with the specified start and stop x,y coordinates,
    557         using the specified paint. NOTE: since a line is always "framed", the
    558         paint's Style is ignored.
    559         @param x0    The x-coordinate of the start point of the line
    560         @param y0    The y-coordinate of the start point of the line
    561         @param x1    The x-coordinate of the end point of the line
    562         @param y1    The y-coordinate of the end point of the line
    563         @param paint The paint used to draw the line
    564     */
    565     void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
    566                   const SkPaint& paint);
    567 
    568     /** Draw the specified rectangle using the specified paint. The rectangle
    569         will be filled or stroked based on the Style in the paint.
    570         @param rect     The rect to be drawn
    571         @param paint    The paint used to draw the rect
    572     */
    573     virtual void drawRect(const SkRect& rect, const SkPaint& paint);
    574 
    575     /** Draw the specified rectangle using the specified paint. The rectangle
    576         will be filled or framed based on the Style in the paint.
    577         @param rect     The rect to be drawn
    578         @param paint    The paint used to draw the rect
    579     */
    580     void drawIRect(const SkIRect& rect, const SkPaint& paint)
    581     {
    582         SkRect r;
    583         r.set(rect);    // promotes the ints to scalars
    584         this->drawRect(r, paint);
    585     }
    586 
    587     /** Draw the specified rectangle using the specified paint. The rectangle
    588         will be filled or framed based on the Style in the paint.
    589         @param left     The left side of the rectangle to be drawn
    590         @param top      The top side of the rectangle to be drawn
    591         @param right    The right side of the rectangle to be drawn
    592         @param bottom   The bottom side of the rectangle to be drawn
    593         @param paint    The paint used to draw the rect
    594     */
    595     void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
    596                         SkScalar bottom, const SkPaint& paint);
    597 
    598     /** Draw the specified oval using the specified paint. The oval will be
    599         filled or framed based on the Style in the paint.
    600         @param oval     The rectangle bounds of the oval to be drawn
    601         @param paint    The paint used to draw the oval
    602     */
    603     virtual void drawOval(const SkRect& oval, const SkPaint&);
    604 
    605     /**
    606      *  Draw the specified RRect using the specified paint The rrect will be filled or stroked
    607      *  based on the Style in the paint.
    608      *
    609      *  @param rrect    The round-rect to draw
    610      *  @param paint    The paint used to draw the round-rect
    611      */
    612     virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint);
    613 
    614     /** Draw the specified circle using the specified paint. If radius is <= 0,
    615         then nothing will be drawn. The circle will be filled
    616         or framed based on the Style in the paint.
    617         @param cx       The x-coordinate of the center of the cirle to be drawn
    618         @param cy       The y-coordinate of the center of the cirle to be drawn
    619         @param radius   The radius of the cirle to be drawn
    620         @param paint    The paint used to draw the circle
    621     */
    622     void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
    623                     const SkPaint& paint);
    624 
    625     /** Draw the specified arc, which will be scaled to fit inside the
    626         specified oval. If the sweep angle is >= 360, then the oval is drawn
    627         completely. Note that this differs slightly from SkPath::arcTo, which
    628         treats the sweep angle mod 360.
    629         @param oval The bounds of oval used to define the shape of the arc
    630         @param startAngle Starting angle (in degrees) where the arc begins
    631         @param sweepAngle Sweep angle (in degrees) measured clockwise
    632         @param useCenter true means include the center of the oval. For filling
    633                          this will draw a wedge. False means just use the arc.
    634         @param paint    The paint used to draw the arc
    635     */
    636     void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
    637                  bool useCenter, const SkPaint& paint);
    638 
    639     /** Draw the specified round-rect using the specified paint. The round-rect
    640         will be filled or framed based on the Style in the paint.
    641         @param rect     The rectangular bounds of the roundRect to be drawn
    642         @param rx       The x-radius of the oval used to round the corners
    643         @param ry       The y-radius of the oval used to round the corners
    644         @param paint    The paint used to draw the roundRect
    645     */
    646     void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
    647                        const SkPaint& paint);
    648 
    649     /** Draw the specified path using the specified paint. The path will be
    650         filled or framed based on the Style in the paint.
    651         @param path     The path to be drawn
    652         @param paint    The paint used to draw the path
    653     */
    654     virtual void drawPath(const SkPath& path, const SkPaint& paint);
    655 
    656     /** Draw the specified bitmap, with its top/left corner at (x,y), using the
    657         specified paint, transformed by the current matrix. Note: if the paint
    658         contains a maskfilter that generates a mask which extends beyond the
    659         bitmap's original width/height, then the bitmap will be drawn as if it
    660         were in a Shader with CLAMP mode. Thus the color outside of the original
    661         width/height will be the edge color replicated.
    662         @param bitmap   The bitmap to be drawn
    663         @param left     The position of the left side of the bitmap being drawn
    664         @param top      The position of the top side of the bitmap being drawn
    665         @param paint    The paint used to draw the bitmap, or NULL
    666     */
    667     virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
    668                             const SkPaint* paint = NULL);
    669 
    670     /** Draw the specified bitmap, with the specified matrix applied (before the
    671         canvas' matrix is applied).
    672         @param bitmap   The bitmap to be drawn
    673         @param src      Optional: specify the subset of the bitmap to be drawn
    674         @param dst      The destination rectangle where the scaled/translated
    675                         image will be drawn
    676         @param paint    The paint used to draw the bitmap, or NULL
    677     */
    678     virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
    679                                       const SkRect& dst,
    680                                       const SkPaint* paint);
    681 
    682     void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
    683                         const SkPaint* paint) {
    684         this->drawBitmapRectToRect(bitmap, NULL, dst, paint);
    685     }
    686 
    687     void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
    688                         const SkRect& dst, const SkPaint* paint = NULL) {
    689         SkRect realSrcStorage;
    690         SkRect* realSrcPtr = NULL;
    691         if (isrc) {
    692             realSrcStorage.set(*isrc);
    693             realSrcPtr = &realSrcStorage;
    694         }
    695         this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint);
    696     }
    697 
    698     virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
    699                                   const SkPaint* paint = NULL);
    700 
    701     /**
    702      *  Draw the bitmap stretched differentially to fit into dst.
    703      *  center is a rect within the bitmap, and logically divides the bitmap
    704      *  into 9 sections (3x3). For example, if the middle pixel of a [5x5]
    705      *  bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
    706      *
    707      *  If the dst is >= the bitmap size, then...
    708      *  - The 4 corners are not stretched at all.
    709      *  - The sides are stretched in only one axis.
    710      *  - The center is stretched in both axes.
    711      * Else, for each axis where dst < bitmap,
    712      *  - The corners shrink proportionally
    713      *  - The sides (along the shrink axis) and center are not drawn
    714      */
    715     virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
    716                                 const SkRect& dst, const SkPaint* paint = NULL);
    717 
    718     /** Draw the specified bitmap, with its top/left corner at (x,y),
    719         NOT transformed by the current matrix. Note: if the paint
    720         contains a maskfilter that generates a mask which extends beyond the
    721         bitmap's original width/height, then the bitmap will be drawn as if it
    722         were in a Shader with CLAMP mode. Thus the color outside of the original
    723         width/height will be the edge color replicated.
    724         @param bitmap   The bitmap to be drawn
    725         @param left     The position of the left side of the bitmap being drawn
    726         @param top      The position of the top side of the bitmap being drawn
    727         @param paint    The paint used to draw the bitmap, or NULL
    728     */
    729     virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
    730                             const SkPaint* paint = NULL);
    731 
    732     /** Draw the text, with origin at (x,y), using the specified paint.
    733         The origin is interpreted based on the Align setting in the paint.
    734         @param text The text to be drawn
    735         @param byteLength   The number of bytes to read from the text parameter
    736         @param x        The x-coordinate of the origin of the text being drawn
    737         @param y        The y-coordinate of the origin of the text being drawn
    738         @param paint    The paint used for the text (e.g. color, size, style)
    739     */
    740     virtual void drawText(const void* text, size_t byteLength, SkScalar x,
    741                           SkScalar y, const SkPaint& paint);
    742 
    743     /** Draw the text, with each character/glyph origin specified by the pos[]
    744         array. The origin is interpreted by the Align setting in the paint.
    745         @param text The text to be drawn
    746         @param byteLength   The number of bytes to read from the text parameter
    747         @param pos      Array of positions, used to position each character
    748         @param paint    The paint used for the text (e.g. color, size, style)
    749         */
    750     virtual void drawPosText(const void* text, size_t byteLength,
    751                              const SkPoint pos[], const SkPaint& paint);
    752 
    753     /** Draw the text, with each character/glyph origin specified by the x
    754         coordinate taken from the xpos[] array, and the y from the constY param.
    755         The origin is interpreted by the Align setting in the paint.
    756         @param text The text to be drawn
    757         @param byteLength   The number of bytes to read from the text parameter
    758         @param xpos     Array of x-positions, used to position each character
    759         @param constY   The shared Y coordinate for all of the positions
    760         @param paint    The paint used for the text (e.g. color, size, style)
    761         */
    762     virtual void drawPosTextH(const void* text, size_t byteLength,
    763                               const SkScalar xpos[], SkScalar constY,
    764                               const SkPaint& paint);
    765 
    766     /** Draw the text, with origin at (x,y), using the specified paint, along
    767         the specified path. The paint's Align setting determins where along the
    768         path to start the text.
    769         @param text The text to be drawn
    770         @param byteLength   The number of bytes to read from the text parameter
    771         @param path         The path the text should follow for its baseline
    772         @param hOffset      The distance along the path to add to the text's
    773                             starting position
    774         @param vOffset      The distance above(-) or below(+) the path to
    775                             position the text
    776         @param paint        The paint used for the text
    777     */
    778     void drawTextOnPathHV(const void* text, size_t byteLength,
    779                           const SkPath& path, SkScalar hOffset,
    780                           SkScalar vOffset, const SkPaint& paint);
    781 
    782     /** Draw the text, with origin at (x,y), using the specified paint, along
    783         the specified path. The paint's Align setting determins where along the
    784         path to start the text.
    785         @param text The text to be drawn
    786         @param byteLength   The number of bytes to read from the text parameter
    787         @param path         The path the text should follow for its baseline
    788         @param matrix       (may be null) Applied to the text before it is
    789                             mapped onto the path
    790         @param paint        The paint used for the text
    791         */
    792     virtual void drawTextOnPath(const void* text, size_t byteLength,
    793                                 const SkPath& path, const SkMatrix* matrix,
    794                                 const SkPaint& paint);
    795 
    796 #ifdef SK_BUILD_FOR_ANDROID
    797     /** Draw the text on path, with each character/glyph origin specified by the pos[]
    798         array. The origin is interpreted by the Align setting in the paint.
    799         @param text The text to be drawn
    800         @param byteLength   The number of bytes to read from the text parameter
    801         @param pos      Array of positions, used to position each character
    802         @param paint    The paint used for the text (e.g. color, size, style)
    803         @param path The path to draw on
    804         @param matrix The canvas matrix
    805         */
    806     void drawPosTextOnPath(const void* text, size_t byteLength,
    807                            const SkPoint pos[], const SkPaint& paint,
    808                            const SkPath& path, const SkMatrix* matrix);
    809 #endif
    810 
    811     /** Draw the picture into this canvas. This method effective brackets the
    812         playback of the picture's draw calls with save/restore, so the state
    813         of this canvas will be unchanged after this call.
    814         @param picture The recorded drawing commands to playback into this
    815                        canvas.
    816     */
    817     virtual void drawPicture(SkPicture& picture);
    818 
    819     enum VertexMode {
    820         kTriangles_VertexMode,
    821         kTriangleStrip_VertexMode,
    822         kTriangleFan_VertexMode
    823     };
    824 
    825     /** Draw the array of vertices, interpreted as triangles (based on mode).
    826         @param vmode How to interpret the array of vertices
    827         @param vertexCount The number of points in the vertices array (and
    828                     corresponding texs and colors arrays if non-null)
    829         @param vertices Array of vertices for the mesh
    830         @param texs May be null. If not null, specifies the coordinate
    831                     in _texture_ space (not uv space) for each vertex.
    832         @param colors May be null. If not null, specifies a color for each
    833                       vertex, to be interpolated across the triangle.
    834         @param xmode Used if both texs and colors are present. In this
    835                     case the colors are combined with the texture using mode,
    836                     before being drawn using the paint. If mode is null, then
    837                     kModulate_Mode is used.
    838         @param indices If not null, array of indices to reference into the
    839                     vertex (texs, colors) array.
    840         @param indexCount number of entries in the indices array (if not null)
    841         @param paint Specifies the shader/texture if present.
    842     */
    843     virtual void drawVertices(VertexMode vmode, int vertexCount,
    844                               const SkPoint vertices[], const SkPoint texs[],
    845                               const SkColor colors[], SkXfermode* xmode,
    846                               const uint16_t indices[], int indexCount,
    847                               const SkPaint& paint);
    848 
    849     /** Send a blob of data to the canvas.
    850         For canvases that draw, this call is effectively a no-op, as the data
    851         is not parsed, but just ignored. However, this call exists for
    852         subclasses like SkPicture's recording canvas, that can store the data
    853         and then play it back later (via another call to drawData).
    854      */
    855     virtual void drawData(const void* data, size_t length) {
    856         // do nothing. Subclasses may do something with the data
    857     }
    858 
    859     /** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
    860         Each comment added via addComment is notionally attached to its
    861         enclosing group. Top-level comments simply belong to no group.
    862      */
    863     virtual void beginCommentGroup(const char* description) {
    864         // do nothing. Subclasses may do something
    865     }
    866     virtual void addComment(const char* kywd, const char* value) {
    867         // do nothing. Subclasses may do something
    868     }
    869     virtual void endCommentGroup() {
    870         // do nothing. Subclasses may do something
    871     }
    872 
    873 
    874     //////////////////////////////////////////////////////////////////////////
    875 
    876     /** Get the current bounder object.
    877         The bounder's reference count is unchaged.
    878         @return the canva's bounder (or NULL).
    879     */
    880     SkBounder*  getBounder() const { return fBounder; }
    881 
    882     /** Set a new bounder (or NULL).
    883         Pass NULL to clear any previous bounder.
    884         As a convenience, the parameter passed is also returned.
    885         If a previous bounder exists, its reference count is decremented.
    886         If bounder is not NULL, its reference count is incremented.
    887         @param bounder the new bounder (or NULL) to be installed in the canvas
    888         @return the set bounder object
    889     */
    890     virtual SkBounder* setBounder(SkBounder* bounder);
    891 
    892     /** Get the current filter object. The filter's reference count is not
    893         affected. The filter is saved/restored, just like the matrix and clip.
    894         @return the canvas' filter (or NULL).
    895     */
    896     SkDrawFilter* getDrawFilter() const;
    897 
    898     /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
    899         As a convenience, the parameter is returned. If an existing filter
    900         exists, its refcnt is decrement. If the new filter is not null, its
    901         refcnt is incremented. The filter is saved/restored, just like the
    902         matrix and clip.
    903         @param filter the new filter (or NULL)
    904         @return the new filter
    905     */
    906     virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
    907 
    908     //////////////////////////////////////////////////////////////////////////
    909 
    910     /** Return the current matrix on the canvas.
    911         This does not account for the translate in any of the devices.
    912         @return The current matrix on the canvas.
    913     */
    914     const SkMatrix& getTotalMatrix() const;
    915 
    916     enum ClipType {
    917         kEmpty_ClipType = 0,
    918         kRect_ClipType,
    919         kComplex_ClipType
    920     };
    921 
    922     /** Returns a description of the total clip; may be cheaper than
    923         getting the clip and querying it directly.
    924     */
    925     ClipType getClipType() const;
    926 
    927     /** Return the current device clip (concatenation of all clip calls).
    928      *  This does not account for the translate in any of the devices.
    929      *  @return the current device clip (concatenation of all clip calls).
    930      *
    931      *  DEPRECATED -- call getClipDeviceBounds() instead.
    932      */
    933     const SkRegion& getTotalClip() const;
    934 
    935     /** Return the clip stack. The clip stack stores all the individual
    936      *  clips organized by the save/restore frame in which they were
    937      *  added.
    938      *  @return the current clip stack ("list" of individual clip elements)
    939      */
    940     const SkClipStack* getClipStack() const {
    941         return &fClipStack;
    942     }
    943 
    944     class ClipVisitor {
    945     public:
    946         virtual ~ClipVisitor();
    947         virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
    948         virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
    949     };
    950 
    951     /**
    952      *  Replays the clip operations, back to front, that have been applied to
    953      *  the canvas, calling the appropriate method on the visitor for each
    954      *  clip. All clips have already been transformed into device space.
    955      */
    956     void replayClips(ClipVisitor*) const;
    957 
    958     ///////////////////////////////////////////////////////////////////////////
    959 
    960     /** After calling saveLayer(), there can be any number of devices that make
    961         up the top-most drawing area. LayerIter can be used to iterate through
    962         those devices. Note that the iterator is only valid until the next API
    963         call made on the canvas. Ownership of all pointers in the iterator stays
    964         with the canvas, so none of them should be modified or deleted.
    965     */
    966     class SK_API LayerIter /*: SkNoncopyable*/ {
    967     public:
    968         /** Initialize iterator with canvas, and set values for 1st device */
    969         LayerIter(SkCanvas*, bool skipEmptyClips);
    970         ~LayerIter();
    971 
    972         /** Return true if the iterator is done */
    973         bool done() const { return fDone; }
    974         /** Cycle to the next device */
    975         void next();
    976 
    977         // These reflect the current device in the iterator
    978 
    979         SkDevice*       device() const;
    980         const SkMatrix& matrix() const;
    981         const SkRegion& clip() const;
    982         const SkPaint&  paint() const;
    983         int             x() const;
    984         int             y() const;
    985 
    986     private:
    987         // used to embed the SkDrawIter object directly in our instance, w/o
    988         // having to expose that class def to the public. There is an assert
    989         // in our constructor to ensure that fStorage is large enough
    990         // (though needs to be a compile-time-assert!). We use intptr_t to work
    991         // safely with 32 and 64 bit machines (to ensure the storage is enough)
    992         intptr_t          fStorage[32];
    993         class SkDrawIter* fImpl;    // this points at fStorage
    994         SkPaint           fDefaultPaint;
    995         bool              fDone;
    996     };
    997 
    998 protected:
    999     // Returns the canvas to be used by DrawIter. Default implementation
   1000     // returns this. Subclasses that encapsulate an indirect canvas may
   1001     // need to overload this method. The impl must keep track of this, as it
   1002     // is not released or deleted by the caller.
   1003     virtual SkCanvas* canvasForDrawIter();
   1004 
   1005     // Clip rectangle bounds. Called internally by saveLayer.
   1006     // returns false if the entire rectangle is entirely clipped out
   1007     bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
   1008                         SkIRect* intersection);
   1009 
   1010     // Called by child classes that override clipPath and clipRRect to only
   1011     // track fast conservative clip bounds, rather than exact clips.
   1012     bool updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op,
   1013                                              bool inverseFilled);
   1014 
   1015     // notify our surface (if we have one) that we are about to draw, so it
   1016     // can perform copy-on-write or invalidate any cached images
   1017     void predrawNotify();
   1018 
   1019     /** DEPRECATED -- use constructor(device)
   1020 
   1021      Marked as 'protected' to avoid new clients using this before we can
   1022      completely remove it.
   1023 
   1024      Specify a device for this canvas to draw into. If it is not null, its
   1025      reference count is incremented. If the canvas was already holding a
   1026      device, its reference count is decremented. The new device is returned.
   1027      */
   1028     virtual SkDevice* setDevice(SkDevice* device);
   1029 
   1030 private:
   1031     class MCRec;
   1032 
   1033     SkClipStack fClipStack;
   1034     SkDeque     fMCStack;
   1035     // points to top of stack
   1036     MCRec*      fMCRec;
   1037     // the first N recs that can fit here mean we won't call malloc
   1038     uint32_t    fMCRecStorage[32];
   1039 
   1040     SkBounder*  fBounder;
   1041     int         fSaveLayerCount;    // number of successful saveLayer calls
   1042 
   1043     SkMetaData* fMetaData;
   1044 
   1045     SkSurface_Base*  fSurfaceBase;
   1046     SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
   1047     void setSurfaceBase(SkSurface_Base* sb) {
   1048         fSurfaceBase = sb;
   1049     }
   1050     friend class SkSurface_Base;
   1051     friend class SkSurface_Gpu;
   1052 
   1053     bool fDeviceCMDirty;            // cleared by updateDeviceCMCache()
   1054     void updateDeviceCMCache();
   1055 
   1056     friend class SkDrawIter;    // needs setupDrawForLayerDevice()
   1057     friend class AutoDrawLooper;
   1058 
   1059     SkDevice* createLayerDevice(SkBitmap::Config, int width, int height,
   1060                                 bool isOpaque);
   1061 
   1062     SkDevice* init(SkDevice*);
   1063 
   1064     // internal methods are not virtual, so they can safely be called by other
   1065     // canvas apis, without confusing subclasses (like SkPictureRecording)
   1066     void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
   1067     void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
   1068                                 const SkRect& dst, const SkPaint* paint);
   1069     void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
   1070                                 const SkRect& dst, const SkPaint* paint);
   1071     void internalDrawPaint(const SkPaint& paint);
   1072     int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
   1073                           SaveFlags, bool justForImageFilter);
   1074     void internalDrawDevice(SkDevice*, int x, int y, const SkPaint*);
   1075 
   1076     // shared by save() and saveLayer()
   1077     int internalSave(SaveFlags flags);
   1078     void internalRestore();
   1079     static void DrawRect(const SkDraw& draw, const SkPaint& paint,
   1080                          const SkRect& r, SkScalar textSize);
   1081     static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
   1082                                     const char text[], size_t byteLength,
   1083                                     SkScalar x, SkScalar y);
   1084 
   1085     /*  These maintain a cache of the clip bounds in local coordinates,
   1086         (converted to 2s-compliment if floats are slow).
   1087      */
   1088     mutable SkRectCompareType fLocalBoundsCompareType;
   1089     mutable bool              fLocalBoundsCompareTypeDirty;
   1090     bool fAllowSoftClip;
   1091     bool fAllowSimplifyClip;
   1092 
   1093     const SkRectCompareType& getLocalClipBoundsCompareType() const {
   1094         if (fLocalBoundsCompareTypeDirty) {
   1095             this->computeLocalClipBoundsCompareType();
   1096             fLocalBoundsCompareTypeDirty = false;
   1097         }
   1098         return fLocalBoundsCompareType;
   1099     }
   1100     void computeLocalClipBoundsCompareType() const;
   1101 
   1102 
   1103     class AutoValidateClip : ::SkNoncopyable {
   1104     public:
   1105         explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
   1106             fCanvas->validateClip();
   1107         }
   1108         ~AutoValidateClip() { fCanvas->validateClip(); }
   1109 
   1110     private:
   1111         const SkCanvas* fCanvas;
   1112     };
   1113 
   1114 #ifdef SK_DEBUG
   1115     void validateClip() const;
   1116 #else
   1117     void validateClip() const {}
   1118 #endif
   1119 
   1120     typedef SkRefCnt INHERITED;
   1121 };
   1122 
   1123 /** Stack helper class to automatically call restoreToCount() on the canvas
   1124     when this object goes out of scope. Use this to guarantee that the canvas
   1125     is restored to a known state.
   1126 */
   1127 class SkAutoCanvasRestore : SkNoncopyable {
   1128 public:
   1129     SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
   1130         SkASSERT(canvas);
   1131         fSaveCount = canvas->getSaveCount();
   1132         if (doSave) {
   1133             canvas->save();
   1134         }
   1135     }
   1136     ~SkAutoCanvasRestore() {
   1137         if (fCanvas) {
   1138             fCanvas->restoreToCount(fSaveCount);
   1139         }
   1140     }
   1141 
   1142     /**
   1143      *  Perform the restore now, instead of waiting for the destructor. Will
   1144      *  only do this once.
   1145      */
   1146     void restore() {
   1147         if (fCanvas) {
   1148             fCanvas->restoreToCount(fSaveCount);
   1149             fCanvas = NULL;
   1150         }
   1151     }
   1152 
   1153 private:
   1154     SkCanvas*   fCanvas;
   1155     int         fSaveCount;
   1156 };
   1157 
   1158 /** Stack helper class to automatically open and close a comment block
   1159  */
   1160 class SkAutoCommentBlock : SkNoncopyable {
   1161 public:
   1162     SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
   1163         fCanvas = canvas;
   1164         if (NULL != fCanvas) {
   1165             fCanvas->beginCommentGroup(description);
   1166         }
   1167     }
   1168 
   1169     ~SkAutoCommentBlock() {
   1170         if (NULL != fCanvas) {
   1171             fCanvas->endCommentGroup();
   1172         }
   1173     }
   1174 
   1175 private:
   1176     SkCanvas* fCanvas;
   1177 };
   1178 
   1179 #endif
   1180