blob: 827ebe866d9f1f3dc1b9ed5410573b2a999f5e0b [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;
robertphillips@google.com9b051a32013-08-20 20:06:40 +000025class SkDevice;
reed@android.com8a1c16f2008-12-17 15:59:43 +000026class SkDraw;
27class SkDrawFilter;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000028class SkMetaData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000029class SkPicture;
reed@google.com4ed0fb72012-12-12 20:48:18 +000030class SkRRect;
reed@google.com97af1a62012-08-28 12:19:02 +000031class SkSurface_Base;
reed@android.com8a1c16f2008-12-17 15:59:43 +000032
33/** \class SkCanvas
34
35 A Canvas encapsulates all of the state about drawing into a device (bitmap).
36 This includes a reference to the device itself, and a stack of matrix/clip
37 values. For any given draw call (e.g. drawRect), the geometry of the object
38 being drawn is transformed by the concatenation of all the matrices in the
39 stack. The transformed geometry is clipped by the intersection of all of
40 the clips in the stack.
41
42 While the Canvas holds the state of the drawing device, the state (style)
43 of the object being drawn is held by the Paint, which is provided as a
44 parameter to each of the draw() methods. The Paint holds attributes such as
45 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
46 etc.
47*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000048class SK_API SkCanvas : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000049public:
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000050 SK_DECLARE_INST_COUNT(SkCanvas)
51
reed@google.comcde92112011-07-06 20:00:52 +000052 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000053
reed@google.com6dc74552011-07-21 18:00:46 +000054 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +000055
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000056 @param device Specifies a device for the canvas to draw into.
57 */
robertphillips@google.com9b051a32013-08-20 20:06:40 +000058 explicit SkCanvas(SkDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000059
60 /** Deprecated - Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +000061 @param bitmap Specifies a bitmap for the canvas to draw into. Its
62 structure are copied to the canvas.
63 */
64 explicit SkCanvas(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +000065 virtual ~SkCanvas();
66
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000067 SkMetaData& getMetaData();
68
reed@android.com8a1c16f2008-12-17 15:59:43 +000069 ///////////////////////////////////////////////////////////////////////////
70
reed@google.com210ce002011-11-01 14:24:23 +000071 /**
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +000072 * Trigger the immediate execution of all pending draw operations.
73 */
74 void flush();
75
76 /**
reed@google.com210ce002011-11-01 14:24:23 +000077 * Return the width/height of the underlying device. The current drawable
78 * area may be small (due to clipping or saveLayer). For a canvas with
79 * no device, 0,0 will be returned.
80 */
81 SkISize getDeviceSize() const;
82
reed@android.com8a1c16f2008-12-17 15:59:43 +000083 /** Return the canvas' device object, which may be null. The device holds
84 the bitmap of the pixels that the canvas draws into. The reference count
85 of the returned device is not changed by this call.
86 */
robertphillips@google.com9b051a32013-08-20 20:06:40 +000087 SkDevice* getDevice() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +000088
reed@google.com9266fed2011-03-30 00:18:03 +000089 /**
90 * saveLayer() can create another device (which is later drawn onto
91 * the previous device). getTopDevice() returns the top-most device current
92 * installed. Note that this can change on other calls like save/restore,
93 * so do not access this device after subsequent canvas calls.
94 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +000095 *
96 * @param updateMatrixClip If this is true, then before the device is
97 * returned, we ensure that its has been notified about the current
98 * matrix and clip. Note: this happens automatically when the device
99 * is drawn to, but is optional here, as there is a small perf hit
100 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000101 */
robertphillips@google.com9b051a32013-08-20 20:06:40 +0000102 SkDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9266fed2011-03-30 00:18:03 +0000103
reed@android.comf2b98d62010-12-20 18:26:13 +0000104 /**
reed@google.comcde92112011-07-06 20:00:52 +0000105 * Shortcut for getDevice()->createCompatibleDevice(...).
106 * If getDevice() == NULL, this method does nothing, and returns NULL.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000107 */
robertphillips@google.com9b051a32013-08-20 20:06:40 +0000108 SkDevice* createCompatibleDevice(SkBitmap::Config config,
109 int width, int height,
110 bool isOpaque);
bsalomon@google.come97f0852011-06-17 13:10:25 +0000111
reed@google.com4b226022011-01-11 18:32:13 +0000112 ///////////////////////////////////////////////////////////////////////////
113
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000114 /**
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000115 * This enum can be used with read/writePixels to perform a pixel ops to or
116 * from an 8888 config other than Skia's native config (SkPMColor). There
117 * are three byte orders supported: native, BGRA, and RGBA. Each has a
118 * premultiplied and unpremultiplied variant.
119 *
120 * Components of a 8888 pixel can be packed/unpacked from a 32bit word using
121 * either byte offsets or shift values. Byte offsets are endian-invariant
122 * while shifts are not. BGRA and RGBA configs are defined by byte
123 * orderings. The native config is defined by shift values (SK_A32_SHIFT,
124 * ..., SK_B32_SHIFT).
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000125 */
126 enum Config8888 {
127 /**
128 * Skia's native order specified by:
129 * SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
130 *
131 * kNative_Premul_Config8888 is equivalent to SkPMColor
132 * kNative_Unpremul_Config8888 has the same component order as SkPMColor
133 * but is not premultiplied.
134 */
135 kNative_Premul_Config8888,
136 kNative_Unpremul_Config8888,
137 /**
138 * low byte to high byte: B, G, R, A.
139 */
140 kBGRA_Premul_Config8888,
141 kBGRA_Unpremul_Config8888,
142 /**
143 * low byte to high byte: R, G, B, A.
144 */
145 kRGBA_Premul_Config8888,
tomhudson@google.com1f902872012-06-01 13:15:47 +0000146 kRGBA_Unpremul_Config8888
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000147 };
148
149 /**
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000150 * On success (returns true), copy the canvas pixels into the bitmap.
151 * On failure, the bitmap parameter is left unchanged and false is
152 * returned.
153 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000154 * The canvas' pixels are converted to the bitmap's config. The only
155 * supported config is kARGB_8888_Config, though this is likely to be
156 * relaxed in the future. The meaning of config kARGB_8888_Config is
157 * modified by the enum param config8888. The default value interprets
158 * kARGB_8888_Config as SkPMColor
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000159 *
160 * If the bitmap has pixels already allocated, the canvas pixels will be
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000161 * written there. If not, bitmap->allocPixels() will be called
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000162 * automatically. If the bitmap is backed by a texture readPixels will
163 * fail.
164 *
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000165 * The actual pixels written is the intersection of the canvas' bounds, and
166 * the rectangle formed by the bitmap's width,height and the specified x,y.
167 * If bitmap pixels extend outside of that intersection, they will not be
168 * modified.
169 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000170 * Other failure conditions:
171 * * If the canvas is backed by a non-raster device (e.g. PDF) then
172 * readPixels will fail.
173 * * If bitmap is texture-backed then readPixels will fail. (This may be
174 * relaxed in the future.)
175 *
176 * Example that reads the entire canvas into a bitmap using the native
177 * SkPMColor:
178 * SkISize size = canvas->getDeviceSize();
179 * bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
180 * size.fHeight);
181 * if (canvas->readPixels(bitmap, 0, 0)) {
182 * // use the pixels
183 * }
bsalomon@google.comc6980972011-11-02 19:57:21 +0000184 */
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000185 bool readPixels(SkBitmap* bitmap,
186 int x, int y,
187 Config8888 config8888 = kNative_Premul_Config8888);
bsalomon@google.comc6980972011-11-02 19:57:21 +0000188
reed@google.com4b226022011-01-11 18:32:13 +0000189 /**
bsalomon@google.comc6980972011-11-02 19:57:21 +0000190 * DEPRECATED: This will be removed as soon as webkit is no longer relying
191 * on it. The bitmap is resized to the intersection of srcRect and the
192 * canvas bounds. New pixels are always allocated on success. Bitmap is
193 * unmodified on failure.
reed@google.com51df9e32010-12-23 19:29:18 +0000194 */
195 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000196
197 /**
198 * Similar to draw sprite, this method will copy the pixels in bitmap onto
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000199 * the canvas, with the top/left corner specified by (x, y). The canvas'
200 * pixel values are completely replaced: there is no blending.
201 *
202 * Currently if bitmap is backed by a texture this is a no-op. This may be
203 * relaxed in the future.
204 *
205 * If the bitmap has config kARGB_8888_Config then the config8888 param
206 * will determines how the pixel valuess are intepreted. If the bitmap is
207 * not kARGB_8888_Config then this parameter is ignored.
epoger@google.com4f1151a2011-07-25 15:47:33 +0000208 *
209 * Note: If you are recording drawing commands on this canvas to
210 * SkPicture, writePixels() is ignored!
reed@google.com51df9e32010-12-23 19:29:18 +0000211 */
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000212 void writePixels(const SkBitmap& bitmap,
213 int x, int y,
214 Config8888 config8888 = kNative_Premul_Config8888);
reed@google.com4b226022011-01-11 18:32:13 +0000215
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000217
reed@android.com8a1c16f2008-12-17 15:59:43 +0000218 enum SaveFlags {
219 /** save the matrix state, restoring it on restore() */
220 kMatrix_SaveFlag = 0x01,
221 /** save the clip state, restoring it on restore() */
222 kClip_SaveFlag = 0x02,
223 /** the layer needs to support per-pixel alpha */
224 kHasAlphaLayer_SaveFlag = 0x04,
225 /** the layer needs to support 8-bits per color component */
226 kFullColorLayer_SaveFlag = 0x08,
227 /** the layer should clip against the bounds argument */
228 kClipToLayer_SaveFlag = 0x10,
229
230 // helper masks for common choices
231 kMatrixClip_SaveFlag = 0x03,
232 kARGB_NoClipLayer_SaveFlag = 0x0F,
233 kARGB_ClipLayer_SaveFlag = 0x1F
234 };
235
reed@android.comdc3381f2010-02-11 16:05:15 +0000236 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000238 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
239 operate on this copy.
240 When the balancing call to restore() is made, the previous matrix, clip,
241 and drawFilter are restored.
djsollen@google.comd4236572013-08-13 14:29:06 +0000242 @param flags The flags govern what portion of the Matrix/Clip/drawFilter
243 state the save (and matching restore) effect. For example,
244 if only kMatrix is specified, then only the matrix state
245 will be pushed and popped. Likewise for the clip if kClip
246 is specified. However, the drawFilter is always affected
247 by calls to save/restore.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248 @return The value to pass to restoreToCount() to balance this save()
249 */
250 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
251
252 /** This behaves the same as save(), but in addition it allocates an
253 offscreen bitmap. All drawing calls are directed there, and only when
254 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000255 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000256 @param bounds (may be null) This rect, if non-null, is used as a hint to
257 limit the size of the offscreen, and thus drawing may be
258 clipped to it, though that clipping is not guaranteed to
259 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000260 @param paint (may be null) This is copied, and is applied to the
261 offscreen when restore() is called
262 @param flags LayerFlags
263 @return The value to pass to restoreToCount() to balance this save()
264 */
265 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
266 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
267
268 /** This behaves the same as save(), but in addition it allocates an
269 offscreen bitmap. All drawing calls are directed there, and only when
270 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000271 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000272 @param bounds (may be null) This rect, if non-null, is used as a hint to
273 limit the size of the offscreen, and thus drawing may be
274 clipped to it, though that clipping is not guaranteed to
275 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000276 @param alpha This is applied to the offscreen when restore() is called.
277 @param flags LayerFlags
278 @return The value to pass to restoreToCount() to balance this save()
279 */
280 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
281 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
282
283 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000284 modifications to the matrix/clip/drawFilter state since the last save
285 call.
286 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287 */
288 virtual void restore();
289
290 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
291 This will equal # save() calls - # restore() calls.
292 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000293 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294
295 /** Efficient way to pop any calls to save() that happened after the save
296 count reached saveCount. It is an error for saveCount to be less than
297 getSaveCount()
298 @param saveCount The number of save() levels to restore from
299 */
300 void restoreToCount(int saveCount);
301
reed@google.com7c202932011-12-14 18:48:05 +0000302 /** Returns true if drawing is currently going to a layer (from saveLayer)
303 * rather than to the root device.
304 */
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000305 virtual bool isDrawingToLayer() const;
reed@google.com7c202932011-12-14 18:48:05 +0000306
reed@android.com8a1c16f2008-12-17 15:59:43 +0000307 /** Preconcat the current matrix with the specified translation
308 @param dx The distance to translate in X
309 @param dy The distance to translate in Y
310 returns true if the operation succeeded (e.g. did not overflow)
311 */
312 virtual bool translate(SkScalar dx, SkScalar dy);
313
314 /** Preconcat the current matrix with the specified scale.
315 @param sx The amount to scale in X
316 @param sy The amount to scale in Y
317 returns true if the operation succeeded (e.g. did not overflow)
318 */
319 virtual bool scale(SkScalar sx, SkScalar sy);
320
321 /** Preconcat the current matrix with the specified rotation.
322 @param degrees The amount to rotate, in degrees
323 returns true if the operation succeeded (e.g. did not overflow)
324 */
325 virtual bool rotate(SkScalar degrees);
326
327 /** Preconcat the current matrix with the specified skew.
328 @param sx The amount to skew in X
329 @param sy The amount to skew in Y
330 returns true if the operation succeeded (e.g. did not overflow)
331 */
332 virtual bool skew(SkScalar sx, SkScalar sy);
333
334 /** Preconcat the current matrix with the specified matrix.
335 @param matrix The matrix to preconcatenate with the current matrix
336 @return true if the operation succeeded (e.g. did not overflow)
337 */
338 virtual bool concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000339
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340 /** Replace the current matrix with a copy of the specified matrix.
341 @param matrix The matrix that will be copied into the current matrix.
342 */
343 virtual void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000344
reed@android.com8a1c16f2008-12-17 15:59:43 +0000345 /** Helper for setMatrix(identity). Sets the current matrix to identity.
346 */
347 void resetMatrix();
348
reed@google.com4ed0fb72012-12-12 20:48:18 +0000349 /**
350 * Modify the current clip with the specified rectangle.
351 * @param rect The rect to combine with the current clip
352 * @param op The region op to apply to the current clip
353 * @param doAntiAlias true if the clip should be antialiased
354 * @return true if the canvas' clip is non-empty
355 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000356 virtual bool clipRect(const SkRect& rect,
reed@google.com071eef92011-10-12 11:52:53 +0000357 SkRegion::Op op = SkRegion::kIntersect_Op,
358 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000359
reed@google.com4ed0fb72012-12-12 20:48:18 +0000360 /**
361 * Modify the current clip with the specified SkRRect.
362 * @param rrect The rrect to combine with the current clip
363 * @param op The region op to apply to the current clip
364 * @param doAntiAlias true if the clip should be antialiased
365 * @return true if the canvas' clip is non-empty
366 */
367 virtual bool clipRRect(const SkRRect& rrect,
368 SkRegion::Op op = SkRegion::kIntersect_Op,
369 bool doAntiAlias = false);
370
371 /**
372 * Modify the current clip with the specified path.
373 * @param path The path to combine with the current clip
374 * @param op The region op to apply to the current clip
375 * @param doAntiAlias true if the clip should be antialiased
376 * @return true if the canvas' new clip is non-empty
377 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000378 virtual bool clipPath(const SkPath& path,
reed@google.com071eef92011-10-12 11:52:53 +0000379 SkRegion::Op op = SkRegion::kIntersect_Op,
380 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000382 /** EXPERIMENTAL -- only used for testing
383 Set to false to force clips to be hard, even if doAntiAlias=true is
384 passed to clipRect or clipPath.
385 */
386 void setAllowSoftClip(bool allow) {
387 fAllowSoftClip = allow;
388 }
389
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000390 /** EXPERIMENTAL -- only used for testing
391 Set to simplify clip stack using path ops.
392 */
393 void setAllowSimplifyClip(bool allow) {
394 fAllowSimplifyClip = allow;
395 }
396
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397 /** Modify the current clip with the specified region. Note that unlike
398 clipRect() and clipPath() which transform their arguments by the current
399 matrix, clipRegion() assumes its argument is already in device
400 coordinates, and so no transformation is performed.
401 @param deviceRgn The region to apply to the current clip
402 @param op The region op to apply to the current clip
403 @return true if the canvas' new clip is non-empty
404 */
405 virtual bool clipRegion(const SkRegion& deviceRgn,
406 SkRegion::Op op = SkRegion::kIntersect_Op);
407
408 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
409 specified region. This does not intersect or in any other way account
410 for the existing clip region.
411 @param deviceRgn The region to copy into the current clip.
412 @return true if the new clip region is non-empty
413 */
414 bool setClipRegion(const SkRegion& deviceRgn) {
415 return this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
416 }
417
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 /** Return true if the specified rectangle, after being transformed by the
419 current matrix, would lie completely outside of the current clip. Call
420 this to check if an area you intend to draw into is clipped out (and
421 therefore you can skip making the draw calls).
422 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 @return true if the rect (transformed by the canvas' matrix) does not
424 intersect with the canvas' clip
425 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000426 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000427
428 /** Return true if the specified path, after being transformed by the
429 current matrix, would lie completely outside of the current clip. Call
430 this to check if an area you intend to draw into is clipped out (and
431 therefore you can skip making the draw calls). Note, for speed it may
432 return false even if the path itself might not intersect the clip
433 (i.e. the bounds of the path intersects, but the path does not).
434 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000435 @return true if the path (transformed by the canvas' matrix) does not
436 intersect with the canvas' clip
437 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000438 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000439
440 /** Return true if the horizontal band specified by top and bottom is
441 completely clipped out. This is a conservative calculation, meaning
442 that it is possible that if the method returns false, the band may still
443 in fact be clipped out, but the converse is not true. If this method
444 returns true, then the band is guaranteed to be clipped out.
445 @param top The top of the horizontal band to compare with the clip
446 @param bottom The bottom of the horizontal and to compare with the clip
447 @return true if the horizontal band is completely clipped out (i.e. does
448 not intersect the current clip)
449 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000450 bool quickRejectY(SkScalar top, SkScalar bottom) const {
djsollen@google.com92d2a292012-02-27 16:17:59 +0000451 SkASSERT(SkScalarToCompareType(top) <= SkScalarToCompareType(bottom));
reed@google.com3b3e8952012-08-16 20:53:31 +0000452 const SkRectCompareType& clipR = this->getLocalClipBoundsCompareType();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000453 // In the case where the clip is empty and we are provided with a
454 // negative top and positive bottom parameter then this test will return
455 // false even though it will be clipped. We have chosen to exclude that
456 // check as it is rare and would result double the comparisons.
457 return SkScalarToCompareType(top) >= clipR.fBottom
458 || SkScalarToCompareType(bottom) <= clipR.fTop;
459 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460
461 /** Return the bounds of the current clip (in local coordinates) in the
462 bounds parameter, and return true if it is non-empty. This can be useful
463 in a way similar to quickReject, in that it tells you that drawing
464 outside of these bounds will be clipped out.
465 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000466 bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000467
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000468 /** Return the bounds of the current clip, in device coordinates; returns
469 true if non-empty. Maybe faster than getting the clip explicitly and
470 then taking its bounds.
471 */
472 bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000473
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000474
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000476 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000477 @param a the alpha component (0..255) of the color to fill the canvas
478 @param r the red component (0..255) of the color to fill the canvas
479 @param g the green component (0..255) of the color to fill the canvas
480 @param b the blue component (0..255) of the color to fill the canvas
481 @param mode the mode to apply the color in (defaults to SrcOver)
482 */
483 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000484 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000485
486 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000487 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000488 @param color the color to draw with
489 @param mode the mode to apply the color in (defaults to SrcOver)
490 */
491 void drawColor(SkColor color,
reed@android.com845fdac2009-06-23 03:01:32 +0000492 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000493
reed@google.com2a981812011-04-14 18:59:28 +0000494 /**
495 * This erases the entire drawing surface to the specified color,
496 * irrespective of the clip. It does not blend with the previous pixels,
497 * but always overwrites them.
498 *
499 * It is roughly equivalent to the following:
500 * canvas.save();
501 * canvas.clipRect(hugeRect, kReplace_Op);
502 * paint.setColor(color);
503 * paint.setXfermodeMode(kSrc_Mode);
504 * canvas.drawPaint(paint);
505 * canvas.restore();
506 * though it is almost always much more efficient.
507 */
508 virtual void clear(SkColor);
509
510 /**
511 * Fill the entire canvas' bitmap (restricted to the current clip) with the
512 * specified paint.
513 * @param paint The paint used to fill the canvas
514 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000515 virtual void drawPaint(const SkPaint& paint);
516
517 enum PointMode {
518 /** drawPoints draws each point separately */
519 kPoints_PointMode,
520 /** drawPoints draws each pair of points as a line segment */
521 kLines_PointMode,
522 /** drawPoints draws the array of points as a polygon */
523 kPolygon_PointMode
524 };
525
526 /** Draw a series of points, interpreted based on the PointMode mode. For
527 all modes, the count parameter is interpreted as the total number of
528 points. For kLine mode, count/2 line segments are drawn.
529 For kPoint mode, each point is drawn centered at its coordinate, and its
530 size is specified by the paint's stroke-width. It draws as a square,
531 unless the paint's cap-type is round, in which the points are drawn as
532 circles.
533 For kLine mode, each pair of points is drawn as a line segment,
534 respecting the paint's settings for cap/join/width.
535 For kPolygon mode, the entire array is drawn as a series of connected
536 line segments.
537 Note that, while similar, kLine and kPolygon modes draw slightly
538 differently than the equivalent path built with a series of moveto,
539 lineto calls, in that the path will draw all of its contours at once,
540 with no interactions if contours intersect each other (think XOR
541 xfermode). drawPoints always draws each element one at a time.
542 @param mode PointMode specifying how to draw the array of points.
543 @param count The number of points in the array
544 @param pts Array of points to draw
545 @param paint The paint used to draw the points
546 */
547 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
548 const SkPaint& paint);
549
550 /** Helper method for drawing a single point. See drawPoints() for a more
551 details.
552 */
553 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000554
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555 /** Draws a single pixel in the specified color.
556 @param x The X coordinate of which pixel to draw
557 @param y The Y coordiante of which pixel to draw
558 @param color The color to draw
559 */
560 void drawPoint(SkScalar x, SkScalar y, SkColor color);
561
562 /** Draw a line segment with the specified start and stop x,y coordinates,
563 using the specified paint. NOTE: since a line is always "framed", the
564 paint's Style is ignored.
565 @param x0 The x-coordinate of the start point of the line
566 @param y0 The y-coordinate of the start point of the line
567 @param x1 The x-coordinate of the end point of the line
568 @param y1 The y-coordinate of the end point of the line
569 @param paint The paint used to draw the line
570 */
571 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
572 const SkPaint& paint);
573
574 /** Draw the specified rectangle using the specified paint. The rectangle
575 will be filled or stroked based on the Style in the paint.
576 @param rect The rect to be drawn
577 @param paint The paint used to draw the rect
578 */
579 virtual void drawRect(const SkRect& rect, const SkPaint& paint);
580
581 /** Draw the specified rectangle using the specified paint. The rectangle
582 will be filled or framed based on the Style in the paint.
583 @param rect The rect to be drawn
584 @param paint The paint used to draw the rect
585 */
586 void drawIRect(const SkIRect& rect, const SkPaint& paint)
587 {
588 SkRect r;
589 r.set(rect); // promotes the ints to scalars
590 this->drawRect(r, paint);
591 }
reed@google.com4b226022011-01-11 18:32:13 +0000592
reed@android.com8a1c16f2008-12-17 15:59:43 +0000593 /** Draw the specified rectangle using the specified paint. The rectangle
594 will be filled or framed based on the Style in the paint.
595 @param left The left side of the rectangle to be drawn
596 @param top The top side of the rectangle to be drawn
597 @param right The right side of the rectangle to be drawn
598 @param bottom The bottom side of the rectangle to be drawn
599 @param paint The paint used to draw the rect
600 */
601 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
602 SkScalar bottom, const SkPaint& paint);
603
604 /** Draw the specified oval using the specified paint. The oval will be
605 filled or framed based on the Style in the paint.
606 @param oval The rectangle bounds of the oval to be drawn
607 @param paint The paint used to draw the oval
608 */
reed@google.com4ed0fb72012-12-12 20:48:18 +0000609 virtual void drawOval(const SkRect& oval, const SkPaint&);
610
611 /**
612 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
613 * based on the Style in the paint.
614 *
615 * @param rrect The round-rect to draw
616 * @param paint The paint used to draw the round-rect
617 */
618 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000619
620 /** Draw the specified circle using the specified paint. If radius is <= 0,
621 then nothing will be drawn. The circle will be filled
622 or framed based on the Style in the paint.
623 @param cx The x-coordinate of the center of the cirle to be drawn
624 @param cy The y-coordinate of the center of the cirle to be drawn
625 @param radius The radius of the cirle to be drawn
626 @param paint The paint used to draw the circle
627 */
628 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
629 const SkPaint& paint);
630
631 /** Draw the specified arc, which will be scaled to fit inside the
632 specified oval. If the sweep angle is >= 360, then the oval is drawn
633 completely. Note that this differs slightly from SkPath::arcTo, which
634 treats the sweep angle mod 360.
635 @param oval The bounds of oval used to define the shape of the arc
636 @param startAngle Starting angle (in degrees) where the arc begins
637 @param sweepAngle Sweep angle (in degrees) measured clockwise
638 @param useCenter true means include the center of the oval. For filling
639 this will draw a wedge. False means just use the arc.
640 @param paint The paint used to draw the arc
641 */
642 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
643 bool useCenter, const SkPaint& paint);
644
645 /** Draw the specified round-rect using the specified paint. The round-rect
646 will be filled or framed based on the Style in the paint.
647 @param rect The rectangular bounds of the roundRect to be drawn
648 @param rx The x-radius of the oval used to round the corners
649 @param ry The y-radius of the oval used to round the corners
650 @param paint The paint used to draw the roundRect
651 */
652 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
653 const SkPaint& paint);
654
655 /** Draw the specified path using the specified paint. The path will be
656 filled or framed based on the Style in the paint.
657 @param path The path to be drawn
658 @param paint The paint used to draw the path
659 */
660 virtual void drawPath(const SkPath& path, const SkPaint& paint);
661
662 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
663 specified paint, transformed by the current matrix. Note: if the paint
664 contains a maskfilter that generates a mask which extends beyond the
665 bitmap's original width/height, then the bitmap will be drawn as if it
666 were in a Shader with CLAMP mode. Thus the color outside of the original
667 width/height will be the edge color replicated.
668 @param bitmap The bitmap to be drawn
669 @param left The position of the left side of the bitmap being drawn
670 @param top The position of the top side of the bitmap being drawn
671 @param paint The paint used to draw the bitmap, or NULL
672 */
673 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
674 const SkPaint* paint = NULL);
675
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000676 enum DrawBitmapRectFlags {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000677 kNone_DrawBitmapRectFlag = 0x0,
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000678 /**
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000679 * When filtering is enabled, allow the color samples outside of
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000680 * the src rect (but still in the src bitmap) to bleed into the
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000681 * drawn portion
682 */
robertphillips@google.com31acc112013-08-20 12:13:48 +0000683 kBleed_DrawBitmapRectFlag = 0x1,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000684 };
685
reed@android.com8a1c16f2008-12-17 15:59:43 +0000686 /** Draw the specified bitmap, with the specified matrix applied (before the
687 canvas' matrix is applied).
688 @param bitmap The bitmap to be drawn
689 @param src Optional: specify the subset of the bitmap to be drawn
690 @param dst The destination rectangle where the scaled/translated
691 image will be drawn
692 @param paint The paint used to draw the bitmap, or NULL
693 */
reed@google.com71121732012-09-18 15:14:33 +0000694 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
695 const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000696 const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000697 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000698
reed@google.com71121732012-09-18 15:14:33 +0000699 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000700 const SkPaint* paint = NULL) {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000701 this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag);
reed@google.com71121732012-09-18 15:14:33 +0000702 }
703
704 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000705 const SkRect& dst, const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000706 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
reed@google.com71121732012-09-18 15:14:33 +0000707 SkRect realSrcStorage;
708 SkRect* realSrcPtr = NULL;
709 if (isrc) {
710 realSrcStorage.set(*isrc);
711 realSrcPtr = &realSrcStorage;
712 }
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000713 this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
reed@google.com71121732012-09-18 15:14:33 +0000714 }
skia.committer@gmail.comc1ad0222012-09-19 02:01:47 +0000715
reed@android.com8a1c16f2008-12-17 15:59:43 +0000716 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
717 const SkPaint* paint = NULL);
reed@google.com4b226022011-01-11 18:32:13 +0000718
reed@google.comf0b5e112011-09-07 11:57:34 +0000719 /**
720 * Draw the bitmap stretched differentially to fit into dst.
721 * center is a rect within the bitmap, and logically divides the bitmap
722 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
723 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
724 *
725 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000726 * - The 4 corners are not stretched at all.
727 * - The sides are stretched in only one axis.
728 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000729 * Else, for each axis where dst < bitmap,
730 * - The corners shrink proportionally
731 * - The sides (along the shrink axis) and center are not drawn
732 */
733 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
734 const SkRect& dst, const SkPaint* paint = NULL);
735
reed@android.com8a1c16f2008-12-17 15:59:43 +0000736 /** Draw the specified bitmap, with its top/left corner at (x,y),
737 NOT transformed by the current matrix. Note: if the paint
738 contains a maskfilter that generates a mask which extends beyond the
739 bitmap's original width/height, then the bitmap will be drawn as if it
740 were in a Shader with CLAMP mode. Thus the color outside of the original
741 width/height will be the edge color replicated.
742 @param bitmap The bitmap to be drawn
743 @param left The position of the left side of the bitmap being drawn
744 @param top The position of the top side of the bitmap being drawn
745 @param paint The paint used to draw the bitmap, or NULL
746 */
747 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
748 const SkPaint* paint = NULL);
749
750 /** Draw the text, with origin at (x,y), using the specified paint.
751 The origin is interpreted based on the Align setting in the paint.
752 @param text The text to be drawn
753 @param byteLength The number of bytes to read from the text parameter
754 @param x The x-coordinate of the origin of the text being drawn
755 @param y The y-coordinate of the origin of the text being drawn
756 @param paint The paint used for the text (e.g. color, size, style)
757 */
758 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
759 SkScalar y, const SkPaint& paint);
760
761 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000762 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000763 @param text The text to be drawn
764 @param byteLength The number of bytes to read from the text parameter
765 @param pos Array of positions, used to position each character
766 @param paint The paint used for the text (e.g. color, size, style)
767 */
768 virtual void drawPosText(const void* text, size_t byteLength,
769 const SkPoint pos[], const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000770
reed@android.com8a1c16f2008-12-17 15:59:43 +0000771 /** Draw the text, with each character/glyph origin specified by the x
772 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000773 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000774 @param text The text to be drawn
775 @param byteLength The number of bytes to read from the text parameter
776 @param xpos Array of x-positions, used to position each character
777 @param constY The shared Y coordinate for all of the positions
778 @param paint The paint used for the text (e.g. color, size, style)
779 */
780 virtual void drawPosTextH(const void* text, size_t byteLength,
781 const SkScalar xpos[], SkScalar constY,
782 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000783
reed@android.com8a1c16f2008-12-17 15:59:43 +0000784 /** Draw the text, with origin at (x,y), using the specified paint, along
785 the specified path. The paint's Align setting determins where along the
786 path to start the text.
787 @param text The text to be drawn
788 @param byteLength The number of bytes to read from the text parameter
789 @param path The path the text should follow for its baseline
790 @param hOffset The distance along the path to add to the text's
791 starting position
792 @param vOffset The distance above(-) or below(+) the path to
793 position the text
794 @param paint The paint used for the text
795 */
796 void drawTextOnPathHV(const void* text, size_t byteLength,
797 const SkPath& path, SkScalar hOffset,
798 SkScalar vOffset, const SkPaint& paint);
799
800 /** Draw the text, with origin at (x,y), using the specified paint, along
801 the specified path. The paint's Align setting determins where along the
802 path to start the text.
803 @param text The text to be drawn
804 @param byteLength The number of bytes to read from the text parameter
805 @param path The path the text should follow for its baseline
806 @param matrix (may be null) Applied to the text before it is
807 mapped onto the path
808 @param paint The paint used for the text
809 */
810 virtual void drawTextOnPath(const void* text, size_t byteLength,
811 const SkPath& path, const SkMatrix* matrix,
812 const SkPaint& paint);
813
djsollen@google.com56c69772011-11-08 19:00:26 +0000814#ifdef SK_BUILD_FOR_ANDROID
djsollen@google.comcd9d69b2011-03-14 20:30:14 +0000815 /** Draw the text on path, with each character/glyph origin specified by the pos[]
816 array. The origin is interpreted by the Align setting in the paint.
817 @param text The text to be drawn
818 @param byteLength The number of bytes to read from the text parameter
819 @param pos Array of positions, used to position each character
820 @param paint The paint used for the text (e.g. color, size, style)
821 @param path The path to draw on
822 @param matrix The canvas matrix
823 */
824 void drawPosTextOnPath(const void* text, size_t byteLength,
825 const SkPoint pos[], const SkPaint& paint,
826 const SkPath& path, const SkMatrix* matrix);
827#endif
828
reed@android.com8a1c16f2008-12-17 15:59:43 +0000829 /** Draw the picture into this canvas. This method effective brackets the
830 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +0000831 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000832 @param picture The recorded drawing commands to playback into this
833 canvas.
834 */
835 virtual void drawPicture(SkPicture& picture);
reed@google.com4b226022011-01-11 18:32:13 +0000836
reed@android.com8a1c16f2008-12-17 15:59:43 +0000837 enum VertexMode {
838 kTriangles_VertexMode,
839 kTriangleStrip_VertexMode,
840 kTriangleFan_VertexMode
841 };
reed@google.com4b226022011-01-11 18:32:13 +0000842
reed@android.com8a1c16f2008-12-17 15:59:43 +0000843 /** Draw the array of vertices, interpreted as triangles (based on mode).
844 @param vmode How to interpret the array of vertices
845 @param vertexCount The number of points in the vertices array (and
846 corresponding texs and colors arrays if non-null)
847 @param vertices Array of vertices for the mesh
848 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +0000849 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000850 @param colors May be null. If not null, specifies a color for each
851 vertex, to be interpolated across the triangle.
852 @param xmode Used if both texs and colors are present. In this
853 case the colors are combined with the texture using mode,
854 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +0000855 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000856 @param indices If not null, array of indices to reference into the
857 vertex (texs, colors) array.
858 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +0000859 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000860 */
861 virtual void drawVertices(VertexMode vmode, int vertexCount,
862 const SkPoint vertices[], const SkPoint texs[],
863 const SkColor colors[], SkXfermode* xmode,
864 const uint16_t indices[], int indexCount,
865 const SkPaint& paint);
866
reed@android.comcb608442009-12-04 21:32:27 +0000867 /** Send a blob of data to the canvas.
868 For canvases that draw, this call is effectively a no-op, as the data
869 is not parsed, but just ignored. However, this call exists for
870 subclasses like SkPicture's recording canvas, that can store the data
871 and then play it back later (via another call to drawData).
872 */
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000873 virtual void drawData(const void* data, size_t length) {
874 // do nothing. Subclasses may do something with the data
875 }
876
skia.committer@gmail.coma5d3e772013-05-30 07:01:29 +0000877 /** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
878 Each comment added via addComment is notionally attached to its
robertphillips@google.com0a4805e2013-05-29 13:24:23 +0000879 enclosing group. Top-level comments simply belong to no group.
880 */
881 virtual void beginCommentGroup(const char* description) {
882 // do nothing. Subclasses may do something
883 }
884 virtual void addComment(const char* kywd, const char* value) {
885 // do nothing. Subclasses may do something
886 }
887 virtual void endCommentGroup() {
888 // do nothing. Subclasses may do something
889 }
890
reed@android.comcb608442009-12-04 21:32:27 +0000891
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +0000893
reed@android.com8a1c16f2008-12-17 15:59:43 +0000894 /** Get the current bounder object.
895 The bounder's reference count is unchaged.
896 @return the canva's bounder (or NULL).
897 */
898 SkBounder* getBounder() const { return fBounder; }
899
900 /** Set a new bounder (or NULL).
901 Pass NULL to clear any previous bounder.
902 As a convenience, the parameter passed is also returned.
903 If a previous bounder exists, its reference count is decremented.
904 If bounder is not NULL, its reference count is incremented.
905 @param bounder the new bounder (or NULL) to be installed in the canvas
906 @return the set bounder object
907 */
908 virtual SkBounder* setBounder(SkBounder* bounder);
reed@google.com4b226022011-01-11 18:32:13 +0000909
reed@android.com8a1c16f2008-12-17 15:59:43 +0000910 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +0000911 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000912 @return the canvas' filter (or NULL).
913 */
914 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +0000915
reed@android.com8a1c16f2008-12-17 15:59:43 +0000916 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
917 As a convenience, the parameter is returned. If an existing filter
918 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +0000919 refcnt is incremented. The filter is saved/restored, just like the
920 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000921 @param filter the new filter (or NULL)
922 @return the new filter
923 */
924 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
925
926 //////////////////////////////////////////////////////////////////////////
927
928 /** Return the current matrix on the canvas.
929 This does not account for the translate in any of the devices.
930 @return The current matrix on the canvas.
931 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000932 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000933
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000934 enum ClipType {
935 kEmpty_ClipType = 0,
936 kRect_ClipType,
937 kComplex_ClipType
938 };
939
940 /** Returns a description of the total clip; may be cheaper than
941 getting the clip and querying it directly.
942 */
943 ClipType getClipType() const;
944
reed@android.com8a1c16f2008-12-17 15:59:43 +0000945 /** Return the current device clip (concatenation of all clip calls).
reed@google.coma707f602012-04-12 16:12:16 +0000946 * This does not account for the translate in any of the devices.
947 * @return the current device clip (concatenation of all clip calls).
reed@google.com5e2457e2011-10-10 21:24:37 +0000948 *
reed@google.coma707f602012-04-12 16:12:16 +0000949 * DEPRECATED -- call getClipDeviceBounds() instead.
reed@google.com5e2457e2011-10-10 21:24:37 +0000950 */
reed@google.coma707f602012-04-12 16:12:16 +0000951 const SkRegion& getTotalClip() const;
reed@google.com5e2457e2011-10-10 21:24:37 +0000952
robertphillips@google.com40a1ae42012-07-13 15:36:15 +0000953 /** Return the clip stack. The clip stack stores all the individual
954 * clips organized by the save/restore frame in which they were
955 * added.
956 * @return the current clip stack ("list" of individual clip elements)
957 */
958 const SkClipStack* getClipStack() const {
959 return &fClipStack;
960 }
961
reed@google.com90c07ea2012-04-13 13:50:27 +0000962 class ClipVisitor {
963 public:
justinlin@google.com20a550c2012-07-27 17:37:12 +0000964 virtual ~ClipVisitor();
reed@google.com90c07ea2012-04-13 13:50:27 +0000965 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
966 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
967 };
968
969 /**
970 * Replays the clip operations, back to front, that have been applied to
971 * the canvas, calling the appropriate method on the visitor for each
972 * clip. All clips have already been transformed into device space.
973 */
974 void replayClips(ClipVisitor*) const;
975
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976 ///////////////////////////////////////////////////////////////////////////
977
978 /** After calling saveLayer(), there can be any number of devices that make
979 up the top-most drawing area. LayerIter can be used to iterate through
980 those devices. Note that the iterator is only valid until the next API
981 call made on the canvas. Ownership of all pointers in the iterator stays
982 with the canvas, so none of them should be modified or deleted.
983 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +0000984 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000985 public:
986 /** Initialize iterator with canvas, and set values for 1st device */
987 LayerIter(SkCanvas*, bool skipEmptyClips);
988 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +0000989
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990 /** Return true if the iterator is done */
991 bool done() const { return fDone; }
992 /** Cycle to the next device */
993 void next();
reed@google.com4b226022011-01-11 18:32:13 +0000994
reed@android.com8a1c16f2008-12-17 15:59:43 +0000995 // These reflect the current device in the iterator
996
robertphillips@google.com9b051a32013-08-20 20:06:40 +0000997 SkDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998 const SkMatrix& matrix() const;
999 const SkRegion& clip() const;
1000 const SkPaint& paint() const;
1001 int x() const;
1002 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001003
reed@android.com8a1c16f2008-12-17 15:59:43 +00001004 private:
1005 // used to embed the SkDrawIter object directly in our instance, w/o
1006 // having to expose that class def to the public. There is an assert
1007 // in our constructor to ensure that fStorage is large enough
1008 // (though needs to be a compile-time-assert!). We use intptr_t to work
1009 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001010 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001011 class SkDrawIter* fImpl; // this points at fStorage
1012 SkPaint fDefaultPaint;
1013 bool fDone;
1014 };
1015
1016protected:
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001017 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001018 // returns this. Subclasses that encapsulate an indirect canvas may
1019 // need to overload this method. The impl must keep track of this, as it
1020 // is not released or deleted by the caller.
1021 virtual SkCanvas* canvasForDrawIter();
1022
junov@chromium.orga907ac32012-02-24 21:54:07 +00001023 // Clip rectangle bounds. Called internally by saveLayer.
1024 // returns false if the entire rectangle is entirely clipped out
1025 bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
reed@google.com49794c02012-03-15 12:10:47 +00001026 SkIRect* intersection);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001027
junov@chromium.orged8d6bb2013-05-29 19:09:48 +00001028 // Called by child classes that override clipPath and clipRRect to only
1029 // track fast conservative clip bounds, rather than exact clips.
1030 bool updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op,
1031 bool inverseFilled);
1032
reed@google.com97af1a62012-08-28 12:19:02 +00001033 // notify our surface (if we have one) that we are about to draw, so it
1034 // can perform copy-on-write or invalidate any cached images
1035 void predrawNotify();
1036
reed@google.com260eae52012-11-14 19:07:24 +00001037 /** DEPRECATED -- use constructor(device)
1038
1039 Marked as 'protected' to avoid new clients using this before we can
1040 completely remove it.
1041
1042 Specify a device for this canvas to draw into. If it is not null, its
1043 reference count is incremented. If the canvas was already holding a
1044 device, its reference count is decremented. The new device is returned.
1045 */
robertphillips@google.com9b051a32013-08-20 20:06:40 +00001046 virtual SkDevice* setDevice(SkDevice* device);
reed@google.com260eae52012-11-14 19:07:24 +00001047
reed@android.com8a1c16f2008-12-17 15:59:43 +00001048private:
1049 class MCRec;
1050
reed@google.com5c3d1472011-02-22 19:12:23 +00001051 SkClipStack fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001052 SkDeque fMCStack;
1053 // points to top of stack
1054 MCRec* fMCRec;
1055 // the first N recs that can fit here mean we won't call malloc
1056 uint32_t fMCRecStorage[32];
1057
1058 SkBounder* fBounder;
junov@chromium.orgb0a7ace2012-04-05 18:33:23 +00001059 int fSaveLayerCount; // number of successful saveLayer calls
reed@android.com8a1c16f2008-12-17 15:59:43 +00001060
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001061 SkMetaData* fMetaData;
1062
reed@google.com97af1a62012-08-28 12:19:02 +00001063 SkSurface_Base* fSurfaceBase;
1064 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1065 void setSurfaceBase(SkSurface_Base* sb) {
1066 fSurfaceBase = sb;
1067 }
1068 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001069 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001070
reed@android.com8a1c16f2008-12-17 15:59:43 +00001071 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1072 void updateDeviceCMCache();
1073
1074 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001075 friend class AutoDrawLooper;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001076
robertphillips@google.com9b051a32013-08-20 20:06:40 +00001077 SkDevice* createLayerDevice(SkBitmap::Config, int width, int height,
1078 bool isOpaque);
bsalomon@google.come97f0852011-06-17 13:10:25 +00001079
robertphillips@google.com9b051a32013-08-20 20:06:40 +00001080 SkDevice* init(SkDevice*);
reed@google.comf0b5e112011-09-07 11:57:34 +00001081
1082 // internal methods are not virtual, so they can safely be called by other
1083 // canvas apis, without confusing subclasses (like SkPictureRecording)
robertphillips@google.com9bf380c2013-07-25 12:10:42 +00001084 void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
reed@google.com71121732012-09-18 15:14:33 +00001085 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001086 const SkRect& dst, const SkPaint* paint,
1087 DrawBitmapRectFlags flags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001088 void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1089 const SkRect& dst, const SkPaint* paint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001090 void internalDrawPaint(const SkPaint& paint);
reed@google.com8926b162012-03-23 15:36:36 +00001091 int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
1092 SaveFlags, bool justForImageFilter);
robertphillips@google.com9b051a32013-08-20 20:06:40 +00001093 void internalDrawDevice(SkDevice*, int x, int y, const SkPaint*);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001094
reed@android.com8a1c16f2008-12-17 15:59:43 +00001095 // shared by save() and saveLayer()
1096 int internalSave(SaveFlags flags);
1097 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001098 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1099 const SkRect& r, SkScalar textSize);
1100 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1101 const char text[], size_t byteLength,
1102 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001103
reed@android.com8a1c16f2008-12-17 15:59:43 +00001104 /* These maintain a cache of the clip bounds in local coordinates,
1105 (converted to 2s-compliment if floats are slow).
1106 */
1107 mutable SkRectCompareType fLocalBoundsCompareType;
1108 mutable bool fLocalBoundsCompareTypeDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001109 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001110 bool fAllowSimplifyClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001111
1112 const SkRectCompareType& getLocalClipBoundsCompareType() const {
reed@google.com3b3e8952012-08-16 20:53:31 +00001113 if (fLocalBoundsCompareTypeDirty) {
1114 this->computeLocalClipBoundsCompareType();
1115 fLocalBoundsCompareTypeDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001116 }
reed@google.com3b3e8952012-08-16 20:53:31 +00001117 return fLocalBoundsCompareType;
reed@android.comba09de42010-02-05 20:46:05 +00001118 }
reed@google.com3b3e8952012-08-16 20:53:31 +00001119 void computeLocalClipBoundsCompareType() const;
reed@android.comf2b98d62010-12-20 18:26:13 +00001120
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001121
reed@google.com5c3d1472011-02-22 19:12:23 +00001122 class AutoValidateClip : ::SkNoncopyable {
1123 public:
1124 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1125 fCanvas->validateClip();
1126 }
1127 ~AutoValidateClip() { fCanvas->validateClip(); }
1128
1129 private:
1130 const SkCanvas* fCanvas;
1131 };
1132
1133#ifdef SK_DEBUG
1134 void validateClip() const;
1135#else
1136 void validateClip() const {}
1137#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001138
1139 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001140};
1141
1142/** Stack helper class to automatically call restoreToCount() on the canvas
1143 when this object goes out of scope. Use this to guarantee that the canvas
1144 is restored to a known state.
1145*/
1146class SkAutoCanvasRestore : SkNoncopyable {
1147public:
1148 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) {
1149 SkASSERT(canvas);
1150 fSaveCount = canvas->getSaveCount();
1151 if (doSave) {
1152 canvas->save();
1153 }
1154 }
1155 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001156 if (fCanvas) {
1157 fCanvas->restoreToCount(fSaveCount);
1158 }
1159 }
1160
1161 /**
1162 * Perform the restore now, instead of waiting for the destructor. Will
1163 * only do this once.
1164 */
1165 void restore() {
1166 if (fCanvas) {
1167 fCanvas->restoreToCount(fSaveCount);
1168 fCanvas = NULL;
1169 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001170 }
1171
1172private:
1173 SkCanvas* fCanvas;
1174 int fSaveCount;
1175};
1176
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001177/** Stack helper class to automatically open and close a comment block
1178 */
1179class SkAutoCommentBlock : SkNoncopyable {
1180public:
1181 SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
1182 fCanvas = canvas;
1183 if (NULL != fCanvas) {
1184 fCanvas->beginCommentGroup(description);
1185 }
1186 }
1187
1188 ~SkAutoCommentBlock() {
1189 if (NULL != fCanvas) {
1190 fCanvas->endCommentGroup();
1191 }
1192 }
1193
1194private:
1195 SkCanvas* fCanvas;
1196};
1197
reed@android.com8a1c16f2008-12-17 15:59:43 +00001198#endif