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