blob: 160b8fb769d91b05ce931b9277c2a30fb792ad0d [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkCanvas_DEFINED
11#define SkCanvas_DEFINED
12
13#include "SkTypes.h"
14#include "SkBitmap.h"
15#include "SkDeque.h"
reed@google.com5c3d1472011-02-22 19:12:23 +000016#include "SkClipStack.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#include "SkPaint.h"
18#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000019#include "SkPath.h"
20#include "SkRegion.h"
21#include "SkScalarCompare.h"
reed@android.com845fdac2009-06-23 03:01:32 +000022#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000023
24class SkBounder;
25class SkDevice;
26class SkDraw;
27class SkDrawFilter;
28class SkPicture;
29
30/** \class SkCanvas
31
32 A Canvas encapsulates all of the state about drawing into a device (bitmap).
33 This includes a reference to the device itself, and a stack of matrix/clip
34 values. For any given draw call (e.g. drawRect), the geometry of the object
35 being drawn is transformed by the concatenation of all the matrices in the
36 stack. The transformed geometry is clipped by the intersection of all of
37 the clips in the stack.
38
39 While the Canvas holds the state of the drawing device, the state (style)
40 of the object being drawn is held by the Paint, which is provided as a
41 parameter to each of the draw() methods. The Paint holds attributes such as
42 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
43 etc.
44*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000045class SK_API SkCanvas : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000046public:
reed@google.comcde92112011-07-06 20:00:52 +000047 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000048
reed@google.com6dc74552011-07-21 18:00:46 +000049 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +000050
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000051 @param device Specifies a device for the canvas to draw into.
52 */
53 explicit SkCanvas(SkDevice* device);
54
55 /** Deprecated - Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +000056 @param bitmap Specifies a bitmap for the canvas to draw into. Its
57 structure are copied to the canvas.
58 */
59 explicit SkCanvas(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +000060 virtual ~SkCanvas();
61
62 ///////////////////////////////////////////////////////////////////////////
63
reed@android.com8a1c16f2008-12-17 15:59:43 +000064 /** Return the canvas' device object, which may be null. The device holds
65 the bitmap of the pixels that the canvas draws into. The reference count
66 of the returned device is not changed by this call.
67 */
68 SkDevice* getDevice() const;
69
70 /** Specify a device for this canvas to draw into. If it is not null, its
71 reference count is incremented. If the canvas was already holding a
72 device, its reference count is decremented. The new device is returned.
73 */
74 SkDevice* setDevice(SkDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000075
reed@google.com9266fed2011-03-30 00:18:03 +000076 /**
77 * saveLayer() can create another device (which is later drawn onto
78 * the previous device). getTopDevice() returns the top-most device current
79 * installed. Note that this can change on other calls like save/restore,
80 * so do not access this device after subsequent canvas calls.
81 * The reference count of the device is not changed.
82 */
83 SkDevice* getTopDevice() const;
84
reed@android.comf2b98d62010-12-20 18:26:13 +000085 /**
86 * Create a new raster device and make it current. This also returns
87 * the new device.
88 */
reed@google.comaf951c92011-06-16 19:10:39 +000089 SkDevice* setBitmapDevice(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +000090
reed@google.com51df9e32010-12-23 19:29:18 +000091 /**
reed@google.comcde92112011-07-06 20:00:52 +000092 * Shortcut for getDevice()->createCompatibleDevice(...).
93 * If getDevice() == NULL, this method does nothing, and returns NULL.
bsalomon@google.come97f0852011-06-17 13:10:25 +000094 */
95 SkDevice* createCompatibleDevice(SkBitmap::Config config,
96 int width, int height,
97 bool isOpaque);
98
reed@google.com4b226022011-01-11 18:32:13 +000099 ///////////////////////////////////////////////////////////////////////////
100
101 /**
reed@google.com51df9e32010-12-23 19:29:18 +0000102 * Copy the pixels from the device into bitmap. Returns true on success.
103 * If false is returned, then the bitmap parameter is left unchanged.
reed@google.com3dd42b32011-02-07 22:44:43 +0000104 * The bitmap parameter is treated as output-only, and will be completely
105 * overwritten (if the method returns true).
reed@google.com51df9e32010-12-23 19:29:18 +0000106 */
107 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
108 bool readPixels(SkBitmap* bitmap);
109
110 /**
111 * Similar to draw sprite, this method will copy the pixels in bitmap onto
112 * the device, with the top/left corner specified by (x, y). The pixel
113 * values in the device are completely replaced: there is no blending.
epoger@google.com4f1151a2011-07-25 15:47:33 +0000114 *
115 * Note: If you are recording drawing commands on this canvas to
116 * SkPicture, writePixels() is ignored!
reed@google.com51df9e32010-12-23 19:29:18 +0000117 */
118 void writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000119
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000121
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 enum SaveFlags {
123 /** save the matrix state, restoring it on restore() */
124 kMatrix_SaveFlag = 0x01,
125 /** save the clip state, restoring it on restore() */
126 kClip_SaveFlag = 0x02,
127 /** the layer needs to support per-pixel alpha */
128 kHasAlphaLayer_SaveFlag = 0x04,
129 /** the layer needs to support 8-bits per color component */
130 kFullColorLayer_SaveFlag = 0x08,
131 /** the layer should clip against the bounds argument */
132 kClipToLayer_SaveFlag = 0x10,
133
134 // helper masks for common choices
135 kMatrixClip_SaveFlag = 0x03,
136 kARGB_NoClipLayer_SaveFlag = 0x0F,
137 kARGB_ClipLayer_SaveFlag = 0x1F
138 };
139
reed@android.comdc3381f2010-02-11 16:05:15 +0000140 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000142 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
143 operate on this copy.
144 When the balancing call to restore() is made, the previous matrix, clip,
145 and drawFilter are restored.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146 @return The value to pass to restoreToCount() to balance this save()
147 */
148 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
149
150 /** This behaves the same as save(), but in addition it allocates an
151 offscreen bitmap. All drawing calls are directed there, and only when
152 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000153 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000154 @param bounds (may be null) This rect, if non-null, is used as a hint to
155 limit the size of the offscreen, and thus drawing may be
156 clipped to it, though that clipping is not guaranteed to
157 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158 @param paint (may be null) This is copied, and is applied to the
159 offscreen when restore() is called
160 @param flags LayerFlags
161 @return The value to pass to restoreToCount() to balance this save()
162 */
163 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
164 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
165
166 /** This behaves the same as save(), but in addition it allocates an
167 offscreen bitmap. All drawing calls are directed there, and only when
168 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000169 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000170 @param bounds (may be null) This rect, if non-null, is used as a hint to
171 limit the size of the offscreen, and thus drawing may be
172 clipped to it, though that clipping is not guaranteed to
173 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 @param alpha This is applied to the offscreen when restore() is called.
175 @param flags LayerFlags
176 @return The value to pass to restoreToCount() to balance this save()
177 */
178 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
179 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
180
181 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000182 modifications to the matrix/clip/drawFilter state since the last save
183 call.
184 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185 */
186 virtual void restore();
187
188 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
189 This will equal # save() calls - # restore() calls.
190 */
191 int getSaveCount() const;
192
193 /** Efficient way to pop any calls to save() that happened after the save
194 count reached saveCount. It is an error for saveCount to be less than
195 getSaveCount()
196 @param saveCount The number of save() levels to restore from
197 */
198 void restoreToCount(int saveCount);
199
200 /** Preconcat the current matrix with the specified translation
201 @param dx The distance to translate in X
202 @param dy The distance to translate in Y
203 returns true if the operation succeeded (e.g. did not overflow)
204 */
205 virtual bool translate(SkScalar dx, SkScalar dy);
206
207 /** Preconcat the current matrix with the specified scale.
208 @param sx The amount to scale in X
209 @param sy The amount to scale in Y
210 returns true if the operation succeeded (e.g. did not overflow)
211 */
212 virtual bool scale(SkScalar sx, SkScalar sy);
213
214 /** Preconcat the current matrix with the specified rotation.
215 @param degrees The amount to rotate, in degrees
216 returns true if the operation succeeded (e.g. did not overflow)
217 */
218 virtual bool rotate(SkScalar degrees);
219
220 /** Preconcat the current matrix with the specified skew.
221 @param sx The amount to skew in X
222 @param sy The amount to skew in Y
223 returns true if the operation succeeded (e.g. did not overflow)
224 */
225 virtual bool skew(SkScalar sx, SkScalar sy);
226
227 /** Preconcat the current matrix with the specified matrix.
228 @param matrix The matrix to preconcatenate with the current matrix
229 @return true if the operation succeeded (e.g. did not overflow)
230 */
231 virtual bool concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000232
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233 /** Replace the current matrix with a copy of the specified matrix.
234 @param matrix The matrix that will be copied into the current matrix.
235 */
236 virtual void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000237
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238 /** Helper for setMatrix(identity). Sets the current matrix to identity.
239 */
240 void resetMatrix();
241
242 /** Modify the current clip with the specified rectangle.
243 @param rect The rect to intersect with the current clip
244 @param op The region op to apply to the current clip
245 @return true if the canvas' clip is non-empty
246 */
247 virtual bool clipRect(const SkRect& rect,
reed@google.com071eef92011-10-12 11:52:53 +0000248 SkRegion::Op op = SkRegion::kIntersect_Op,
249 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250
251 /** Modify the current clip with the specified path.
252 @param path The path to apply to the current clip
253 @param op The region op to apply to the current clip
254 @return true if the canvas' new clip is non-empty
255 */
256 virtual bool clipPath(const SkPath& path,
reed@google.com071eef92011-10-12 11:52:53 +0000257 SkRegion::Op op = SkRegion::kIntersect_Op,
258 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259
260 /** Modify the current clip with the specified region. Note that unlike
261 clipRect() and clipPath() which transform their arguments by the current
262 matrix, clipRegion() assumes its argument is already in device
263 coordinates, and so no transformation is performed.
264 @param deviceRgn The region to apply to the current clip
265 @param op The region op to apply to the current clip
266 @return true if the canvas' new clip is non-empty
267 */
268 virtual bool clipRegion(const SkRegion& deviceRgn,
269 SkRegion::Op op = SkRegion::kIntersect_Op);
270
271 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
272 specified region. This does not intersect or in any other way account
273 for the existing clip region.
274 @param deviceRgn The region to copy into the current clip.
275 @return true if the new clip region is non-empty
276 */
277 bool setClipRegion(const SkRegion& deviceRgn) {
278 return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
279 }
280
281 /** Enum describing how to treat edges when performing quick-reject tests
282 of a geometry against the current clip. Treating them as antialiased
283 (kAA_EdgeType) will take into account the extra pixels that may be drawn
284 if the edge does not lie exactly on a device pixel boundary (after being
285 transformed by the current matrix).
286 */
287 enum EdgeType {
288 /** Treat the edges as B&W (not antialiased) for the purposes of testing
289 against the current clip
290 */
291 kBW_EdgeType,
292 /** Treat the edges as antialiased for the purposes of testing
293 against the current clip
294 */
295 kAA_EdgeType
296 };
297
298 /** Return true if the specified rectangle, after being transformed by the
299 current matrix, would lie completely outside of the current clip. Call
300 this to check if an area you intend to draw into is clipped out (and
301 therefore you can skip making the draw calls).
302 @param rect the rect to compare with the current clip
303 @param et specifies how to treat the edges (see EdgeType)
304 @return true if the rect (transformed by the canvas' matrix) does not
305 intersect with the canvas' clip
306 */
307 bool quickReject(const SkRect& rect, EdgeType et) const;
308
309 /** Return true if the specified path, after being transformed by the
310 current matrix, would lie completely outside of the current clip. Call
311 this to check if an area you intend to draw into is clipped out (and
312 therefore you can skip making the draw calls). Note, for speed it may
313 return false even if the path itself might not intersect the clip
314 (i.e. the bounds of the path intersects, but the path does not).
315 @param path The path to compare with the current clip
316 @param et specifies how to treat the edges (see EdgeType)
317 @return true if the path (transformed by the canvas' matrix) does not
318 intersect with the canvas' clip
319 */
320 bool quickReject(const SkPath& path, EdgeType et) const;
321
322 /** Return true if the horizontal band specified by top and bottom is
323 completely clipped out. This is a conservative calculation, meaning
324 that it is possible that if the method returns false, the band may still
325 in fact be clipped out, but the converse is not true. If this method
326 returns true, then the band is guaranteed to be clipped out.
327 @param top The top of the horizontal band to compare with the clip
328 @param bottom The bottom of the horizontal and to compare with the clip
329 @return true if the horizontal band is completely clipped out (i.e. does
330 not intersect the current clip)
331 */
332 bool quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const;
333
334 /** Return the bounds of the current clip (in local coordinates) in the
335 bounds parameter, and return true if it is non-empty. This can be useful
336 in a way similar to quickReject, in that it tells you that drawing
337 outside of these bounds will be clipped out.
338 */
339 bool getClipBounds(SkRect* bounds, EdgeType et = kAA_EdgeType) const;
340
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000341 /** Return the bounds of the current clip, in device coordinates; returns
342 true if non-empty. Maybe faster than getting the clip explicitly and
343 then taking its bounds.
344 */
345 bool getClipDeviceBounds(SkIRect* bounds) const;
346
347
reed@android.com8a1c16f2008-12-17 15:59:43 +0000348 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000349 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 @param a the alpha component (0..255) of the color to fill the canvas
351 @param r the red component (0..255) of the color to fill the canvas
352 @param g the green component (0..255) of the color to fill the canvas
353 @param b the blue component (0..255) of the color to fill the canvas
354 @param mode the mode to apply the color in (defaults to SrcOver)
355 */
356 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000357 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358
359 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000360 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000361 @param color the color to draw with
362 @param mode the mode to apply the color in (defaults to SrcOver)
363 */
364 void drawColor(SkColor color,
reed@android.com845fdac2009-06-23 03:01:32 +0000365 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000366
reed@google.com2a981812011-04-14 18:59:28 +0000367 /**
368 * This erases the entire drawing surface to the specified color,
369 * irrespective of the clip. It does not blend with the previous pixels,
370 * but always overwrites them.
371 *
372 * It is roughly equivalent to the following:
373 * canvas.save();
374 * canvas.clipRect(hugeRect, kReplace_Op);
375 * paint.setColor(color);
376 * paint.setXfermodeMode(kSrc_Mode);
377 * canvas.drawPaint(paint);
378 * canvas.restore();
379 * though it is almost always much more efficient.
380 */
381 virtual void clear(SkColor);
382
383 /**
384 * Fill the entire canvas' bitmap (restricted to the current clip) with the
385 * specified paint.
386 * @param paint The paint used to fill the canvas
387 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000388 virtual void drawPaint(const SkPaint& paint);
389
390 enum PointMode {
391 /** drawPoints draws each point separately */
392 kPoints_PointMode,
393 /** drawPoints draws each pair of points as a line segment */
394 kLines_PointMode,
395 /** drawPoints draws the array of points as a polygon */
396 kPolygon_PointMode
397 };
398
399 /** Draw a series of points, interpreted based on the PointMode mode. For
400 all modes, the count parameter is interpreted as the total number of
401 points. For kLine mode, count/2 line segments are drawn.
402 For kPoint mode, each point is drawn centered at its coordinate, and its
403 size is specified by the paint's stroke-width. It draws as a square,
404 unless the paint's cap-type is round, in which the points are drawn as
405 circles.
406 For kLine mode, each pair of points is drawn as a line segment,
407 respecting the paint's settings for cap/join/width.
408 For kPolygon mode, the entire array is drawn as a series of connected
409 line segments.
410 Note that, while similar, kLine and kPolygon modes draw slightly
411 differently than the equivalent path built with a series of moveto,
412 lineto calls, in that the path will draw all of its contours at once,
413 with no interactions if contours intersect each other (think XOR
414 xfermode). drawPoints always draws each element one at a time.
415 @param mode PointMode specifying how to draw the array of points.
416 @param count The number of points in the array
417 @param pts Array of points to draw
418 @param paint The paint used to draw the points
419 */
420 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
421 const SkPaint& paint);
422
423 /** Helper method for drawing a single point. See drawPoints() for a more
424 details.
425 */
426 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000427
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428 /** Draws a single pixel in the specified color.
429 @param x The X coordinate of which pixel to draw
430 @param y The Y coordiante of which pixel to draw
431 @param color The color to draw
432 */
433 void drawPoint(SkScalar x, SkScalar y, SkColor color);
434
435 /** Draw a line segment with the specified start and stop x,y coordinates,
436 using the specified paint. NOTE: since a line is always "framed", the
437 paint's Style is ignored.
438 @param x0 The x-coordinate of the start point of the line
439 @param y0 The y-coordinate of the start point of the line
440 @param x1 The x-coordinate of the end point of the line
441 @param y1 The y-coordinate of the end point of the line
442 @param paint The paint used to draw the line
443 */
444 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
445 const SkPaint& paint);
446
447 /** Draw the specified rectangle using the specified paint. The rectangle
448 will be filled or stroked based on the Style in the paint.
449 @param rect The rect to be drawn
450 @param paint The paint used to draw the rect
451 */
452 virtual void drawRect(const SkRect& rect, const SkPaint& paint);
453
454 /** Draw the specified rectangle using the specified paint. The rectangle
455 will be filled or framed based on the Style in the paint.
456 @param rect The rect to be drawn
457 @param paint The paint used to draw the rect
458 */
459 void drawIRect(const SkIRect& rect, const SkPaint& paint)
460 {
461 SkRect r;
462 r.set(rect); // promotes the ints to scalars
463 this->drawRect(r, paint);
464 }
reed@google.com4b226022011-01-11 18:32:13 +0000465
reed@android.com8a1c16f2008-12-17 15:59:43 +0000466 /** Draw the specified rectangle using the specified paint. The rectangle
467 will be filled or framed based on the Style in the paint.
468 @param left The left side of the rectangle to be drawn
469 @param top The top side of the rectangle to be drawn
470 @param right The right side of the rectangle to be drawn
471 @param bottom The bottom side of the rectangle to be drawn
472 @param paint The paint used to draw the rect
473 */
474 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
475 SkScalar bottom, const SkPaint& paint);
476
477 /** Draw the specified oval using the specified paint. The oval will be
478 filled or framed based on the Style in the paint.
479 @param oval The rectangle bounds of the oval to be drawn
480 @param paint The paint used to draw the oval
481 */
482 void drawOval(const SkRect& oval, const SkPaint&);
483
484 /** Draw the specified circle using the specified paint. If radius is <= 0,
485 then nothing will be drawn. The circle will be filled
486 or framed based on the Style in the paint.
487 @param cx The x-coordinate of the center of the cirle to be drawn
488 @param cy The y-coordinate of the center of the cirle to be drawn
489 @param radius The radius of the cirle to be drawn
490 @param paint The paint used to draw the circle
491 */
492 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
493 const SkPaint& paint);
494
495 /** Draw the specified arc, which will be scaled to fit inside the
496 specified oval. If the sweep angle is >= 360, then the oval is drawn
497 completely. Note that this differs slightly from SkPath::arcTo, which
498 treats the sweep angle mod 360.
499 @param oval The bounds of oval used to define the shape of the arc
500 @param startAngle Starting angle (in degrees) where the arc begins
501 @param sweepAngle Sweep angle (in degrees) measured clockwise
502 @param useCenter true means include the center of the oval. For filling
503 this will draw a wedge. False means just use the arc.
504 @param paint The paint used to draw the arc
505 */
506 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
507 bool useCenter, const SkPaint& paint);
508
509 /** Draw the specified round-rect using the specified paint. The round-rect
510 will be filled or framed based on the Style in the paint.
511 @param rect The rectangular bounds of the roundRect to be drawn
512 @param rx The x-radius of the oval used to round the corners
513 @param ry The y-radius of the oval used to round the corners
514 @param paint The paint used to draw the roundRect
515 */
516 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
517 const SkPaint& paint);
518
519 /** Draw the specified path using the specified paint. The path will be
520 filled or framed based on the Style in the paint.
521 @param path The path to be drawn
522 @param paint The paint used to draw the path
523 */
524 virtual void drawPath(const SkPath& path, const SkPaint& paint);
525
526 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
527 specified paint, transformed by the current matrix. Note: if the paint
528 contains a maskfilter that generates a mask which extends beyond the
529 bitmap's original width/height, then the bitmap will be drawn as if it
530 were in a Shader with CLAMP mode. Thus the color outside of the original
531 width/height will be the edge color replicated.
532 @param bitmap The bitmap to be drawn
533 @param left The position of the left side of the bitmap being drawn
534 @param top The position of the top side of the bitmap being drawn
535 @param paint The paint used to draw the bitmap, or NULL
536 */
537 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
538 const SkPaint* paint = NULL);
539
540 /** Draw the specified bitmap, with the specified matrix applied (before the
541 canvas' matrix is applied).
542 @param bitmap The bitmap to be drawn
543 @param src Optional: specify the subset of the bitmap to be drawn
544 @param dst The destination rectangle where the scaled/translated
545 image will be drawn
546 @param paint The paint used to draw the bitmap, or NULL
547 */
548 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
549 const SkRect& dst, const SkPaint* paint = NULL);
550
551 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
552 const SkPaint* paint = NULL);
reed@google.com4b226022011-01-11 18:32:13 +0000553
reed@google.comf0b5e112011-09-07 11:57:34 +0000554 /**
555 * Draw the bitmap stretched differentially to fit into dst.
556 * center is a rect within the bitmap, and logically divides the bitmap
557 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
558 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
559 *
560 * If the dst is >= the bitmap size, then...
561 * - The 4 corners are not stretch at all.
562 * - The sides are stretch in only one axis.
563 * - The center is stretch in both axes.
564 * Else, for each axis where dst < bitmap,
565 * - The corners shrink proportionally
566 * - The sides (along the shrink axis) and center are not drawn
567 */
568 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
569 const SkRect& dst, const SkPaint* paint = NULL);
570
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571 /** Draw the specified bitmap, with its top/left corner at (x,y),
572 NOT transformed by the current matrix. Note: if the paint
573 contains a maskfilter that generates a mask which extends beyond the
574 bitmap's original width/height, then the bitmap will be drawn as if it
575 were in a Shader with CLAMP mode. Thus the color outside of the original
576 width/height will be the edge color replicated.
577 @param bitmap The bitmap to be drawn
578 @param left The position of the left side of the bitmap being drawn
579 @param top The position of the top side of the bitmap being drawn
580 @param paint The paint used to draw the bitmap, or NULL
581 */
582 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
583 const SkPaint* paint = NULL);
584
585 /** Draw the text, with origin at (x,y), using the specified paint.
586 The origin is interpreted based on the Align setting in the paint.
587 @param text The text to be drawn
588 @param byteLength The number of bytes to read from the text parameter
589 @param x The x-coordinate of the origin of the text being drawn
590 @param y The y-coordinate of the origin of the text being drawn
591 @param paint The paint used for the text (e.g. color, size, style)
592 */
593 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
594 SkScalar y, const SkPaint& paint);
595
596 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000597 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000598 @param text The text to be drawn
599 @param byteLength The number of bytes to read from the text parameter
600 @param pos Array of positions, used to position each character
601 @param paint The paint used for the text (e.g. color, size, style)
602 */
603 virtual void drawPosText(const void* text, size_t byteLength,
604 const SkPoint pos[], const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000605
reed@android.com8a1c16f2008-12-17 15:59:43 +0000606 /** Draw the text, with each character/glyph origin specified by the x
607 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000608 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000609 @param text The text to be drawn
610 @param byteLength The number of bytes to read from the text parameter
611 @param xpos Array of x-positions, used to position each character
612 @param constY The shared Y coordinate for all of the positions
613 @param paint The paint used for the text (e.g. color, size, style)
614 */
615 virtual void drawPosTextH(const void* text, size_t byteLength,
616 const SkScalar xpos[], SkScalar constY,
617 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000618
reed@android.com8a1c16f2008-12-17 15:59:43 +0000619 /** Draw the text, with origin at (x,y), using the specified paint, along
620 the specified path. The paint's Align setting determins where along the
621 path to start the text.
622 @param text The text to be drawn
623 @param byteLength The number of bytes to read from the text parameter
624 @param path The path the text should follow for its baseline
625 @param hOffset The distance along the path to add to the text's
626 starting position
627 @param vOffset The distance above(-) or below(+) the path to
628 position the text
629 @param paint The paint used for the text
630 */
631 void drawTextOnPathHV(const void* text, size_t byteLength,
632 const SkPath& path, SkScalar hOffset,
633 SkScalar vOffset, const SkPaint& paint);
634
635 /** Draw the text, with origin at (x,y), using the specified paint, along
636 the specified path. The paint's Align setting determins where along the
637 path to start the text.
638 @param text The text to be drawn
639 @param byteLength The number of bytes to read from the text parameter
640 @param path The path the text should follow for its baseline
641 @param matrix (may be null) Applied to the text before it is
642 mapped onto the path
643 @param paint The paint used for the text
644 */
645 virtual void drawTextOnPath(const void* text, size_t byteLength,
646 const SkPath& path, const SkMatrix* matrix,
647 const SkPaint& paint);
648
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000649#ifdef ANDROID
650 /** Draw the text on path, with each character/glyph origin specified by the pos[]
651 array. The origin is interpreted by the Align setting in the paint.
652 @param text The text to be drawn
653 @param byteLength The number of bytes to read from the text parameter
654 @param pos Array of positions, used to position each character
655 @param paint The paint used for the text (e.g. color, size, style)
656 @param path The path to draw on
657 @param matrix The canvas matrix
658 */
659 void drawPosTextOnPath(const void* text, size_t byteLength,
660 const SkPoint pos[], const SkPaint& paint,
661 const SkPath& path, const SkMatrix* matrix);
662#endif
663
reed@android.com8a1c16f2008-12-17 15:59:43 +0000664 /** Draw the picture into this canvas. This method effective brackets the
665 playback of the picture's draw calls with save/restore, so the state
666 of this canvas will be unchanged after this call. This contrasts with
667 the more immediate method SkPicture::draw(), which does not bracket
668 the canvas with save/restore, thus the canvas may be left in a changed
669 state after the call.
670 @param picture The recorded drawing commands to playback into this
671 canvas.
672 */
673 virtual void drawPicture(SkPicture& picture);
reed@google.com4b226022011-01-11 18:32:13 +0000674
reed@android.com8a1c16f2008-12-17 15:59:43 +0000675 enum VertexMode {
676 kTriangles_VertexMode,
677 kTriangleStrip_VertexMode,
678 kTriangleFan_VertexMode
679 };
reed@google.com4b226022011-01-11 18:32:13 +0000680
reed@android.com8a1c16f2008-12-17 15:59:43 +0000681 /** Draw the array of vertices, interpreted as triangles (based on mode).
682 @param vmode How to interpret the array of vertices
683 @param vertexCount The number of points in the vertices array (and
684 corresponding texs and colors arrays if non-null)
685 @param vertices Array of vertices for the mesh
686 @param texs May be null. If not null, specifies the coordinate
687 in texture space for each vertex.
688 @param colors May be null. If not null, specifies a color for each
689 vertex, to be interpolated across the triangle.
690 @param xmode Used if both texs and colors are present. In this
691 case the colors are combined with the texture using mode,
692 before being drawn using the paint. If mode is null, then
reed@android.com845fdac2009-06-23 03:01:32 +0000693 kMultiply_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000694 @param indices If not null, array of indices to reference into the
695 vertex (texs, colors) array.
696 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +0000697 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000698 */
699 virtual void drawVertices(VertexMode vmode, int vertexCount,
700 const SkPoint vertices[], const SkPoint texs[],
701 const SkColor colors[], SkXfermode* xmode,
702 const uint16_t indices[], int indexCount,
703 const SkPaint& paint);
704
reed@android.comcb608442009-12-04 21:32:27 +0000705 /** Send a blob of data to the canvas.
706 For canvases that draw, this call is effectively a no-op, as the data
707 is not parsed, but just ignored. However, this call exists for
708 subclasses like SkPicture's recording canvas, that can store the data
709 and then play it back later (via another call to drawData).
710 */
711 virtual void drawData(const void* data, size_t length);
712
reed@android.com8a1c16f2008-12-17 15:59:43 +0000713 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +0000714
reed@android.com8a1c16f2008-12-17 15:59:43 +0000715 /** Get the current bounder object.
716 The bounder's reference count is unchaged.
717 @return the canva's bounder (or NULL).
718 */
719 SkBounder* getBounder() const { return fBounder; }
720
721 /** Set a new bounder (or NULL).
722 Pass NULL to clear any previous bounder.
723 As a convenience, the parameter passed is also returned.
724 If a previous bounder exists, its reference count is decremented.
725 If bounder is not NULL, its reference count is incremented.
726 @param bounder the new bounder (or NULL) to be installed in the canvas
727 @return the set bounder object
728 */
729 virtual SkBounder* setBounder(SkBounder* bounder);
reed@google.com4b226022011-01-11 18:32:13 +0000730
reed@android.com8a1c16f2008-12-17 15:59:43 +0000731 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +0000732 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000733 @return the canvas' filter (or NULL).
734 */
735 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +0000736
reed@android.com8a1c16f2008-12-17 15:59:43 +0000737 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
738 As a convenience, the parameter is returned. If an existing filter
739 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +0000740 refcnt is incremented. The filter is saved/restored, just like the
741 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000742 @param filter the new filter (or NULL)
743 @return the new filter
744 */
745 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
746
747 //////////////////////////////////////////////////////////////////////////
748
749 /** Return the current matrix on the canvas.
750 This does not account for the translate in any of the devices.
751 @return The current matrix on the canvas.
752 */
753 const SkMatrix& getTotalMatrix() const;
754
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000755 enum ClipType {
756 kEmpty_ClipType = 0,
757 kRect_ClipType,
758 kComplex_ClipType
759 };
760
761 /** Returns a description of the total clip; may be cheaper than
762 getting the clip and querying it directly.
763 */
764 ClipType getClipType() const;
765
reed@android.com8a1c16f2008-12-17 15:59:43 +0000766 /** Return the current device clip (concatenation of all clip calls).
767 This does not account for the translate in any of the devices.
768 @return the current device clip (concatenation of all clip calls).
769 */
770 const SkRegion& getTotalClip() const;
771
reed@google.com7d7ca792011-02-23 22:39:18 +0000772 /**
reed@google.com5e2457e2011-10-10 21:24:37 +0000773 * Return true if the current clip is non-empty.
774 *
775 * If bounds is not NULL, set it to the bounds of the current clip
776 * in global coordinates.
777 */
778 bool getTotalClipBounds(SkIRect* bounds) const;
779
780 /**
reed@google.com7d7ca792011-02-23 22:39:18 +0000781 * Return the current clipstack. This mirrors the result in getTotalClip()
782 * but is represented as a stack of geometric clips + region-ops.
783 */
784 const SkClipStack& getTotalClipStack() const;
785
reed@android.comf2b98d62010-12-20 18:26:13 +0000786 void setExternalMatrix(const SkMatrix* = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000787
788 ///////////////////////////////////////////////////////////////////////////
789
790 /** After calling saveLayer(), there can be any number of devices that make
791 up the top-most drawing area. LayerIter can be used to iterate through
792 those devices. Note that the iterator is only valid until the next API
793 call made on the canvas. Ownership of all pointers in the iterator stays
794 with the canvas, so none of them should be modified or deleted.
795 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +0000796 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000797 public:
798 /** Initialize iterator with canvas, and set values for 1st device */
799 LayerIter(SkCanvas*, bool skipEmptyClips);
800 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +0000801
reed@android.com8a1c16f2008-12-17 15:59:43 +0000802 /** Return true if the iterator is done */
803 bool done() const { return fDone; }
804 /** Cycle to the next device */
805 void next();
reed@google.com4b226022011-01-11 18:32:13 +0000806
reed@android.com8a1c16f2008-12-17 15:59:43 +0000807 // These reflect the current device in the iterator
808
809 SkDevice* device() const;
810 const SkMatrix& matrix() const;
811 const SkRegion& clip() const;
812 const SkPaint& paint() const;
813 int x() const;
814 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +0000815
reed@android.com8a1c16f2008-12-17 15:59:43 +0000816 private:
817 // used to embed the SkDrawIter object directly in our instance, w/o
818 // having to expose that class def to the public. There is an assert
819 // in our constructor to ensure that fStorage is large enough
820 // (though needs to be a compile-time-assert!). We use intptr_t to work
821 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +0000822 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +0000823 class SkDrawIter* fImpl; // this points at fStorage
824 SkPaint fDefaultPaint;
825 bool fDone;
826 };
827
828protected:
829 // all of the drawBitmap variants call this guy
reed@android.comf2b98d62010-12-20 18:26:13 +0000830 virtual void commonDrawBitmap(const SkBitmap&, const SkIRect*,
831 const SkMatrix&, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000832
reed@android.com8a1c16f2008-12-17 15:59:43 +0000833private:
834 class MCRec;
835
reed@google.com5c3d1472011-02-22 19:12:23 +0000836 SkClipStack fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000837 SkDeque fMCStack;
838 // points to top of stack
839 MCRec* fMCRec;
840 // the first N recs that can fit here mean we won't call malloc
841 uint32_t fMCRecStorage[32];
842
843 SkBounder* fBounder;
reed@android.com199f1082009-06-10 02:12:47 +0000844 SkDevice* fLastDeviceToGainFocus;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000845
bsalomon@google.comd302f142011-03-03 13:54:13 +0000846 void prepareForDeviceDraw(SkDevice*, const SkMatrix&, const SkRegion&,
847 const SkClipStack& clipStack);
reed@google.com4b226022011-01-11 18:32:13 +0000848
reed@android.com8a1c16f2008-12-17 15:59:43 +0000849 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
850 void updateDeviceCMCache();
851
852 friend class SkDrawIter; // needs setupDrawForLayerDevice()
853
bsalomon@google.come97f0852011-06-17 13:10:25 +0000854 SkDevice* createLayerDevice(SkBitmap::Config, int width, int height,
855 bool isOpaque);
856
reed@android.com8a1c16f2008-12-17 15:59:43 +0000857 SkDevice* init(SkDevice*);
reed@google.comf0b5e112011-09-07 11:57:34 +0000858
859 // internal methods are not virtual, so they can safely be called by other
860 // canvas apis, without confusing subclasses (like SkPictureRecording)
reed@android.comf2b98d62010-12-20 18:26:13 +0000861 void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000862 const SkPaint* paint);
reed@google.comf0b5e112011-09-07 11:57:34 +0000863 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
864 const SkRect& dst, const SkPaint* paint);
865 void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
866 const SkRect& dst, const SkPaint* paint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +0000867 void internalDrawPaint(const SkPaint& paint);
868
reed@google.comf0b5e112011-09-07 11:57:34 +0000869
reed@android.com8a1c16f2008-12-17 15:59:43 +0000870 void drawDevice(SkDevice*, int x, int y, const SkPaint*);
871 // shared by save() and saveLayer()
872 int internalSave(SaveFlags flags);
873 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +0000874 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
875 const SkRect& r, SkScalar textSize);
876 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
877 const char text[], size_t byteLength,
878 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +0000879
reed@android.com8a1c16f2008-12-17 15:59:43 +0000880 /* These maintain a cache of the clip bounds in local coordinates,
881 (converted to 2s-compliment if floats are slow).
882 */
883 mutable SkRectCompareType fLocalBoundsCompareType;
884 mutable bool fLocalBoundsCompareTypeDirty;
885
reed@android.comba09de42010-02-05 20:46:05 +0000886 mutable SkRectCompareType fLocalBoundsCompareTypeBW;
887 mutable bool fLocalBoundsCompareTypeDirtyBW;
888
889 /* Get the local clip bounds with an anti-aliased edge.
890 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000891 const SkRectCompareType& getLocalClipBoundsCompareType() const {
reed@android.comba09de42010-02-05 20:46:05 +0000892 return getLocalClipBoundsCompareType(kAA_EdgeType);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000893 }
reed@android.comba09de42010-02-05 20:46:05 +0000894
895 const SkRectCompareType& getLocalClipBoundsCompareType(EdgeType et) const {
896 if (et == kAA_EdgeType) {
897 if (fLocalBoundsCompareTypeDirty) {
898 this->computeLocalClipBoundsCompareType(et);
899 fLocalBoundsCompareTypeDirty = false;
900 }
901 return fLocalBoundsCompareType;
902 } else {
903 if (fLocalBoundsCompareTypeDirtyBW) {
904 this->computeLocalClipBoundsCompareType(et);
905 fLocalBoundsCompareTypeDirtyBW = false;
906 }
907 return fLocalBoundsCompareTypeBW;
908 }
909 }
910 void computeLocalClipBoundsCompareType(EdgeType et) const;
reed@android.comf2b98d62010-12-20 18:26:13 +0000911
912 SkMatrix fExternalMatrix, fExternalInverse;
913 bool fUseExternalMatrix;
reed@google.com5c3d1472011-02-22 19:12:23 +0000914
915 class AutoValidateClip : ::SkNoncopyable {
916 public:
917 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
918 fCanvas->validateClip();
919 }
920 ~AutoValidateClip() { fCanvas->validateClip(); }
921
922 private:
923 const SkCanvas* fCanvas;
924 };
925
926#ifdef SK_DEBUG
927 void validateClip() const;
928#else
929 void validateClip() const {}
930#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000931};
932
933/** Stack helper class to automatically call restoreToCount() on the canvas
934 when this object goes out of scope. Use this to guarantee that the canvas
935 is restored to a known state.
936*/
937class SkAutoCanvasRestore : SkNoncopyable {
938public:
939 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
940 SkASSERT(canvas);
941 fSaveCount = canvas->getSaveCount();
942 if (doSave) {
943 canvas->save();
944 }
945 }
946 ~SkAutoCanvasRestore() {
947 fCanvas->restoreToCount(fSaveCount);
948 }
949
950private:
951 SkCanvas* fCanvas;
952 int fSaveCount;
953};
954
955#endif