blob: 1e153078c7828580adba5f4a432343faa74a632f [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkCanvas_DEFINED
18#define SkCanvas_DEFINED
19
20#include "SkTypes.h"
21#include "SkBitmap.h"
22#include "SkDeque.h"
reed@google.com5c3d1472011-02-22 19:12:23 +000023#include "SkClipStack.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000024#include "SkPaint.h"
25#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000026#include "SkPath.h"
27#include "SkRegion.h"
28#include "SkScalarCompare.h"
reed@android.com845fdac2009-06-23 03:01:32 +000029#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000030
31class SkBounder;
32class SkDevice;
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000033class SkDeviceFactory;
reed@android.com8a1c16f2008-12-17 15:59:43 +000034class SkDraw;
35class SkDrawFilter;
36class SkPicture;
reed@android.comf76bacf2009-05-13 14:00:33 +000037class SkShape;
reed@android.com8a1c16f2008-12-17 15:59:43 +000038
39/** \class SkCanvas
40
41 A Canvas encapsulates all of the state about drawing into a device (bitmap).
42 This includes a reference to the device itself, and a stack of matrix/clip
43 values. For any given draw call (e.g. drawRect), the geometry of the object
44 being drawn is transformed by the concatenation of all the matrices in the
45 stack. The transformed geometry is clipped by the intersection of all of
46 the clips in the stack.
47
48 While the Canvas holds the state of the drawing device, the state (style)
49 of the object being drawn is held by the Paint, which is provided as a
50 parameter to each of the draw() methods. The Paint holds attributes such as
51 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
52 etc.
53*/
54class SkCanvas : public SkRefCnt {
55public:
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000056 /** Construct a canvas with the given device factory.
57 @param factory Specify the factory for generating additional devices.
vandebo@chromium.orgb70ae312010-10-15 18:58:19 +000058 The factory may be null, in which case
59 SkRasterDeviceFactory will be used.
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000060 */
61 explicit SkCanvas(SkDeviceFactory* factory = NULL);
62
63 /** Construct a canvas with the specified device to draw into. The device
64 factory will be retrieved from the passed device.
65 @param device Specifies a device for the canvas to draw into.
66 */
67 explicit SkCanvas(SkDevice* device);
68
69 /** Deprecated - Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +000070 @param bitmap Specifies a bitmap for the canvas to draw into. Its
71 structure are copied to the canvas.
72 */
73 explicit SkCanvas(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +000074 virtual ~SkCanvas();
75
76 ///////////////////////////////////////////////////////////////////////////
77
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000078 /** If the Device supports GL viewports, return true and set size (if not
79 null) to the size of the viewport. If it is not supported, ignore size
80 and return false.
reed@android.com8a1c16f2008-12-17 15:59:43 +000081 */
82 virtual bool getViewport(SkIPoint* size) const;
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000083
84 /** If the Device supports GL viewports, return true and set the viewport
85 to the specified x and y dimensions. If it is not supported, ignore x
86 and y and return false.
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 */
88 virtual bool setViewport(int x, int y);
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 /** Specify a device for this canvas to draw into. If it is not null, its
97 reference count is incremented. If the canvas was already holding a
98 device, its reference count is decremented. The new device is returned.
99 */
100 SkDevice* setDevice(SkDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000101
reed@android.comf2b98d62010-12-20 18:26:13 +0000102 /** May be overridden by subclasses. This returns a compatible device
103 for this canvas, with the specified config/width/height. If the device
104 is raster, the pixels will be allocated automatically.
105 */
106 virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
107 bool isOpaque, bool forLayer = false);
108
109 /**
110 * Create a new raster device and make it current. This also returns
111 * the new device.
112 */
113 SkDevice* setBitmapDevice(const SkBitmap& bitmap, bool forLayer = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114
reed@google.com51df9e32010-12-23 19:29:18 +0000115 /**
reed@google.com4b226022011-01-11 18:32:13 +0000116 * Return the current device factory, or NULL.
117 */
118 SkDeviceFactory* getDeviceFactory() const { return fDeviceFactory; }
119
120 /**
121 * Replace any existing factory with the specified factory.
122 */
123 SkDeviceFactory* setDeviceFactory(SkDeviceFactory*);
124
125 ///////////////////////////////////////////////////////////////////////////
126
127 /**
reed@google.com51df9e32010-12-23 19:29:18 +0000128 * Copy the pixels from the device into bitmap. Returns true on success.
129 * If false is returned, then the bitmap parameter is left unchanged.
reed@google.com3dd42b32011-02-07 22:44:43 +0000130 * The bitmap parameter is treated as output-only, and will be completely
131 * overwritten (if the method returns true).
reed@google.com51df9e32010-12-23 19:29:18 +0000132 */
133 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
134 bool readPixels(SkBitmap* bitmap);
135
136 /**
137 * Similar to draw sprite, this method will copy the pixels in bitmap onto
138 * the device, with the top/left corner specified by (x, y). The pixel
139 * values in the device are completely replaced: there is no blending.
140 */
141 void writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000142
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000144
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 enum SaveFlags {
146 /** save the matrix state, restoring it on restore() */
147 kMatrix_SaveFlag = 0x01,
148 /** save the clip state, restoring it on restore() */
149 kClip_SaveFlag = 0x02,
150 /** the layer needs to support per-pixel alpha */
151 kHasAlphaLayer_SaveFlag = 0x04,
152 /** the layer needs to support 8-bits per color component */
153 kFullColorLayer_SaveFlag = 0x08,
154 /** the layer should clip against the bounds argument */
155 kClipToLayer_SaveFlag = 0x10,
156
157 // helper masks for common choices
158 kMatrixClip_SaveFlag = 0x03,
159 kARGB_NoClipLayer_SaveFlag = 0x0F,
160 kARGB_ClipLayer_SaveFlag = 0x1F
161 };
162
reed@android.comdc3381f2010-02-11 16:05:15 +0000163 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000165 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
166 operate on this copy.
167 When the balancing call to restore() is made, the previous matrix, clip,
168 and drawFilter are restored.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169 @return The value to pass to restoreToCount() to balance this save()
170 */
171 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
172
173 /** This behaves the same as save(), but in addition it allocates an
174 offscreen bitmap. All drawing calls are directed there, and only when
175 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000176 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000177 @param bounds (may be null) This rect, if non-null, is used as a hint to
178 limit the size of the offscreen, and thus drawing may be
179 clipped to it, though that clipping is not guaranteed to
180 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181 @param paint (may be null) This is copied, and is applied to the
182 offscreen when restore() is called
183 @param flags LayerFlags
184 @return The value to pass to restoreToCount() to balance this save()
185 */
186 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
187 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
188
189 /** This behaves the same as save(), but in addition it allocates an
190 offscreen bitmap. All drawing calls are directed there, and only when
191 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000192 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000193 @param bounds (may be null) This rect, if non-null, is used as a hint to
194 limit the size of the offscreen, and thus drawing may be
195 clipped to it, though that clipping is not guaranteed to
196 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197 @param alpha This is applied to the offscreen when restore() is called.
198 @param flags LayerFlags
199 @return The value to pass to restoreToCount() to balance this save()
200 */
201 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
202 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
203
204 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000205 modifications to the matrix/clip/drawFilter state since the last save
206 call.
207 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 */
209 virtual void restore();
210
211 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
212 This will equal # save() calls - # restore() calls.
213 */
214 int getSaveCount() const;
215
216 /** Efficient way to pop any calls to save() that happened after the save
217 count reached saveCount. It is an error for saveCount to be less than
218 getSaveCount()
219 @param saveCount The number of save() levels to restore from
220 */
221 void restoreToCount(int saveCount);
222
223 /** Preconcat the current matrix with the specified translation
224 @param dx The distance to translate in X
225 @param dy The distance to translate in Y
226 returns true if the operation succeeded (e.g. did not overflow)
227 */
228 virtual bool translate(SkScalar dx, SkScalar dy);
229
230 /** Preconcat the current matrix with the specified scale.
231 @param sx The amount to scale in X
232 @param sy The amount to scale in Y
233 returns true if the operation succeeded (e.g. did not overflow)
234 */
235 virtual bool scale(SkScalar sx, SkScalar sy);
236
237 /** Preconcat the current matrix with the specified rotation.
238 @param degrees The amount to rotate, in degrees
239 returns true if the operation succeeded (e.g. did not overflow)
240 */
241 virtual bool rotate(SkScalar degrees);
242
243 /** Preconcat the current matrix with the specified skew.
244 @param sx The amount to skew in X
245 @param sy The amount to skew in Y
246 returns true if the operation succeeded (e.g. did not overflow)
247 */
248 virtual bool skew(SkScalar sx, SkScalar sy);
249
250 /** Preconcat the current matrix with the specified matrix.
251 @param matrix The matrix to preconcatenate with the current matrix
252 @return true if the operation succeeded (e.g. did not overflow)
253 */
254 virtual bool concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000255
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 /** Replace the current matrix with a copy of the specified matrix.
257 @param matrix The matrix that will be copied into the current matrix.
258 */
259 virtual void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000260
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261 /** Helper for setMatrix(identity). Sets the current matrix to identity.
262 */
263 void resetMatrix();
264
265 /** Modify the current clip with the specified rectangle.
266 @param rect The rect to intersect with the current clip
267 @param op The region op to apply to the current clip
268 @return true if the canvas' clip is non-empty
269 */
270 virtual bool clipRect(const SkRect& rect,
271 SkRegion::Op op = SkRegion::kIntersect_Op);
272
273 /** Modify the current clip with the specified path.
274 @param path The path to apply to the current clip
275 @param op The region op to apply to the current clip
276 @return true if the canvas' new clip is non-empty
277 */
278 virtual bool clipPath(const SkPath& path,
279 SkRegion::Op op = SkRegion::kIntersect_Op);
280
281 /** Modify the current clip with the specified region. Note that unlike
282 clipRect() and clipPath() which transform their arguments by the current
283 matrix, clipRegion() assumes its argument is already in device
284 coordinates, and so no transformation is performed.
285 @param deviceRgn The region to apply to the current clip
286 @param op The region op to apply to the current clip
287 @return true if the canvas' new clip is non-empty
288 */
289 virtual bool clipRegion(const SkRegion& deviceRgn,
290 SkRegion::Op op = SkRegion::kIntersect_Op);
291
292 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
293 specified region. This does not intersect or in any other way account
294 for the existing clip region.
295 @param deviceRgn The region to copy into the current clip.
296 @return true if the new clip region is non-empty
297 */
298 bool setClipRegion(const SkRegion& deviceRgn) {
299 return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
300 }
301
302 /** Enum describing how to treat edges when performing quick-reject tests
303 of a geometry against the current clip. Treating them as antialiased
304 (kAA_EdgeType) will take into account the extra pixels that may be drawn
305 if the edge does not lie exactly on a device pixel boundary (after being
306 transformed by the current matrix).
307 */
308 enum EdgeType {
309 /** Treat the edges as B&W (not antialiased) for the purposes of testing
310 against the current clip
311 */
312 kBW_EdgeType,
313 /** Treat the edges as antialiased for the purposes of testing
314 against the current clip
315 */
316 kAA_EdgeType
317 };
318
319 /** Return true if the specified rectangle, after being transformed by the
320 current matrix, would lie completely outside of the current clip. Call
321 this to check if an area you intend to draw into is clipped out (and
322 therefore you can skip making the draw calls).
323 @param rect the rect to compare with the current clip
324 @param et specifies how to treat the edges (see EdgeType)
325 @return true if the rect (transformed by the canvas' matrix) does not
326 intersect with the canvas' clip
327 */
328 bool quickReject(const SkRect& rect, EdgeType et) const;
329
330 /** Return true if the specified path, after being transformed by the
331 current matrix, would lie completely outside of the current clip. Call
332 this to check if an area you intend to draw into is clipped out (and
333 therefore you can skip making the draw calls). Note, for speed it may
334 return false even if the path itself might not intersect the clip
335 (i.e. the bounds of the path intersects, but the path does not).
336 @param path The path to compare with the current clip
337 @param et specifies how to treat the edges (see EdgeType)
338 @return true if the path (transformed by the canvas' matrix) does not
339 intersect with the canvas' clip
340 */
341 bool quickReject(const SkPath& path, EdgeType et) const;
342
343 /** Return true if the horizontal band specified by top and bottom is
344 completely clipped out. This is a conservative calculation, meaning
345 that it is possible that if the method returns false, the band may still
346 in fact be clipped out, but the converse is not true. If this method
347 returns true, then the band is guaranteed to be clipped out.
348 @param top The top of the horizontal band to compare with the clip
349 @param bottom The bottom of the horizontal and to compare with the clip
350 @return true if the horizontal band is completely clipped out (i.e. does
351 not intersect the current clip)
352 */
353 bool quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const;
354
355 /** Return the bounds of the current clip (in local coordinates) in the
356 bounds parameter, and return true if it is non-empty. This can be useful
357 in a way similar to quickReject, in that it tells you that drawing
358 outside of these bounds will be clipped out.
359 */
360 bool getClipBounds(SkRect* bounds, EdgeType et = kAA_EdgeType) const;
361
362 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000363 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364 @param a the alpha component (0..255) of the color to fill the canvas
365 @param r the red component (0..255) of the color to fill the canvas
366 @param g the green component (0..255) of the color to fill the canvas
367 @param b the blue component (0..255) of the color to fill the canvas
368 @param mode the mode to apply the color in (defaults to SrcOver)
369 */
370 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000371 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000372
373 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000374 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000375 @param color the color to draw with
376 @param mode the mode to apply the color in (defaults to SrcOver)
377 */
378 void drawColor(SkColor color,
reed@android.com845fdac2009-06-23 03:01:32 +0000379 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000380
381 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
382 specified paint.
383 @param paint The paint used to fill the canvas
384 */
385 virtual void drawPaint(const SkPaint& paint);
386
387 enum PointMode {
388 /** drawPoints draws each point separately */
389 kPoints_PointMode,
390 /** drawPoints draws each pair of points as a line segment */
391 kLines_PointMode,
392 /** drawPoints draws the array of points as a polygon */
393 kPolygon_PointMode
394 };
395
396 /** Draw a series of points, interpreted based on the PointMode mode. For
397 all modes, the count parameter is interpreted as the total number of
398 points. For kLine mode, count/2 line segments are drawn.
399 For kPoint mode, each point is drawn centered at its coordinate, and its
400 size is specified by the paint's stroke-width. It draws as a square,
401 unless the paint's cap-type is round, in which the points are drawn as
402 circles.
403 For kLine mode, each pair of points is drawn as a line segment,
404 respecting the paint's settings for cap/join/width.
405 For kPolygon mode, the entire array is drawn as a series of connected
406 line segments.
407 Note that, while similar, kLine and kPolygon modes draw slightly
408 differently than the equivalent path built with a series of moveto,
409 lineto calls, in that the path will draw all of its contours at once,
410 with no interactions if contours intersect each other (think XOR
411 xfermode). drawPoints always draws each element one at a time.
412 @param mode PointMode specifying how to draw the array of points.
413 @param count The number of points in the array
414 @param pts Array of points to draw
415 @param paint The paint used to draw the points
416 */
417 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
418 const SkPaint& paint);
419
420 /** Helper method for drawing a single point. See drawPoints() for a more
421 details.
422 */
423 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000424
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425 /** Draws a single pixel in the specified color.
426 @param x The X coordinate of which pixel to draw
427 @param y The Y coordiante of which pixel to draw
428 @param color The color to draw
429 */
430 void drawPoint(SkScalar x, SkScalar y, SkColor color);
431
432 /** Draw a line segment with the specified start and stop x,y coordinates,
433 using the specified paint. NOTE: since a line is always "framed", the
434 paint's Style is ignored.
435 @param x0 The x-coordinate of the start point of the line
436 @param y0 The y-coordinate of the start point of the line
437 @param x1 The x-coordinate of the end point of the line
438 @param y1 The y-coordinate of the end point of the line
439 @param paint The paint used to draw the line
440 */
441 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
442 const SkPaint& paint);
443
444 /** Draw the specified rectangle using the specified paint. The rectangle
445 will be filled or stroked based on the Style in the paint.
446 @param rect The rect to be drawn
447 @param paint The paint used to draw the rect
448 */
449 virtual void drawRect(const SkRect& rect, const SkPaint& paint);
450
451 /** Draw the specified rectangle using the specified paint. The rectangle
452 will be filled or framed based on the Style in the paint.
453 @param rect The rect to be drawn
454 @param paint The paint used to draw the rect
455 */
456 void drawIRect(const SkIRect& rect, const SkPaint& paint)
457 {
458 SkRect r;
459 r.set(rect); // promotes the ints to scalars
460 this->drawRect(r, paint);
461 }
reed@google.com4b226022011-01-11 18:32:13 +0000462
reed@android.com8a1c16f2008-12-17 15:59:43 +0000463 /** Draw the specified rectangle using the specified paint. The rectangle
464 will be filled or framed based on the Style in the paint.
465 @param left The left side of the rectangle to be drawn
466 @param top The top side of the rectangle to be drawn
467 @param right The right side of the rectangle to be drawn
468 @param bottom The bottom side of the rectangle to be drawn
469 @param paint The paint used to draw the rect
470 */
471 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
472 SkScalar bottom, const SkPaint& paint);
473
474 /** Draw the specified oval using the specified paint. The oval will be
475 filled or framed based on the Style in the paint.
476 @param oval The rectangle bounds of the oval to be drawn
477 @param paint The paint used to draw the oval
478 */
479 void drawOval(const SkRect& oval, const SkPaint&);
480
481 /** Draw the specified circle using the specified paint. If radius is <= 0,
482 then nothing will be drawn. The circle will be filled
483 or framed based on the Style in the paint.
484 @param cx The x-coordinate of the center of the cirle to be drawn
485 @param cy The y-coordinate of the center of the cirle to be drawn
486 @param radius The radius of the cirle to be drawn
487 @param paint The paint used to draw the circle
488 */
489 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
490 const SkPaint& paint);
491
492 /** Draw the specified arc, which will be scaled to fit inside the
493 specified oval. If the sweep angle is >= 360, then the oval is drawn
494 completely. Note that this differs slightly from SkPath::arcTo, which
495 treats the sweep angle mod 360.
496 @param oval The bounds of oval used to define the shape of the arc
497 @param startAngle Starting angle (in degrees) where the arc begins
498 @param sweepAngle Sweep angle (in degrees) measured clockwise
499 @param useCenter true means include the center of the oval. For filling
500 this will draw a wedge. False means just use the arc.
501 @param paint The paint used to draw the arc
502 */
503 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
504 bool useCenter, const SkPaint& paint);
505
506 /** Draw the specified round-rect using the specified paint. The round-rect
507 will be filled or framed based on the Style in the paint.
508 @param rect The rectangular bounds of the roundRect to be drawn
509 @param rx The x-radius of the oval used to round the corners
510 @param ry The y-radius of the oval used to round the corners
511 @param paint The paint used to draw the roundRect
512 */
513 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
514 const SkPaint& paint);
515
516 /** Draw the specified path using the specified paint. The path will be
517 filled or framed based on the Style in the paint.
518 @param path The path to be drawn
519 @param paint The paint used to draw the path
520 */
521 virtual void drawPath(const SkPath& path, const SkPaint& paint);
522
523 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
524 specified paint, transformed by the current matrix. Note: if the paint
525 contains a maskfilter that generates a mask which extends beyond the
526 bitmap's original width/height, then the bitmap will be drawn as if it
527 were in a Shader with CLAMP mode. Thus the color outside of the original
528 width/height will be the edge color replicated.
529 @param bitmap The bitmap to be drawn
530 @param left The position of the left side of the bitmap being drawn
531 @param top The position of the top side of the bitmap being drawn
532 @param paint The paint used to draw the bitmap, or NULL
533 */
534 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
535 const SkPaint* paint = NULL);
536
537 /** Draw the specified bitmap, with the specified matrix applied (before the
538 canvas' matrix is applied).
539 @param bitmap The bitmap to be drawn
540 @param src Optional: specify the subset of the bitmap to be drawn
541 @param dst The destination rectangle where the scaled/translated
542 image will be drawn
543 @param paint The paint used to draw the bitmap, or NULL
544 */
545 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
546 const SkRect& dst, const SkPaint* paint = NULL);
547
548 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
549 const SkPaint* paint = NULL);
reed@google.com4b226022011-01-11 18:32:13 +0000550
reed@android.com8a1c16f2008-12-17 15:59:43 +0000551 /** Draw the specified bitmap, with its top/left corner at (x,y),
552 NOT transformed by the current matrix. Note: if the paint
553 contains a maskfilter that generates a mask which extends beyond the
554 bitmap's original width/height, then the bitmap will be drawn as if it
555 were in a Shader with CLAMP mode. Thus the color outside of the original
556 width/height will be the edge color replicated.
557 @param bitmap The bitmap to be drawn
558 @param left The position of the left side of the bitmap being drawn
559 @param top The position of the top side of the bitmap being drawn
560 @param paint The paint used to draw the bitmap, or NULL
561 */
562 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
563 const SkPaint* paint = NULL);
564
565 /** Draw the text, with origin at (x,y), using the specified paint.
566 The origin is interpreted based on the Align setting in the paint.
567 @param text The text to be drawn
568 @param byteLength The number of bytes to read from the text parameter
569 @param x The x-coordinate of the origin of the text being drawn
570 @param y The y-coordinate of the origin of the text being drawn
571 @param paint The paint used for the text (e.g. color, size, style)
572 */
573 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
574 SkScalar y, const SkPaint& paint);
575
576 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000577 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000578 @param text The text to be drawn
579 @param byteLength The number of bytes to read from the text parameter
580 @param pos Array of positions, used to position each character
581 @param paint The paint used for the text (e.g. color, size, style)
582 */
583 virtual void drawPosText(const void* text, size_t byteLength,
584 const SkPoint pos[], const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000585
reed@android.com8a1c16f2008-12-17 15:59:43 +0000586 /** Draw the text, with each character/glyph origin specified by the x
587 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000588 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000589 @param text The text to be drawn
590 @param byteLength The number of bytes to read from the text parameter
591 @param xpos Array of x-positions, used to position each character
592 @param constY The shared Y coordinate for all of the positions
593 @param paint The paint used for the text (e.g. color, size, style)
594 */
595 virtual void drawPosTextH(const void* text, size_t byteLength,
596 const SkScalar xpos[], SkScalar constY,
597 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000598
reed@android.com8a1c16f2008-12-17 15:59:43 +0000599 /** Draw the text, with origin at (x,y), using the specified paint, along
600 the specified path. The paint's Align setting determins where along the
601 path to start the text.
602 @param text The text to be drawn
603 @param byteLength The number of bytes to read from the text parameter
604 @param path The path the text should follow for its baseline
605 @param hOffset The distance along the path to add to the text's
606 starting position
607 @param vOffset The distance above(-) or below(+) the path to
608 position the text
609 @param paint The paint used for the text
610 */
611 void drawTextOnPathHV(const void* text, size_t byteLength,
612 const SkPath& path, SkScalar hOffset,
613 SkScalar vOffset, const SkPaint& paint);
614
615 /** Draw the text, with origin at (x,y), using the specified paint, along
616 the specified path. The paint's Align setting determins where along the
617 path to start the text.
618 @param text The text to be drawn
619 @param byteLength The number of bytes to read from the text parameter
620 @param path The path the text should follow for its baseline
621 @param matrix (may be null) Applied to the text before it is
622 mapped onto the path
623 @param paint The paint used for the text
624 */
625 virtual void drawTextOnPath(const void* text, size_t byteLength,
626 const SkPath& path, const SkMatrix* matrix,
627 const SkPaint& paint);
628
629 /** Draw the picture into this canvas. This method effective brackets the
630 playback of the picture's draw calls with save/restore, so the state
631 of this canvas will be unchanged after this call. This contrasts with
632 the more immediate method SkPicture::draw(), which does not bracket
633 the canvas with save/restore, thus the canvas may be left in a changed
634 state after the call.
635 @param picture The recorded drawing commands to playback into this
636 canvas.
637 */
638 virtual void drawPicture(SkPicture& picture);
reed@google.com4b226022011-01-11 18:32:13 +0000639
reed@android.comf76bacf2009-05-13 14:00:33 +0000640 /** Draws the specified shape
641 */
642 virtual void drawShape(SkShape*);
643
reed@android.com8a1c16f2008-12-17 15:59:43 +0000644 enum VertexMode {
645 kTriangles_VertexMode,
646 kTriangleStrip_VertexMode,
647 kTriangleFan_VertexMode
648 };
reed@google.com4b226022011-01-11 18:32:13 +0000649
reed@android.com8a1c16f2008-12-17 15:59:43 +0000650 /** Draw the array of vertices, interpreted as triangles (based on mode).
651 @param vmode How to interpret the array of vertices
652 @param vertexCount The number of points in the vertices array (and
653 corresponding texs and colors arrays if non-null)
654 @param vertices Array of vertices for the mesh
655 @param texs May be null. If not null, specifies the coordinate
656 in texture space for each vertex.
657 @param colors May be null. If not null, specifies a color for each
658 vertex, to be interpolated across the triangle.
659 @param xmode Used if both texs and colors are present. In this
660 case the colors are combined with the texture using mode,
661 before being drawn using the paint. If mode is null, then
reed@android.com845fdac2009-06-23 03:01:32 +0000662 kMultiply_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000663 @param indices If not null, array of indices to reference into the
664 vertex (texs, colors) array.
665 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +0000666 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000667 */
668 virtual void drawVertices(VertexMode vmode, int vertexCount,
669 const SkPoint vertices[], const SkPoint texs[],
670 const SkColor colors[], SkXfermode* xmode,
671 const uint16_t indices[], int indexCount,
672 const SkPaint& paint);
673
reed@android.comcb608442009-12-04 21:32:27 +0000674 /** Send a blob of data to the canvas.
675 For canvases that draw, this call is effectively a no-op, as the data
676 is not parsed, but just ignored. However, this call exists for
677 subclasses like SkPicture's recording canvas, that can store the data
678 and then play it back later (via another call to drawData).
679 */
680 virtual void drawData(const void* data, size_t length);
681
reed@android.com8a1c16f2008-12-17 15:59:43 +0000682 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +0000683
reed@android.com8a1c16f2008-12-17 15:59:43 +0000684 /** Get the current bounder object.
685 The bounder's reference count is unchaged.
686 @return the canva's bounder (or NULL).
687 */
688 SkBounder* getBounder() const { return fBounder; }
689
690 /** Set a new bounder (or NULL).
691 Pass NULL to clear any previous bounder.
692 As a convenience, the parameter passed is also returned.
693 If a previous bounder exists, its reference count is decremented.
694 If bounder is not NULL, its reference count is incremented.
695 @param bounder the new bounder (or NULL) to be installed in the canvas
696 @return the set bounder object
697 */
698 virtual SkBounder* setBounder(SkBounder* bounder);
reed@google.com4b226022011-01-11 18:32:13 +0000699
reed@android.com8a1c16f2008-12-17 15:59:43 +0000700 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +0000701 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000702 @return the canvas' filter (or NULL).
703 */
704 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +0000705
reed@android.com8a1c16f2008-12-17 15:59:43 +0000706 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
707 As a convenience, the parameter is returned. If an existing filter
708 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +0000709 refcnt is incremented. The filter is saved/restored, just like the
710 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000711 @param filter the new filter (or NULL)
712 @return the new filter
713 */
714 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
715
716 //////////////////////////////////////////////////////////////////////////
717
718 /** Return the current matrix on the canvas.
719 This does not account for the translate in any of the devices.
720 @return The current matrix on the canvas.
721 */
722 const SkMatrix& getTotalMatrix() const;
723
724 /** Return the current device clip (concatenation of all clip calls).
725 This does not account for the translate in any of the devices.
726 @return the current device clip (concatenation of all clip calls).
727 */
728 const SkRegion& getTotalClip() const;
729
reed@google.com7d7ca792011-02-23 22:39:18 +0000730 /**
731 * Return the current clipstack. This mirrors the result in getTotalClip()
732 * but is represented as a stack of geometric clips + region-ops.
733 */
734 const SkClipStack& getTotalClipStack() const;
735
reed@android.comf2b98d62010-12-20 18:26:13 +0000736 void setExternalMatrix(const SkMatrix* = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000737
738 ///////////////////////////////////////////////////////////////////////////
739
740 /** After calling saveLayer(), there can be any number of devices that make
741 up the top-most drawing area. LayerIter can be used to iterate through
742 those devices. Note that the iterator is only valid until the next API
743 call made on the canvas. Ownership of all pointers in the iterator stays
744 with the canvas, so none of them should be modified or deleted.
745 */
746 class LayerIter /*: SkNoncopyable*/ {
747 public:
748 /** Initialize iterator with canvas, and set values for 1st device */
749 LayerIter(SkCanvas*, bool skipEmptyClips);
750 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +0000751
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752 /** Return true if the iterator is done */
753 bool done() const { return fDone; }
754 /** Cycle to the next device */
755 void next();
reed@google.com4b226022011-01-11 18:32:13 +0000756
reed@android.com8a1c16f2008-12-17 15:59:43 +0000757 // These reflect the current device in the iterator
758
759 SkDevice* device() const;
760 const SkMatrix& matrix() const;
761 const SkRegion& clip() const;
762 const SkPaint& paint() const;
763 int x() const;
764 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +0000765
reed@android.com8a1c16f2008-12-17 15:59:43 +0000766 private:
767 // used to embed the SkDrawIter object directly in our instance, w/o
768 // having to expose that class def to the public. There is an assert
769 // in our constructor to ensure that fStorage is large enough
770 // (though needs to be a compile-time-assert!). We use intptr_t to work
771 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +0000772 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +0000773 class SkDrawIter* fImpl; // this points at fStorage
774 SkPaint fDefaultPaint;
775 bool fDone;
776 };
777
778protected:
779 // all of the drawBitmap variants call this guy
reed@android.comf2b98d62010-12-20 18:26:13 +0000780 virtual void commonDrawBitmap(const SkBitmap&, const SkIRect*,
781 const SkMatrix&, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000782
reed@android.com8a1c16f2008-12-17 15:59:43 +0000783private:
784 class MCRec;
785
reed@google.com5c3d1472011-02-22 19:12:23 +0000786 SkClipStack fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000787 SkDeque fMCStack;
788 // points to top of stack
789 MCRec* fMCRec;
790 // the first N recs that can fit here mean we won't call malloc
791 uint32_t fMCRecStorage[32];
792
793 SkBounder* fBounder;
reed@android.com199f1082009-06-10 02:12:47 +0000794 SkDevice* fLastDeviceToGainFocus;
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000795 SkDeviceFactory* fDeviceFactory;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000796
reed@android.comf2b98d62010-12-20 18:26:13 +0000797 void prepareForDeviceDraw(SkDevice*, const SkMatrix&, const SkRegion&);
reed@google.com4b226022011-01-11 18:32:13 +0000798
reed@android.com8a1c16f2008-12-17 15:59:43 +0000799 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
800 void updateDeviceCMCache();
801
802 friend class SkDrawIter; // needs setupDrawForLayerDevice()
803
804 SkDevice* init(SkDevice*);
reed@android.comf2b98d62010-12-20 18:26:13 +0000805 void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000806 const SkPaint* paint);
807 void drawDevice(SkDevice*, int x, int y, const SkPaint*);
808 // shared by save() and saveLayer()
809 int internalSave(SaveFlags flags);
810 void internalRestore();
reed@google.com4b226022011-01-11 18:32:13 +0000811
reed@android.com8a1c16f2008-12-17 15:59:43 +0000812 /* These maintain a cache of the clip bounds in local coordinates,
813 (converted to 2s-compliment if floats are slow).
814 */
815 mutable SkRectCompareType fLocalBoundsCompareType;
816 mutable bool fLocalBoundsCompareTypeDirty;
817
reed@android.comba09de42010-02-05 20:46:05 +0000818 mutable SkRectCompareType fLocalBoundsCompareTypeBW;
819 mutable bool fLocalBoundsCompareTypeDirtyBW;
820
821 /* Get the local clip bounds with an anti-aliased edge.
822 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000823 const SkRectCompareType& getLocalClipBoundsCompareType() const {
reed@android.comba09de42010-02-05 20:46:05 +0000824 return getLocalClipBoundsCompareType(kAA_EdgeType);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000825 }
reed@android.comba09de42010-02-05 20:46:05 +0000826
827 const SkRectCompareType& getLocalClipBoundsCompareType(EdgeType et) const {
828 if (et == kAA_EdgeType) {
829 if (fLocalBoundsCompareTypeDirty) {
830 this->computeLocalClipBoundsCompareType(et);
831 fLocalBoundsCompareTypeDirty = false;
832 }
833 return fLocalBoundsCompareType;
834 } else {
835 if (fLocalBoundsCompareTypeDirtyBW) {
836 this->computeLocalClipBoundsCompareType(et);
837 fLocalBoundsCompareTypeDirtyBW = false;
838 }
839 return fLocalBoundsCompareTypeBW;
840 }
841 }
842 void computeLocalClipBoundsCompareType(EdgeType et) const;
reed@android.comf2b98d62010-12-20 18:26:13 +0000843
844 SkMatrix fExternalMatrix, fExternalInverse;
845 bool fUseExternalMatrix;
reed@google.com5c3d1472011-02-22 19:12:23 +0000846
847 class AutoValidateClip : ::SkNoncopyable {
848 public:
849 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
850 fCanvas->validateClip();
851 }
852 ~AutoValidateClip() { fCanvas->validateClip(); }
853
854 private:
855 const SkCanvas* fCanvas;
856 };
857
858#ifdef SK_DEBUG
859 void validateClip() const;
860#else
861 void validateClip() const {}
862#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000863};
864
865/** Stack helper class to automatically call restoreToCount() on the canvas
866 when this object goes out of scope. Use this to guarantee that the canvas
867 is restored to a known state.
868*/
869class SkAutoCanvasRestore : SkNoncopyable {
870public:
871 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
872 SkASSERT(canvas);
873 fSaveCount = canvas->getSaveCount();
874 if (doSave) {
875 canvas->save();
876 }
877 }
878 ~SkAutoCanvasRestore() {
879 fCanvas->restoreToCount(fSaveCount);
880 }
881
882private:
883 SkCanvas* fCanvas;
884 int fSaveCount;
885};
886
887#endif
888