From 0910916c0f7b951ee55c4b7c6358295b9bca0565 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 19:30:35 -0800 Subject: auto import from //depot/cupcake/@135843 --- include/core/SkCanvas.h | 794 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 794 insertions(+) create mode 100644 include/core/SkCanvas.h (limited to 'include/core/SkCanvas.h') diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h new file mode 100644 index 0000000..a19a5ae --- /dev/null +++ b/include/core/SkCanvas.h @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SkCanvas_DEFINED +#define SkCanvas_DEFINED + +#include "SkTypes.h" +#include "SkBitmap.h" +#include "SkDeque.h" +#include "SkPaint.h" +#include "SkRefCnt.h" +#include "SkPorterDuff.h" +#include "SkPath.h" +#include "SkRegion.h" +#include "SkScalarCompare.h" + +class SkBounder; +class SkDevice; +class SkDraw; +class SkDrawFilter; +class SkPicture; + +/** \class SkCanvas + + A Canvas encapsulates all of the state about drawing into a device (bitmap). + This includes a reference to the device itself, and a stack of matrix/clip + values. For any given draw call (e.g. drawRect), the geometry of the object + being drawn is transformed by the concatenation of all the matrices in the + stack. The transformed geometry is clipped by the intersection of all of + the clips in the stack. + + While the Canvas holds the state of the drawing device, the state (style) + of the object being drawn is held by the Paint, which is provided as a + parameter to each of the draw() methods. The Paint holds attributes such as + color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns), + etc. +*/ +class SkCanvas : public SkRefCnt { +public: + /** Construct a canvas with the specified bitmap to draw into. + @param bitmap Specifies a bitmap for the canvas to draw into. Its + structure are copied to the canvas. + */ + explicit SkCanvas(const SkBitmap& bitmap); + /** Construct a canvas with the specified device to draw into. + @param device Specifies a device for the canvas to draw into. The + device may be null. + */ + explicit SkCanvas(SkDevice* device = NULL); + virtual ~SkCanvas(); + + /////////////////////////////////////////////////////////////////////////// + + /** If this subclass of SkCanvas supports GL viewports, return true and set + size (if not null) to the size of the viewport. If it is not supported, + ignore vp and return false. + */ + virtual bool getViewport(SkIPoint* size) const; + + /** If this subclass of SkCanvas supports GL viewports, return true and set + the viewport to the specified x and y dimensions. If it is not + supported, ignore x and y and return false. + */ + virtual bool setViewport(int x, int y); + + /** Return the canvas' device object, which may be null. The device holds + the bitmap of the pixels that the canvas draws into. The reference count + of the returned device is not changed by this call. + */ + SkDevice* getDevice() const; + + /** Specify a device for this canvas to draw into. If it is not null, its + reference count is incremented. If the canvas was already holding a + device, its reference count is decremented. The new device is returned. + */ + SkDevice* setDevice(SkDevice* device); + + /** Specify a bitmap for the canvas to draw into. This is a help method for + setDevice(), and it creates a device for the bitmap by calling + createDevice(). The structure of the bitmap is copied into the device. + */ + virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap); + + /////////////////////////////////////////////////////////////////////////// + + enum SaveFlags { + /** save the matrix state, restoring it on restore() */ + kMatrix_SaveFlag = 0x01, + /** save the clip state, restoring it on restore() */ + kClip_SaveFlag = 0x02, + /** the layer needs to support per-pixel alpha */ + kHasAlphaLayer_SaveFlag = 0x04, + /** the layer needs to support 8-bits per color component */ + kFullColorLayer_SaveFlag = 0x08, + /** the layer should clip against the bounds argument */ + kClipToLayer_SaveFlag = 0x10, + + // helper masks for common choices + kMatrixClip_SaveFlag = 0x03, + kARGB_NoClipLayer_SaveFlag = 0x0F, + kARGB_ClipLayer_SaveFlag = 0x1F + }; + + /** This call saves the current matrix and clip information, and pushes a + copy onto a private stack. Subsequent calls to translate, scale, + rotate, skew, concat or clipRect, clipPath all operate on this copy. + When the balancing call to restore() is made, this copy is deleted and + the previous matrix/clip state is restored. + @return The value to pass to restoreToCount() to balance this save() + */ + virtual int save(SaveFlags flags = kMatrixClip_SaveFlag); + + /** This behaves the same as save(), but in addition it allocates an + offscreen bitmap. All drawing calls are directed there, and only when + the balancing call to restore() is made is that offscreen transfered to + the canvas (or the previous layer). Subsequent calls to translate, + scale, rotate, skew, concat or clipRect, clipPath all operate on this + copy. When the balancing call to restore() is made, this copy is deleted + and the previous matrix/clip state is restored. + @param bounds (may be null) the maximum size the offscreen bitmap needs + to be (in local coordinates) + @param paint (may be null) This is copied, and is applied to the + offscreen when restore() is called + @param flags LayerFlags + @return The value to pass to restoreToCount() to balance this save() + */ + virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, + SaveFlags flags = kARGB_ClipLayer_SaveFlag); + + /** This behaves the same as save(), but in addition it allocates an + offscreen bitmap. All drawing calls are directed there, and only when + the balancing call to restore() is made is that offscreen transfered to + the canvas (or the previous layer). Subsequent calls to translate, + scale, rotate, skew, concat or clipRect, clipPath all operate on this + copy. When the balancing call to restore() is made, this copy is deleted + and the previous matrix/clip state is restored. + @param bounds (may be null) the maximum size the offscreen bitmap needs + to be (in local coordinates) + @param alpha This is applied to the offscreen when restore() is called. + @param flags LayerFlags + @return The value to pass to restoreToCount() to balance this save() + */ + int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, + SaveFlags flags = kARGB_ClipLayer_SaveFlag); + + /** This call balances a previous call to save(), and is used to remove all + modifications to the matrix/clip state since the last save call. It is + an error to call restore() more times than save() was called. + */ + virtual void restore(); + + /** Returns the number of matrix/clip states on the SkCanvas' private stack. + This will equal # save() calls - # restore() calls. + */ + int getSaveCount() const; + + /** Efficient way to pop any calls to save() that happened after the save + count reached saveCount. It is an error for saveCount to be less than + getSaveCount() + @param saveCount The number of save() levels to restore from + */ + void restoreToCount(int saveCount); + + /** Preconcat the current matrix with the specified translation + @param dx The distance to translate in X + @param dy The distance to translate in Y + returns true if the operation succeeded (e.g. did not overflow) + */ + virtual bool translate(SkScalar dx, SkScalar dy); + + /** Preconcat the current matrix with the specified scale. + @param sx The amount to scale in X + @param sy The amount to scale in Y + returns true if the operation succeeded (e.g. did not overflow) + */ + virtual bool scale(SkScalar sx, SkScalar sy); + + /** Preconcat the current matrix with the specified rotation. + @param degrees The amount to rotate, in degrees + returns true if the operation succeeded (e.g. did not overflow) + */ + virtual bool rotate(SkScalar degrees); + + /** Preconcat the current matrix with the specified skew. + @param sx The amount to skew in X + @param sy The amount to skew in Y + returns true if the operation succeeded (e.g. did not overflow) + */ + virtual bool skew(SkScalar sx, SkScalar sy); + + /** Preconcat the current matrix with the specified matrix. + @param matrix The matrix to preconcatenate with the current matrix + @return true if the operation succeeded (e.g. did not overflow) + */ + virtual bool concat(const SkMatrix& matrix); + + /** Replace the current matrix with a copy of the specified matrix. + @param matrix The matrix that will be copied into the current matrix. + */ + virtual void setMatrix(const SkMatrix& matrix); + + /** Helper for setMatrix(identity). Sets the current matrix to identity. + */ + void resetMatrix(); + + /** Modify the current clip with the specified rectangle. + @param rect The rect to intersect with the current clip + @param op The region op to apply to the current clip + @return true if the canvas' clip is non-empty + */ + virtual bool clipRect(const SkRect& rect, + SkRegion::Op op = SkRegion::kIntersect_Op); + + /** Modify the current clip with the specified path. + @param path The path to apply to the current clip + @param op The region op to apply to the current clip + @return true if the canvas' new clip is non-empty + */ + virtual bool clipPath(const SkPath& path, + SkRegion::Op op = SkRegion::kIntersect_Op); + + /** Modify the current clip with the specified region. Note that unlike + clipRect() and clipPath() which transform their arguments by the current + matrix, clipRegion() assumes its argument is already in device + coordinates, and so no transformation is performed. + @param deviceRgn The region to apply to the current clip + @param op The region op to apply to the current clip + @return true if the canvas' new clip is non-empty + */ + virtual bool clipRegion(const SkRegion& deviceRgn, + SkRegion::Op op = SkRegion::kIntersect_Op); + + /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the + specified region. This does not intersect or in any other way account + for the existing clip region. + @param deviceRgn The region to copy into the current clip. + @return true if the new clip region is non-empty + */ + bool setClipRegion(const SkRegion& deviceRgn) { + return this->clipRegion(deviceRgn, SkRegion::kReplace_Op); + } + + /** Enum describing how to treat edges when performing quick-reject tests + of a geometry against the current clip. Treating them as antialiased + (kAA_EdgeType) will take into account the extra pixels that may be drawn + if the edge does not lie exactly on a device pixel boundary (after being + transformed by the current matrix). + */ + enum EdgeType { + /** Treat the edges as B&W (not antialiased) for the purposes of testing + against the current clip + */ + kBW_EdgeType, + /** Treat the edges as antialiased for the purposes of testing + against the current clip + */ + kAA_EdgeType + }; + + /** Return true if the specified rectangle, after being transformed by the + current matrix, would lie completely outside of the current clip. Call + this to check if an area you intend to draw into is clipped out (and + therefore you can skip making the draw calls). + @param rect the rect to compare with the current clip + @param et specifies how to treat the edges (see EdgeType) + @return true if the rect (transformed by the canvas' matrix) does not + intersect with the canvas' clip + */ + bool quickReject(const SkRect& rect, EdgeType et) const; + + /** Return true if the specified path, after being transformed by the + current matrix, would lie completely outside of the current clip. Call + this to check if an area you intend to draw into is clipped out (and + therefore you can skip making the draw calls). Note, for speed it may + return false even if the path itself might not intersect the clip + (i.e. the bounds of the path intersects, but the path does not). + @param path The path to compare with the current clip + @param et specifies how to treat the edges (see EdgeType) + @return true if the path (transformed by the canvas' matrix) does not + intersect with the canvas' clip + */ + bool quickReject(const SkPath& path, EdgeType et) const; + + /** Return true if the horizontal band specified by top and bottom is + completely clipped out. This is a conservative calculation, meaning + that it is possible that if the method returns false, the band may still + in fact be clipped out, but the converse is not true. If this method + returns true, then the band is guaranteed to be clipped out. + @param top The top of the horizontal band to compare with the clip + @param bottom The bottom of the horizontal and to compare with the clip + @return true if the horizontal band is completely clipped out (i.e. does + not intersect the current clip) + */ + bool quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const; + + /** Return the bounds of the current clip (in local coordinates) in the + bounds parameter, and return true if it is non-empty. This can be useful + in a way similar to quickReject, in that it tells you that drawing + outside of these bounds will be clipped out. + */ + bool getClipBounds(SkRect* bounds, EdgeType et = kAA_EdgeType) const; + + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified ARGB color, using the specified PorterDuff mode. + @param a the alpha component (0..255) of the color to fill the canvas + @param r the red component (0..255) of the color to fill the canvas + @param g the green component (0..255) of the color to fill the canvas + @param b the blue component (0..255) of the color to fill the canvas + @param mode the mode to apply the color in (defaults to SrcOver) + */ + void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, + SkPorterDuff::Mode mode = SkPorterDuff::kSrcOver_Mode); + + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified color and porter-duff xfermode. + @param color the color to draw with + @param mode the mode to apply the color in (defaults to SrcOver) + */ + void drawColor(SkColor color, + SkPorterDuff::Mode mode = SkPorterDuff::kSrcOver_Mode); + + /** Fill the entire canvas' bitmap (restricted to the current clip) with the + specified paint. + @param paint The paint used to fill the canvas + */ + virtual void drawPaint(const SkPaint& paint); + + enum PointMode { + /** drawPoints draws each point separately */ + kPoints_PointMode, + /** drawPoints draws each pair of points as a line segment */ + kLines_PointMode, + /** drawPoints draws the array of points as a polygon */ + kPolygon_PointMode + }; + + /** Draw a series of points, interpreted based on the PointMode mode. For + all modes, the count parameter is interpreted as the total number of + points. For kLine mode, count/2 line segments are drawn. + For kPoint mode, each point is drawn centered at its coordinate, and its + size is specified by the paint's stroke-width. It draws as a square, + unless the paint's cap-type is round, in which the points are drawn as + circles. + For kLine mode, each pair of points is drawn as a line segment, + respecting the paint's settings for cap/join/width. + For kPolygon mode, the entire array is drawn as a series of connected + line segments. + Note that, while similar, kLine and kPolygon modes draw slightly + differently than the equivalent path built with a series of moveto, + lineto calls, in that the path will draw all of its contours at once, + with no interactions if contours intersect each other (think XOR + xfermode). drawPoints always draws each element one at a time. + @param mode PointMode specifying how to draw the array of points. + @param count The number of points in the array + @param pts Array of points to draw + @param paint The paint used to draw the points + */ + virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], + const SkPaint& paint); + + /** Helper method for drawing a single point. See drawPoints() for a more + details. + */ + void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint); + + /** Draws a single pixel in the specified color. + @param x The X coordinate of which pixel to draw + @param y The Y coordiante of which pixel to draw + @param color The color to draw + */ + void drawPoint(SkScalar x, SkScalar y, SkColor color); + + /** Draw a line segment with the specified start and stop x,y coordinates, + using the specified paint. NOTE: since a line is always "framed", the + paint's Style is ignored. + @param x0 The x-coordinate of the start point of the line + @param y0 The y-coordinate of the start point of the line + @param x1 The x-coordinate of the end point of the line + @param y1 The y-coordinate of the end point of the line + @param paint The paint used to draw the line + */ + void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, + const SkPaint& paint); + + /** Draw the specified rectangle using the specified paint. The rectangle + will be filled or stroked based on the Style in the paint. + @param rect The rect to be drawn + @param paint The paint used to draw the rect + */ + virtual void drawRect(const SkRect& rect, const SkPaint& paint); + + /** Draw the specified rectangle using the specified paint. The rectangle + will be filled or framed based on the Style in the paint. + @param rect The rect to be drawn + @param paint The paint used to draw the rect + */ + void drawIRect(const SkIRect& rect, const SkPaint& paint) + { + SkRect r; + r.set(rect); // promotes the ints to scalars + this->drawRect(r, paint); + } + + /** Draw the specified rectangle using the specified paint. The rectangle + will be filled or framed based on the Style in the paint. + @param left The left side of the rectangle to be drawn + @param top The top side of the rectangle to be drawn + @param right The right side of the rectangle to be drawn + @param bottom The bottom side of the rectangle to be drawn + @param paint The paint used to draw the rect + */ + void drawRectCoords(SkScalar left, SkScalar top, SkScalar right, + SkScalar bottom, const SkPaint& paint); + + /** Draw the specified oval using the specified paint. The oval will be + filled or framed based on the Style in the paint. + @param oval The rectangle bounds of the oval to be drawn + @param paint The paint used to draw the oval + */ + void drawOval(const SkRect& oval, const SkPaint&); + + /** Draw the specified circle using the specified paint. If radius is <= 0, + then nothing will be drawn. The circle will be filled + or framed based on the Style in the paint. + @param cx The x-coordinate of the center of the cirle to be drawn + @param cy The y-coordinate of the center of the cirle to be drawn + @param radius The radius of the cirle to be drawn + @param paint The paint used to draw the circle + */ + void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, + const SkPaint& paint); + + /** Draw the specified arc, which will be scaled to fit inside the + specified oval. If the sweep angle is >= 360, then the oval is drawn + completely. Note that this differs slightly from SkPath::arcTo, which + treats the sweep angle mod 360. + @param oval The bounds of oval used to define the shape of the arc + @param startAngle Starting angle (in degrees) where the arc begins + @param sweepAngle Sweep angle (in degrees) measured clockwise + @param useCenter true means include the center of the oval. For filling + this will draw a wedge. False means just use the arc. + @param paint The paint used to draw the arc + */ + void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, + bool useCenter, const SkPaint& paint); + + /** Draw the specified round-rect using the specified paint. The round-rect + will be filled or framed based on the Style in the paint. + @param rect The rectangular bounds of the roundRect to be drawn + @param rx The x-radius of the oval used to round the corners + @param ry The y-radius of the oval used to round the corners + @param paint The paint used to draw the roundRect + */ + void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, + const SkPaint& paint); + + /** Draw the specified path using the specified paint. The path will be + filled or framed based on the Style in the paint. + @param path The path to be drawn + @param paint The paint used to draw the path + */ + virtual void drawPath(const SkPath& path, const SkPaint& paint); + + /** Draw the specified bitmap, with its top/left corner at (x,y), using the + specified paint, transformed by the current matrix. Note: if the paint + contains a maskfilter that generates a mask which extends beyond the + bitmap's original width/height, then the bitmap will be drawn as if it + were in a Shader with CLAMP mode. Thus the color outside of the original + width/height will be the edge color replicated. + @param bitmap The bitmap to be drawn + @param left The position of the left side of the bitmap being drawn + @param top The position of the top side of the bitmap being drawn + @param paint The paint used to draw the bitmap, or NULL + */ + virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, + const SkPaint* paint = NULL); + + /** Draw the specified bitmap, with the specified matrix applied (before the + canvas' matrix is applied). + @param bitmap The bitmap to be drawn + @param src Optional: specify the subset of the bitmap to be drawn + @param dst The destination rectangle where the scaled/translated + image will be drawn + @param paint The paint used to draw the bitmap, or NULL + */ + virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, + const SkRect& dst, const SkPaint* paint = NULL); + + virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, + const SkPaint* paint = NULL); + + /** Draw the specified bitmap, with its top/left corner at (x,y), + NOT transformed by the current matrix. Note: if the paint + contains a maskfilter that generates a mask which extends beyond the + bitmap's original width/height, then the bitmap will be drawn as if it + were in a Shader with CLAMP mode. Thus the color outside of the original + width/height will be the edge color replicated. + @param bitmap The bitmap to be drawn + @param left The position of the left side of the bitmap being drawn + @param top The position of the top side of the bitmap being drawn + @param paint The paint used to draw the bitmap, or NULL + */ + virtual void drawSprite(const SkBitmap& bitmap, int left, int top, + const SkPaint* paint = NULL); + + /** Draw the text, with origin at (x,y), using the specified paint. + The origin is interpreted based on the Align setting in the paint. + @param text The text to be drawn + @param byteLength The number of bytes to read from the text parameter + @param x The x-coordinate of the origin of the text being drawn + @param y The y-coordinate of the origin of the text being drawn + @param paint The paint used for the text (e.g. color, size, style) + */ + virtual void drawText(const void* text, size_t byteLength, SkScalar x, + SkScalar y, const SkPaint& paint); + + /** Draw the text, with each character/glyph origin specified by the pos[] + array. The origin is interpreted by the Align setting in the paint. + @param text The text to be drawn + @param byteLength The number of bytes to read from the text parameter + @param pos Array of positions, used to position each character + @param paint The paint used for the text (e.g. color, size, style) + */ + virtual void drawPosText(const void* text, size_t byteLength, + const SkPoint pos[], const SkPaint& paint); + + /** Draw the text, with each character/glyph origin specified by the x + coordinate taken from the xpos[] array, and the y from the constY param. + The origin is interpreted by the Align setting in the paint. + @param text The text to be drawn + @param byteLength The number of bytes to read from the text parameter + @param xpos Array of x-positions, used to position each character + @param constY The shared Y coordinate for all of the positions + @param paint The paint used for the text (e.g. color, size, style) + */ + virtual void drawPosTextH(const void* text, size_t byteLength, + const SkScalar xpos[], SkScalar constY, + const SkPaint& paint); + + /** Draw the text, with origin at (x,y), using the specified paint, along + the specified path. The paint's Align setting determins where along the + path to start the text. + @param text The text to be drawn + @param byteLength The number of bytes to read from the text parameter + @param path The path the text should follow for its baseline + @param hOffset The distance along the path to add to the text's + starting position + @param vOffset The distance above(-) or below(+) the path to + position the text + @param paint The paint used for the text + */ + void drawTextOnPathHV(const void* text, size_t byteLength, + const SkPath& path, SkScalar hOffset, + SkScalar vOffset, const SkPaint& paint); + + /** Draw the text, with origin at (x,y), using the specified paint, along + the specified path. The paint's Align setting determins where along the + path to start the text. + @param text The text to be drawn + @param byteLength The number of bytes to read from the text parameter + @param path The path the text should follow for its baseline + @param matrix (may be null) Applied to the text before it is + mapped onto the path + @param paint The paint used for the text + */ + virtual void drawTextOnPath(const void* text, size_t byteLength, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint); + + /** Draw the picture into this canvas. This method effective brackets the + playback of the picture's draw calls with save/restore, so the state + of this canvas will be unchanged after this call. This contrasts with + the more immediate method SkPicture::draw(), which does not bracket + the canvas with save/restore, thus the canvas may be left in a changed + state after the call. + @param picture The recorded drawing commands to playback into this + canvas. + */ + virtual void drawPicture(SkPicture& picture); + + enum VertexMode { + kTriangles_VertexMode, + kTriangleStrip_VertexMode, + kTriangleFan_VertexMode + }; + + /** Draw the array of vertices, interpreted as triangles (based on mode). + @param vmode How to interpret the array of vertices + @param vertexCount The number of points in the vertices array (and + corresponding texs and colors arrays if non-null) + @param vertices Array of vertices for the mesh + @param texs May be null. If not null, specifies the coordinate + in texture space for each vertex. + @param colors May be null. If not null, specifies a color for each + vertex, to be interpolated across the triangle. + @param xmode Used if both texs and colors are present. In this + case the colors are combined with the texture using mode, + before being drawn using the paint. If mode is null, then + the porter-duff MULTIPLY mode is used. + @param indices If not null, array of indices to reference into the + vertex (texs, colors) array. + @param indexCount number of entries in the indices array (if not null) + @param paint Specifies the shader/texture if present. + */ + virtual void drawVertices(VertexMode vmode, int vertexCount, + const SkPoint vertices[], const SkPoint texs[], + const SkColor colors[], SkXfermode* xmode, + const uint16_t indices[], int indexCount, + const SkPaint& paint); + + ////////////////////////////////////////////////////////////////////////// + + /** Get the current bounder object. + The bounder's reference count is unchaged. + @return the canva's bounder (or NULL). + */ + SkBounder* getBounder() const { return fBounder; } + + /** Set a new bounder (or NULL). + Pass NULL to clear any previous bounder. + As a convenience, the parameter passed is also returned. + If a previous bounder exists, its reference count is decremented. + If bounder is not NULL, its reference count is incremented. + @param bounder the new bounder (or NULL) to be installed in the canvas + @return the set bounder object + */ + virtual SkBounder* setBounder(SkBounder* bounder); + + /** Get the current filter object. The filter's reference count is not + affected. The filter is part of the state this is affected by + save/restore. + @return the canvas' filter (or NULL). + */ + SkDrawFilter* getDrawFilter() const; + + /** Set the new filter (or NULL). Pass NULL to clear any existing filter. + As a convenience, the parameter is returned. If an existing filter + exists, its refcnt is decrement. If the new filter is not null, its + refcnt is incremented. The filter is part of the state this is affected + by save/restore. + @param filter the new filter (or NULL) + @return the new filter + */ + virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter); + + ////////////////////////////////////////////////////////////////////////// + + /** Return the current matrix on the canvas. + This does not account for the translate in any of the devices. + @return The current matrix on the canvas. + */ + const SkMatrix& getTotalMatrix() const; + + /** Return the current device clip (concatenation of all clip calls). + This does not account for the translate in any of the devices. + @return the current device clip (concatenation of all clip calls). + */ + const SkRegion& getTotalClip() const; + + /** May be overridden by subclasses. This returns a compatible device + for this canvas, with the specified config/width/height. If isOpaque + is true, then the underlying bitmap is optimized to assume that every + pixel will be drawn to, and thus it does not need to clear the alpha + channel ahead of time (assuming the specified config supports per-pixel + alpha.) If isOpaque is false, then the bitmap should clear its alpha + channel. + */ + virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, + bool isOpaque, bool isForLayer); + + /////////////////////////////////////////////////////////////////////////// + + /** After calling saveLayer(), there can be any number of devices that make + up the top-most drawing area. LayerIter can be used to iterate through + those devices. Note that the iterator is only valid until the next API + call made on the canvas. Ownership of all pointers in the iterator stays + with the canvas, so none of them should be modified or deleted. + */ + class LayerIter /*: SkNoncopyable*/ { + public: + /** Initialize iterator with canvas, and set values for 1st device */ + LayerIter(SkCanvas*, bool skipEmptyClips); + ~LayerIter(); + + /** Return true if the iterator is done */ + bool done() const { return fDone; } + /** Cycle to the next device */ + void next(); + + // These reflect the current device in the iterator + + SkDevice* device() const; + const SkMatrix& matrix() const; + const SkRegion& clip() const; + const SkPaint& paint() const; + int x() const; + int y() const; + + private: + // used to embed the SkDrawIter object directly in our instance, w/o + // having to expose that class def to the public. There is an assert + // in our constructor to ensure that fStorage is large enough + // (though needs to be a compile-time-assert!). We use intptr_t to work + // safely with 32 and 64 bit machines (to ensure the storage is enough) + intptr_t fStorage[12]; + class SkDrawIter* fImpl; // this points at fStorage + SkPaint fDefaultPaint; + bool fDone; + }; + +protected: + // all of the drawBitmap variants call this guy + virtual void commonDrawBitmap(const SkBitmap&, const SkMatrix& m, + const SkPaint& paint); + +private: + class MCRec; + + SkDeque fMCStack; + // points to top of stack + MCRec* fMCRec; + // the first N recs that can fit here mean we won't call malloc + uint32_t fMCRecStorage[32]; + + SkBounder* fBounder; + + void prepareForDeviceDraw(SkDevice*); + + bool fDeviceCMDirty; // cleared by updateDeviceCMCache() + void updateDeviceCMCache(); + + friend class SkDrawIter; // needs setupDrawForLayerDevice() + + SkDevice* init(SkDevice*); + void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, + const SkPaint* paint); + void drawDevice(SkDevice*, int x, int y, const SkPaint*); + // shared by save() and saveLayer() + int internalSave(SaveFlags flags); + void internalRestore(); + + /* These maintain a cache of the clip bounds in local coordinates, + (converted to 2s-compliment if floats are slow). + */ + mutable SkRectCompareType fLocalBoundsCompareType; + mutable bool fLocalBoundsCompareTypeDirty; + + const SkRectCompareType& getLocalClipBoundsCompareType() const { + if (fLocalBoundsCompareTypeDirty) { + this->computeLocalClipBoundsCompareType(); + fLocalBoundsCompareTypeDirty = false; + } + return fLocalBoundsCompareType; + } + void computeLocalClipBoundsCompareType() const; +}; + +/** Stack helper class to automatically call restoreToCount() on the canvas + when this object goes out of scope. Use this to guarantee that the canvas + is restored to a known state. +*/ +class SkAutoCanvasRestore : SkNoncopyable { +public: + SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) { + SkASSERT(canvas); + fSaveCount = canvas->getSaveCount(); + if (doSave) { + canvas->save(); + } + } + ~SkAutoCanvasRestore() { + fCanvas->restoreToCount(fSaveCount); + } + +private: + SkCanvas* fCanvas; + int fSaveCount; +}; + +#endif + -- cgit v1.1