blob: 08bd0f027dab3f1151241f9a45857c707df8d5db [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@google.com210ce002011-11-01 14:24:23 +000064 /**
65 * Return the width/height of the underlying device. The current drawable
66 * area may be small (due to clipping or saveLayer). For a canvas with
67 * no device, 0,0 will be returned.
68 */
69 SkISize getDeviceSize() const;
70
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 /** Return the canvas' device object, which may be null. The device holds
72 the bitmap of the pixels that the canvas draws into. The reference count
73 of the returned device is not changed by this call.
74 */
75 SkDevice* getDevice() const;
76
77 /** Specify a device for this canvas to draw into. If it is not null, its
78 reference count is incremented. If the canvas was already holding a
79 device, its reference count is decremented. The new device is returned.
80 */
81 SkDevice* setDevice(SkDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000082
reed@google.com9266fed2011-03-30 00:18:03 +000083 /**
84 * saveLayer() can create another device (which is later drawn onto
85 * the previous device). getTopDevice() returns the top-most device current
86 * installed. Note that this can change on other calls like save/restore,
87 * so do not access this device after subsequent canvas calls.
88 * The reference count of the device is not changed.
89 */
90 SkDevice* getTopDevice() const;
91
reed@android.comf2b98d62010-12-20 18:26:13 +000092 /**
93 * Create a new raster device and make it current. This also returns
94 * the new device.
95 */
reed@google.comaf951c92011-06-16 19:10:39 +000096 SkDevice* setBitmapDevice(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +000097
reed@google.com51df9e32010-12-23 19:29:18 +000098 /**
reed@google.comcde92112011-07-06 20:00:52 +000099 * Shortcut for getDevice()->createCompatibleDevice(...).
100 * If getDevice() == NULL, this method does nothing, and returns NULL.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000101 */
102 SkDevice* createCompatibleDevice(SkBitmap::Config config,
103 int width, int height,
104 bool isOpaque);
105
reed@google.com4b226022011-01-11 18:32:13 +0000106 ///////////////////////////////////////////////////////////////////////////
107
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000108 /**
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000109 * This enum can be used with read/writePixels to perform a pixel ops to or
110 * from an 8888 config other than Skia's native config (SkPMColor). There
111 * are three byte orders supported: native, BGRA, and RGBA. Each has a
112 * premultiplied and unpremultiplied variant.
113 *
114 * Components of a 8888 pixel can be packed/unpacked from a 32bit word using
115 * either byte offsets or shift values. Byte offsets are endian-invariant
116 * while shifts are not. BGRA and RGBA configs are defined by byte
117 * orderings. The native config is defined by shift values (SK_A32_SHIFT,
118 * ..., SK_B32_SHIFT).
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000119 */
120 enum Config8888 {
121 /**
122 * Skia's native order specified by:
123 * SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
124 *
125 * kNative_Premul_Config8888 is equivalent to SkPMColor
126 * kNative_Unpremul_Config8888 has the same component order as SkPMColor
127 * but is not premultiplied.
128 */
129 kNative_Premul_Config8888,
130 kNative_Unpremul_Config8888,
131 /**
132 * low byte to high byte: B, G, R, A.
133 */
134 kBGRA_Premul_Config8888,
135 kBGRA_Unpremul_Config8888,
136 /**
137 * low byte to high byte: R, G, B, A.
138 */
139 kRGBA_Premul_Config8888,
140 kRGBA_Unpremul_Config8888,
141 };
142
143 /**
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000144 * On success (returns true), copy the canvas pixels into the bitmap.
145 * On failure, the bitmap parameter is left unchanged and false is
146 * returned.
147 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000148 * The canvas' pixels are converted to the bitmap's config. The only
149 * supported config is kARGB_8888_Config, though this is likely to be
150 * relaxed in the future. The meaning of config kARGB_8888_Config is
151 * modified by the enum param config8888. The default value interprets
152 * kARGB_8888_Config as SkPMColor
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000153 *
154 * If the bitmap has pixels already allocated, the canvas pixels will be
155 * written there. If not, bitmap->allocPixels() will be called
156 * automatically. If the bitmap is backed by a texture readPixels will
157 * fail.
158 *
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000159 * The actual pixels written is the intersection of the canvas' bounds, and
160 * the rectangle formed by the bitmap's width,height and the specified x,y.
161 * If bitmap pixels extend outside of that intersection, they will not be
162 * modified.
163 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000164 * Other failure conditions:
165 * * If the canvas is backed by a non-raster device (e.g. PDF) then
166 * readPixels will fail.
167 * * If bitmap is texture-backed then readPixels will fail. (This may be
168 * relaxed in the future.)
169 *
170 * Example that reads the entire canvas into a bitmap using the native
171 * SkPMColor:
172 * SkISize size = canvas->getDeviceSize();
173 * bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
174 * size.fHeight);
175 * if (canvas->readPixels(bitmap, 0, 0)) {
176 * // use the pixels
177 * }
bsalomon@google.comc6980972011-11-02 19:57:21 +0000178 */
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000179 bool readPixels(SkBitmap* bitmap,
180 int x, int y,
181 Config8888 config8888 = kNative_Premul_Config8888);
bsalomon@google.comc6980972011-11-02 19:57:21 +0000182
reed@google.com4b226022011-01-11 18:32:13 +0000183 /**
bsalomon@google.comc6980972011-11-02 19:57:21 +0000184 * DEPRECATED: This will be removed as soon as webkit is no longer relying
185 * on it. The bitmap is resized to the intersection of srcRect and the
186 * canvas bounds. New pixels are always allocated on success. Bitmap is
187 * unmodified on failure.
reed@google.com51df9e32010-12-23 19:29:18 +0000188 */
189 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000190
191 /**
192 * Similar to draw sprite, this method will copy the pixels in bitmap onto
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000193 * the canvas, with the top/left corner specified by (x, y). The canvas'
194 * pixel values are completely replaced: there is no blending.
195 *
196 * Currently if bitmap is backed by a texture this is a no-op. This may be
197 * relaxed in the future.
198 *
199 * If the bitmap has config kARGB_8888_Config then the config8888 param
200 * will determines how the pixel valuess are intepreted. If the bitmap is
201 * not kARGB_8888_Config then this parameter is ignored.
epoger@google.com4f1151a2011-07-25 15:47:33 +0000202 *
203 * Note: If you are recording drawing commands on this canvas to
204 * SkPicture, writePixels() is ignored!
reed@google.com51df9e32010-12-23 19:29:18 +0000205 */
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000206 void writePixels(const SkBitmap& bitmap,
207 int x, int y,
208 Config8888 config8888 = kNative_Premul_Config8888);
reed@google.com4b226022011-01-11 18:32:13 +0000209
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000211
reed@android.com8a1c16f2008-12-17 15:59:43 +0000212 enum SaveFlags {
213 /** save the matrix state, restoring it on restore() */
214 kMatrix_SaveFlag = 0x01,
215 /** save the clip state, restoring it on restore() */
216 kClip_SaveFlag = 0x02,
217 /** the layer needs to support per-pixel alpha */
218 kHasAlphaLayer_SaveFlag = 0x04,
219 /** the layer needs to support 8-bits per color component */
220 kFullColorLayer_SaveFlag = 0x08,
221 /** the layer should clip against the bounds argument */
222 kClipToLayer_SaveFlag = 0x10,
223
224 // helper masks for common choices
225 kMatrixClip_SaveFlag = 0x03,
226 kARGB_NoClipLayer_SaveFlag = 0x0F,
227 kARGB_ClipLayer_SaveFlag = 0x1F
228 };
229
reed@android.comdc3381f2010-02-11 16:05:15 +0000230 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000232 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
233 operate on this copy.
234 When the balancing call to restore() is made, the previous matrix, clip,
235 and drawFilter are restored.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 @return The value to pass to restoreToCount() to balance this save()
237 */
238 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
239
240 /** This behaves the same as save(), but in addition it allocates an
241 offscreen bitmap. All drawing calls are directed there, and only when
242 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000243 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000244 @param bounds (may be null) This rect, if non-null, is used as a hint to
245 limit the size of the offscreen, and thus drawing may be
246 clipped to it, though that clipping is not guaranteed to
247 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 @param paint (may be null) This is copied, and is applied to the
249 offscreen when restore() is called
250 @param flags LayerFlags
251 @return The value to pass to restoreToCount() to balance this save()
252 */
253 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
254 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
255
256 /** This behaves the same as save(), but in addition it allocates an
257 offscreen bitmap. All drawing calls are directed there, and only when
258 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000259 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000260 @param bounds (may be null) This rect, if non-null, is used as a hint to
261 limit the size of the offscreen, and thus drawing may be
262 clipped to it, though that clipping is not guaranteed to
263 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000264 @param alpha This is applied to the offscreen when restore() is called.
265 @param flags LayerFlags
266 @return The value to pass to restoreToCount() to balance this save()
267 */
268 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
269 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
270
271 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000272 modifications to the matrix/clip/drawFilter state since the last save
273 call.
274 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275 */
276 virtual void restore();
277
278 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
279 This will equal # save() calls - # restore() calls.
280 */
281 int getSaveCount() const;
282
283 /** Efficient way to pop any calls to save() that happened after the save
284 count reached saveCount. It is an error for saveCount to be less than
285 getSaveCount()
286 @param saveCount The number of save() levels to restore from
287 */
288 void restoreToCount(int saveCount);
289
290 /** Preconcat the current matrix with the specified translation
291 @param dx The distance to translate in X
292 @param dy The distance to translate in Y
293 returns true if the operation succeeded (e.g. did not overflow)
294 */
295 virtual bool translate(SkScalar dx, SkScalar dy);
296
297 /** Preconcat the current matrix with the specified scale.
298 @param sx The amount to scale in X
299 @param sy The amount to scale in Y
300 returns true if the operation succeeded (e.g. did not overflow)
301 */
302 virtual bool scale(SkScalar sx, SkScalar sy);
303
304 /** Preconcat the current matrix with the specified rotation.
305 @param degrees The amount to rotate, in degrees
306 returns true if the operation succeeded (e.g. did not overflow)
307 */
308 virtual bool rotate(SkScalar degrees);
309
310 /** Preconcat the current matrix with the specified skew.
311 @param sx The amount to skew in X
312 @param sy The amount to skew in Y
313 returns true if the operation succeeded (e.g. did not overflow)
314 */
315 virtual bool skew(SkScalar sx, SkScalar sy);
316
317 /** Preconcat the current matrix with the specified matrix.
318 @param matrix The matrix to preconcatenate with the current matrix
319 @return true if the operation succeeded (e.g. did not overflow)
320 */
321 virtual bool concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000322
reed@android.com8a1c16f2008-12-17 15:59:43 +0000323 /** Replace the current matrix with a copy of the specified matrix.
324 @param matrix The matrix that will be copied into the current matrix.
325 */
326 virtual void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000327
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 /** Helper for setMatrix(identity). Sets the current matrix to identity.
329 */
330 void resetMatrix();
331
332 /** Modify the current clip with the specified rectangle.
333 @param rect The rect to intersect with the current clip
334 @param op The region op to apply to the current clip
335 @return true if the canvas' clip is non-empty
336 */
337 virtual bool clipRect(const SkRect& rect,
reed@google.com071eef92011-10-12 11:52:53 +0000338 SkRegion::Op op = SkRegion::kIntersect_Op,
339 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340
341 /** Modify the current clip with the specified path.
342 @param path The path to apply to the current clip
343 @param op The region op to apply to the current clip
344 @return true if the canvas' new clip is non-empty
345 */
346 virtual bool clipPath(const SkPath& path,
reed@google.com071eef92011-10-12 11:52:53 +0000347 SkRegion::Op op = SkRegion::kIntersect_Op,
348 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000349
350 /** Modify the current clip with the specified region. Note that unlike
351 clipRect() and clipPath() which transform their arguments by the current
352 matrix, clipRegion() assumes its argument is already in device
353 coordinates, and so no transformation is performed.
354 @param deviceRgn The region to apply to the current clip
355 @param op The region op to apply to the current clip
356 @return true if the canvas' new clip is non-empty
357 */
358 virtual bool clipRegion(const SkRegion& deviceRgn,
359 SkRegion::Op op = SkRegion::kIntersect_Op);
360
361 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
362 specified region. This does not intersect or in any other way account
363 for the existing clip region.
364 @param deviceRgn The region to copy into the current clip.
365 @return true if the new clip region is non-empty
366 */
367 bool setClipRegion(const SkRegion& deviceRgn) {
368 return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
369 }
370
371 /** Enum describing how to treat edges when performing quick-reject tests
372 of a geometry against the current clip. Treating them as antialiased
373 (kAA_EdgeType) will take into account the extra pixels that may be drawn
374 if the edge does not lie exactly on a device pixel boundary (after being
375 transformed by the current matrix).
376 */
377 enum EdgeType {
378 /** Treat the edges as B&W (not antialiased) for the purposes of testing
379 against the current clip
380 */
381 kBW_EdgeType,
382 /** Treat the edges as antialiased for the purposes of testing
383 against the current clip
384 */
385 kAA_EdgeType
386 };
387
388 /** Return true if the specified rectangle, after being transformed by the
389 current matrix, would lie completely outside of the current clip. Call
390 this to check if an area you intend to draw into is clipped out (and
391 therefore you can skip making the draw calls).
392 @param rect the rect to compare with the current clip
393 @param et specifies how to treat the edges (see EdgeType)
394 @return true if the rect (transformed by the canvas' matrix) does not
395 intersect with the canvas' clip
396 */
397 bool quickReject(const SkRect& rect, EdgeType et) const;
398
399 /** Return true if the specified path, after being transformed by the
400 current matrix, would lie completely outside of the current clip. Call
401 this to check if an area you intend to draw into is clipped out (and
402 therefore you can skip making the draw calls). Note, for speed it may
403 return false even if the path itself might not intersect the clip
404 (i.e. the bounds of the path intersects, but the path does not).
405 @param path The path to compare with the current clip
406 @param et specifies how to treat the edges (see EdgeType)
407 @return true if the path (transformed by the canvas' matrix) does not
408 intersect with the canvas' clip
409 */
410 bool quickReject(const SkPath& path, EdgeType et) const;
411
412 /** Return true if the horizontal band specified by top and bottom is
413 completely clipped out. This is a conservative calculation, meaning
414 that it is possible that if the method returns false, the band may still
415 in fact be clipped out, but the converse is not true. If this method
416 returns true, then the band is guaranteed to be clipped out.
417 @param top The top of the horizontal band to compare with the clip
418 @param bottom The bottom of the horizontal and to compare with the clip
419 @return true if the horizontal band is completely clipped out (i.e. does
420 not intersect the current clip)
421 */
422 bool quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const;
423
424 /** Return the bounds of the current clip (in local coordinates) in the
425 bounds parameter, and return true if it is non-empty. This can be useful
426 in a way similar to quickReject, in that it tells you that drawing
427 outside of these bounds will be clipped out.
428 */
429 bool getClipBounds(SkRect* bounds, EdgeType et = kAA_EdgeType) const;
430
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000431 /** Return the bounds of the current clip, in device coordinates; returns
432 true if non-empty. Maybe faster than getting the clip explicitly and
433 then taking its bounds.
434 */
435 bool getClipDeviceBounds(SkIRect* bounds) const;
436
437
reed@android.com8a1c16f2008-12-17 15:59:43 +0000438 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000439 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000440 @param a the alpha component (0..255) of the color to fill the canvas
441 @param r the red component (0..255) of the color to fill the canvas
442 @param g the green component (0..255) of the color to fill the canvas
443 @param b the blue component (0..255) of the color to fill the canvas
444 @param mode the mode to apply the color in (defaults to SrcOver)
445 */
446 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000447 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000448
449 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000450 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000451 @param color the color to draw with
452 @param mode the mode to apply the color in (defaults to SrcOver)
453 */
454 void drawColor(SkColor color,
reed@android.com845fdac2009-06-23 03:01:32 +0000455 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000456
reed@google.com2a981812011-04-14 18:59:28 +0000457 /**
458 * This erases the entire drawing surface to the specified color,
459 * irrespective of the clip. It does not blend with the previous pixels,
460 * but always overwrites them.
461 *
462 * It is roughly equivalent to the following:
463 * canvas.save();
464 * canvas.clipRect(hugeRect, kReplace_Op);
465 * paint.setColor(color);
466 * paint.setXfermodeMode(kSrc_Mode);
467 * canvas.drawPaint(paint);
468 * canvas.restore();
469 * though it is almost always much more efficient.
470 */
471 virtual void clear(SkColor);
472
473 /**
474 * Fill the entire canvas' bitmap (restricted to the current clip) with the
475 * specified paint.
476 * @param paint The paint used to fill the canvas
477 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478 virtual void drawPaint(const SkPaint& paint);
479
480 enum PointMode {
481 /** drawPoints draws each point separately */
482 kPoints_PointMode,
483 /** drawPoints draws each pair of points as a line segment */
484 kLines_PointMode,
485 /** drawPoints draws the array of points as a polygon */
486 kPolygon_PointMode
487 };
488
489 /** Draw a series of points, interpreted based on the PointMode mode. For
490 all modes, the count parameter is interpreted as the total number of
491 points. For kLine mode, count/2 line segments are drawn.
492 For kPoint mode, each point is drawn centered at its coordinate, and its
493 size is specified by the paint's stroke-width. It draws as a square,
494 unless the paint's cap-type is round, in which the points are drawn as
495 circles.
496 For kLine mode, each pair of points is drawn as a line segment,
497 respecting the paint's settings for cap/join/width.
498 For kPolygon mode, the entire array is drawn as a series of connected
499 line segments.
500 Note that, while similar, kLine and kPolygon modes draw slightly
501 differently than the equivalent path built with a series of moveto,
502 lineto calls, in that the path will draw all of its contours at once,
503 with no interactions if contours intersect each other (think XOR
504 xfermode). drawPoints always draws each element one at a time.
505 @param mode PointMode specifying how to draw the array of points.
506 @param count The number of points in the array
507 @param pts Array of points to draw
508 @param paint The paint used to draw the points
509 */
510 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
511 const SkPaint& paint);
512
513 /** Helper method for drawing a single point. See drawPoints() for a more
514 details.
515 */
516 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000517
reed@android.com8a1c16f2008-12-17 15:59:43 +0000518 /** Draws a single pixel in the specified color.
519 @param x The X coordinate of which pixel to draw
520 @param y The Y coordiante of which pixel to draw
521 @param color The color to draw
522 */
523 void drawPoint(SkScalar x, SkScalar y, SkColor color);
524
525 /** Draw a line segment with the specified start and stop x,y coordinates,
526 using the specified paint. NOTE: since a line is always "framed", the
527 paint's Style is ignored.
528 @param x0 The x-coordinate of the start point of the line
529 @param y0 The y-coordinate of the start point of the line
530 @param x1 The x-coordinate of the end point of the line
531 @param y1 The y-coordinate of the end point of the line
532 @param paint The paint used to draw the line
533 */
534 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
535 const SkPaint& paint);
536
537 /** Draw the specified rectangle using the specified paint. The rectangle
538 will be filled or stroked based on the Style in the paint.
539 @param rect The rect to be drawn
540 @param paint The paint used to draw the rect
541 */
542 virtual void drawRect(const SkRect& rect, const SkPaint& paint);
543
544 /** Draw the specified rectangle using the specified paint. The rectangle
545 will be filled or framed based on the Style in the paint.
546 @param rect The rect to be drawn
547 @param paint The paint used to draw the rect
548 */
549 void drawIRect(const SkIRect& rect, const SkPaint& paint)
550 {
551 SkRect r;
552 r.set(rect); // promotes the ints to scalars
553 this->drawRect(r, paint);
554 }
reed@google.com4b226022011-01-11 18:32:13 +0000555
reed@android.com8a1c16f2008-12-17 15:59:43 +0000556 /** Draw the specified rectangle using the specified paint. The rectangle
557 will be filled or framed based on the Style in the paint.
558 @param left The left side of the rectangle to be drawn
559 @param top The top side of the rectangle to be drawn
560 @param right The right side of the rectangle to be drawn
561 @param bottom The bottom side of the rectangle to be drawn
562 @param paint The paint used to draw the rect
563 */
564 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
565 SkScalar bottom, const SkPaint& paint);
566
567 /** Draw the specified oval using the specified paint. The oval will be
568 filled or framed based on the Style in the paint.
569 @param oval The rectangle bounds of the oval to be drawn
570 @param paint The paint used to draw the oval
571 */
572 void drawOval(const SkRect& oval, const SkPaint&);
573
574 /** Draw the specified circle using the specified paint. If radius is <= 0,
575 then nothing will be drawn. The circle will be filled
576 or framed based on the Style in the paint.
577 @param cx The x-coordinate of the center of the cirle to be drawn
578 @param cy The y-coordinate of the center of the cirle to be drawn
579 @param radius The radius of the cirle to be drawn
580 @param paint The paint used to draw the circle
581 */
582 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
583 const SkPaint& paint);
584
585 /** Draw the specified arc, which will be scaled to fit inside the
586 specified oval. If the sweep angle is >= 360, then the oval is drawn
587 completely. Note that this differs slightly from SkPath::arcTo, which
588 treats the sweep angle mod 360.
589 @param oval The bounds of oval used to define the shape of the arc
590 @param startAngle Starting angle (in degrees) where the arc begins
591 @param sweepAngle Sweep angle (in degrees) measured clockwise
592 @param useCenter true means include the center of the oval. For filling
593 this will draw a wedge. False means just use the arc.
594 @param paint The paint used to draw the arc
595 */
596 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
597 bool useCenter, const SkPaint& paint);
598
599 /** Draw the specified round-rect using the specified paint. The round-rect
600 will be filled or framed based on the Style in the paint.
601 @param rect The rectangular bounds of the roundRect to be drawn
602 @param rx The x-radius of the oval used to round the corners
603 @param ry The y-radius of the oval used to round the corners
604 @param paint The paint used to draw the roundRect
605 */
606 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
607 const SkPaint& paint);
608
609 /** Draw the specified path using the specified paint. The path will be
610 filled or framed based on the Style in the paint.
611 @param path The path to be drawn
612 @param paint The paint used to draw the path
613 */
614 virtual void drawPath(const SkPath& path, const SkPaint& paint);
615
616 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
617 specified paint, transformed by the current matrix. Note: if the paint
618 contains a maskfilter that generates a mask which extends beyond the
619 bitmap's original width/height, then the bitmap will be drawn as if it
620 were in a Shader with CLAMP mode. Thus the color outside of the original
621 width/height will be the edge color replicated.
622 @param bitmap The bitmap to be drawn
623 @param left The position of the left side of the bitmap being drawn
624 @param top The position of the top side of the bitmap being drawn
625 @param paint The paint used to draw the bitmap, or NULL
626 */
627 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
628 const SkPaint* paint = NULL);
629
630 /** Draw the specified bitmap, with the specified matrix applied (before the
631 canvas' matrix is applied).
632 @param bitmap The bitmap to be drawn
633 @param src Optional: specify the subset of the bitmap to be drawn
634 @param dst The destination rectangle where the scaled/translated
635 image will be drawn
636 @param paint The paint used to draw the bitmap, or NULL
637 */
638 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
639 const SkRect& dst, const SkPaint* paint = NULL);
640
641 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
642 const SkPaint* paint = NULL);
reed@google.com4b226022011-01-11 18:32:13 +0000643
reed@google.comf0b5e112011-09-07 11:57:34 +0000644 /**
645 * Draw the bitmap stretched differentially to fit into dst.
646 * center is a rect within the bitmap, and logically divides the bitmap
647 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
648 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
649 *
650 * If the dst is >= the bitmap size, then...
651 * - The 4 corners are not stretch at all.
652 * - The sides are stretch in only one axis.
653 * - The center is stretch in both axes.
654 * Else, for each axis where dst < bitmap,
655 * - The corners shrink proportionally
656 * - The sides (along the shrink axis) and center are not drawn
657 */
658 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
659 const SkRect& dst, const SkPaint* paint = NULL);
660
reed@android.com8a1c16f2008-12-17 15:59:43 +0000661 /** Draw the specified bitmap, with its top/left corner at (x,y),
662 NOT transformed by the current matrix. Note: if the paint
663 contains a maskfilter that generates a mask which extends beyond the
664 bitmap's original width/height, then the bitmap will be drawn as if it
665 were in a Shader with CLAMP mode. Thus the color outside of the original
666 width/height will be the edge color replicated.
667 @param bitmap The bitmap to be drawn
668 @param left The position of the left side of the bitmap being drawn
669 @param top The position of the top side of the bitmap being drawn
670 @param paint The paint used to draw the bitmap, or NULL
671 */
672 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
673 const SkPaint* paint = NULL);
674
675 /** Draw the text, with origin at (x,y), using the specified paint.
676 The origin is interpreted based on the Align setting in the paint.
677 @param text The text to be drawn
678 @param byteLength The number of bytes to read from the text parameter
679 @param x The x-coordinate of the origin of the text being drawn
680 @param y The y-coordinate of the origin of the text being drawn
681 @param paint The paint used for the text (e.g. color, size, style)
682 */
683 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
684 SkScalar y, const SkPaint& paint);
685
686 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000687 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000688 @param text The text to be drawn
689 @param byteLength The number of bytes to read from the text parameter
690 @param pos Array of positions, used to position each character
691 @param paint The paint used for the text (e.g. color, size, style)
692 */
693 virtual void drawPosText(const void* text, size_t byteLength,
694 const SkPoint pos[], const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000695
reed@android.com8a1c16f2008-12-17 15:59:43 +0000696 /** Draw the text, with each character/glyph origin specified by the x
697 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000698 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000699 @param text The text to be drawn
700 @param byteLength The number of bytes to read from the text parameter
701 @param xpos Array of x-positions, used to position each character
702 @param constY The shared Y coordinate for all of the positions
703 @param paint The paint used for the text (e.g. color, size, style)
704 */
705 virtual void drawPosTextH(const void* text, size_t byteLength,
706 const SkScalar xpos[], SkScalar constY,
707 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000708
reed@android.com8a1c16f2008-12-17 15:59:43 +0000709 /** Draw the text, with origin at (x,y), using the specified paint, along
710 the specified path. The paint's Align setting determins where along the
711 path to start the text.
712 @param text The text to be drawn
713 @param byteLength The number of bytes to read from the text parameter
714 @param path The path the text should follow for its baseline
715 @param hOffset The distance along the path to add to the text's
716 starting position
717 @param vOffset The distance above(-) or below(+) the path to
718 position the text
719 @param paint The paint used for the text
720 */
721 void drawTextOnPathHV(const void* text, size_t byteLength,
722 const SkPath& path, SkScalar hOffset,
723 SkScalar vOffset, const SkPaint& paint);
724
725 /** Draw the text, with origin at (x,y), using the specified paint, along
726 the specified path. The paint's Align setting determins where along the
727 path to start the text.
728 @param text The text to be drawn
729 @param byteLength The number of bytes to read from the text parameter
730 @param path The path the text should follow for its baseline
731 @param matrix (may be null) Applied to the text before it is
732 mapped onto the path
733 @param paint The paint used for the text
734 */
735 virtual void drawTextOnPath(const void* text, size_t byteLength,
736 const SkPath& path, const SkMatrix* matrix,
737 const SkPaint& paint);
738
djsollen@google.com56c69772011-11-08 19:00:26 +0000739#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000740 /** Draw the text on path, with each character/glyph origin specified by the pos[]
741 array. The origin is interpreted by the Align setting in the paint.
742 @param text The text to be drawn
743 @param byteLength The number of bytes to read from the text parameter
744 @param pos Array of positions, used to position each character
745 @param paint The paint used for the text (e.g. color, size, style)
746 @param path The path to draw on
747 @param matrix The canvas matrix
748 */
749 void drawPosTextOnPath(const void* text, size_t byteLength,
750 const SkPoint pos[], const SkPaint& paint,
751 const SkPath& path, const SkMatrix* matrix);
752#endif
753
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754 /** Draw the picture into this canvas. This method effective brackets the
755 playback of the picture's draw calls with save/restore, so the state
756 of this canvas will be unchanged after this call. This contrasts with
757 the more immediate method SkPicture::draw(), which does not bracket
758 the canvas with save/restore, thus the canvas may be left in a changed
759 state after the call.
760 @param picture The recorded drawing commands to playback into this
761 canvas.
762 */
763 virtual void drawPicture(SkPicture& picture);
reed@google.com4b226022011-01-11 18:32:13 +0000764
reed@android.com8a1c16f2008-12-17 15:59:43 +0000765 enum VertexMode {
766 kTriangles_VertexMode,
767 kTriangleStrip_VertexMode,
768 kTriangleFan_VertexMode
769 };
reed@google.com4b226022011-01-11 18:32:13 +0000770
reed@android.com8a1c16f2008-12-17 15:59:43 +0000771 /** Draw the array of vertices, interpreted as triangles (based on mode).
772 @param vmode How to interpret the array of vertices
773 @param vertexCount The number of points in the vertices array (and
774 corresponding texs and colors arrays if non-null)
775 @param vertices Array of vertices for the mesh
776 @param texs May be null. If not null, specifies the coordinate
777 in texture space for each vertex.
778 @param colors May be null. If not null, specifies a color for each
779 vertex, to be interpolated across the triangle.
780 @param xmode Used if both texs and colors are present. In this
781 case the colors are combined with the texture using mode,
782 before being drawn using the paint. If mode is null, then
reed@android.com845fdac2009-06-23 03:01:32 +0000783 kMultiply_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000784 @param indices If not null, array of indices to reference into the
785 vertex (texs, colors) array.
786 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +0000787 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000788 */
789 virtual void drawVertices(VertexMode vmode, int vertexCount,
790 const SkPoint vertices[], const SkPoint texs[],
791 const SkColor colors[], SkXfermode* xmode,
792 const uint16_t indices[], int indexCount,
793 const SkPaint& paint);
794
reed@android.comcb608442009-12-04 21:32:27 +0000795 /** Send a blob of data to the canvas.
796 For canvases that draw, this call is effectively a no-op, as the data
797 is not parsed, but just ignored. However, this call exists for
798 subclasses like SkPicture's recording canvas, that can store the data
799 and then play it back later (via another call to drawData).
800 */
801 virtual void drawData(const void* data, size_t length);
802
reed@android.com8a1c16f2008-12-17 15:59:43 +0000803 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +0000804
reed@android.com8a1c16f2008-12-17 15:59:43 +0000805 /** Get the current bounder object.
806 The bounder's reference count is unchaged.
807 @return the canva's bounder (or NULL).
808 */
809 SkBounder* getBounder() const { return fBounder; }
810
811 /** Set a new bounder (or NULL).
812 Pass NULL to clear any previous bounder.
813 As a convenience, the parameter passed is also returned.
814 If a previous bounder exists, its reference count is decremented.
815 If bounder is not NULL, its reference count is incremented.
816 @param bounder the new bounder (or NULL) to be installed in the canvas
817 @return the set bounder object
818 */
819 virtual SkBounder* setBounder(SkBounder* bounder);
reed@google.com4b226022011-01-11 18:32:13 +0000820
reed@android.com8a1c16f2008-12-17 15:59:43 +0000821 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +0000822 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000823 @return the canvas' filter (or NULL).
824 */
825 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +0000826
reed@android.com8a1c16f2008-12-17 15:59:43 +0000827 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
828 As a convenience, the parameter is returned. If an existing filter
829 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +0000830 refcnt is incremented. The filter is saved/restored, just like the
831 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000832 @param filter the new filter (or NULL)
833 @return the new filter
834 */
835 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
836
837 //////////////////////////////////////////////////////////////////////////
838
839 /** Return the current matrix on the canvas.
840 This does not account for the translate in any of the devices.
841 @return The current matrix on the canvas.
842 */
843 const SkMatrix& getTotalMatrix() const;
844
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000845 enum ClipType {
846 kEmpty_ClipType = 0,
847 kRect_ClipType,
848 kComplex_ClipType
849 };
850
851 /** Returns a description of the total clip; may be cheaper than
852 getting the clip and querying it directly.
853 */
854 ClipType getClipType() const;
855
reed@android.com8a1c16f2008-12-17 15:59:43 +0000856 /** Return the current device clip (concatenation of all clip calls).
857 This does not account for the translate in any of the devices.
858 @return the current device clip (concatenation of all clip calls).
859 */
860 const SkRegion& getTotalClip() const;
861
reed@google.com7d7ca792011-02-23 22:39:18 +0000862 /**
reed@google.com5e2457e2011-10-10 21:24:37 +0000863 * Return true if the current clip is non-empty.
864 *
865 * If bounds is not NULL, set it to the bounds of the current clip
866 * in global coordinates.
867 */
868 bool getTotalClipBounds(SkIRect* bounds) const;
869
870 /**
reed@google.com7d7ca792011-02-23 22:39:18 +0000871 * Return the current clipstack. This mirrors the result in getTotalClip()
872 * but is represented as a stack of geometric clips + region-ops.
873 */
874 const SkClipStack& getTotalClipStack() const;
875
reed@android.comf2b98d62010-12-20 18:26:13 +0000876 void setExternalMatrix(const SkMatrix* = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000877
878 ///////////////////////////////////////////////////////////////////////////
879
880 /** After calling saveLayer(), there can be any number of devices that make
881 up the top-most drawing area. LayerIter can be used to iterate through
882 those devices. Note that the iterator is only valid until the next API
883 call made on the canvas. Ownership of all pointers in the iterator stays
884 with the canvas, so none of them should be modified or deleted.
885 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +0000886 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000887 public:
888 /** Initialize iterator with canvas, and set values for 1st device */
889 LayerIter(SkCanvas*, bool skipEmptyClips);
890 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +0000891
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892 /** Return true if the iterator is done */
893 bool done() const { return fDone; }
894 /** Cycle to the next device */
895 void next();
reed@google.com4b226022011-01-11 18:32:13 +0000896
reed@android.com8a1c16f2008-12-17 15:59:43 +0000897 // These reflect the current device in the iterator
898
899 SkDevice* device() const;
900 const SkMatrix& matrix() const;
901 const SkRegion& clip() const;
902 const SkPaint& paint() const;
903 int x() const;
904 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +0000905
reed@android.com8a1c16f2008-12-17 15:59:43 +0000906 private:
907 // used to embed the SkDrawIter object directly in our instance, w/o
908 // having to expose that class def to the public. There is an assert
909 // in our constructor to ensure that fStorage is large enough
910 // (though needs to be a compile-time-assert!). We use intptr_t to work
911 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +0000912 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +0000913 class SkDrawIter* fImpl; // this points at fStorage
914 SkPaint fDefaultPaint;
915 bool fDone;
916 };
917
918protected:
919 // all of the drawBitmap variants call this guy
reed@android.comf2b98d62010-12-20 18:26:13 +0000920 virtual void commonDrawBitmap(const SkBitmap&, const SkIRect*,
921 const SkMatrix&, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000922
reed@android.com8a1c16f2008-12-17 15:59:43 +0000923private:
924 class MCRec;
925
reed@google.com5c3d1472011-02-22 19:12:23 +0000926 SkClipStack fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000927 SkDeque fMCStack;
928 // points to top of stack
929 MCRec* fMCRec;
930 // the first N recs that can fit here mean we won't call malloc
931 uint32_t fMCRecStorage[32];
932
933 SkBounder* fBounder;
reed@android.com199f1082009-06-10 02:12:47 +0000934 SkDevice* fLastDeviceToGainFocus;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000935
bsalomon@google.comd302f142011-03-03 13:54:13 +0000936 void prepareForDeviceDraw(SkDevice*, const SkMatrix&, const SkRegion&,
937 const SkClipStack& clipStack);
reed@google.com4b226022011-01-11 18:32:13 +0000938
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
940 void updateDeviceCMCache();
941
942 friend class SkDrawIter; // needs setupDrawForLayerDevice()
943
bsalomon@google.come97f0852011-06-17 13:10:25 +0000944 SkDevice* createLayerDevice(SkBitmap::Config, int width, int height,
945 bool isOpaque);
946
reed@android.com8a1c16f2008-12-17 15:59:43 +0000947 SkDevice* init(SkDevice*);
reed@google.comf0b5e112011-09-07 11:57:34 +0000948
949 // internal methods are not virtual, so they can safely be called by other
950 // canvas apis, without confusing subclasses (like SkPictureRecording)
reed@android.comf2b98d62010-12-20 18:26:13 +0000951 void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000952 const SkPaint* paint);
reed@google.comf0b5e112011-09-07 11:57:34 +0000953 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
954 const SkRect& dst, const SkPaint* paint);
955 void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
956 const SkRect& dst, const SkPaint* paint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +0000957 void internalDrawPaint(const SkPaint& paint);
958
reed@google.comf0b5e112011-09-07 11:57:34 +0000959
reed@android.com8a1c16f2008-12-17 15:59:43 +0000960 void drawDevice(SkDevice*, int x, int y, const SkPaint*);
961 // shared by save() and saveLayer()
962 int internalSave(SaveFlags flags);
963 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +0000964 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
965 const SkRect& r, SkScalar textSize);
966 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
967 const char text[], size_t byteLength,
968 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +0000969
reed@android.com8a1c16f2008-12-17 15:59:43 +0000970 /* These maintain a cache of the clip bounds in local coordinates,
971 (converted to 2s-compliment if floats are slow).
972 */
973 mutable SkRectCompareType fLocalBoundsCompareType;
974 mutable bool fLocalBoundsCompareTypeDirty;
975
reed@android.comba09de42010-02-05 20:46:05 +0000976 mutable SkRectCompareType fLocalBoundsCompareTypeBW;
977 mutable bool fLocalBoundsCompareTypeDirtyBW;
978
979 /* Get the local clip bounds with an anti-aliased edge.
980 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000981 const SkRectCompareType& getLocalClipBoundsCompareType() const {
reed@android.comba09de42010-02-05 20:46:05 +0000982 return getLocalClipBoundsCompareType(kAA_EdgeType);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000983 }
reed@android.comba09de42010-02-05 20:46:05 +0000984
985 const SkRectCompareType& getLocalClipBoundsCompareType(EdgeType et) const {
986 if (et == kAA_EdgeType) {
987 if (fLocalBoundsCompareTypeDirty) {
988 this->computeLocalClipBoundsCompareType(et);
989 fLocalBoundsCompareTypeDirty = false;
990 }
991 return fLocalBoundsCompareType;
992 } else {
993 if (fLocalBoundsCompareTypeDirtyBW) {
994 this->computeLocalClipBoundsCompareType(et);
995 fLocalBoundsCompareTypeDirtyBW = false;
996 }
997 return fLocalBoundsCompareTypeBW;
998 }
999 }
1000 void computeLocalClipBoundsCompareType(EdgeType et) const;
reed@android.comf2b98d62010-12-20 18:26:13 +00001001
1002 SkMatrix fExternalMatrix, fExternalInverse;
1003 bool fUseExternalMatrix;
reed@google.com5c3d1472011-02-22 19:12:23 +00001004
1005 class AutoValidateClip : ::SkNoncopyable {
1006 public:
1007 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1008 fCanvas->validateClip();
1009 }
1010 ~AutoValidateClip() { fCanvas->validateClip(); }
1011
1012 private:
1013 const SkCanvas* fCanvas;
1014 };
1015
1016#ifdef SK_DEBUG
1017 void validateClip() const;
1018#else
1019 void validateClip() const {}
1020#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021};
1022
1023/** Stack helper class to automatically call restoreToCount() on the canvas
1024 when this object goes out of scope. Use this to guarantee that the canvas
1025 is restored to a known state.
1026*/
1027class SkAutoCanvasRestore : SkNoncopyable {
1028public:
1029 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
1030 SkASSERT(canvas);
1031 fSaveCount = canvas->getSaveCount();
1032 if (doSave) {
1033 canvas->save();
1034 }
1035 }
1036 ~SkAutoCanvasRestore() {
1037 fCanvas->restoreToCount(fSaveCount);
1038 }
1039
1040private:
1041 SkCanvas* fCanvas;
1042 int fSaveCount;
1043};
1044
1045#endif