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