blob: 7fd21352a468e21d55d618432684ff23230e9cd6 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkCanvas_DEFINED
9#define SkCanvas_DEFINED
10
11#include "SkTypes.h"
12#include "SkBitmap.h"
13#include "SkDeque.h"
reed@google.com5c3d1472011-02-22 19:12:23 +000014#include "SkClipStack.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015#include "SkPaint.h"
16#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#include "SkPath.h"
18#include "SkRegion.h"
reed@android.com845fdac2009-06-23 03:01:32 +000019#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000020
reed@google.comb93ba452014-03-10 19:47:58 +000021// if not defined, we always assume ClipToLayer for saveLayer()
22//#define SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
23
24
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000025//#define SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +000026//#define SK_SUPPORT_LEGACY_GETCLIPTYPE
27//#define SK_SUPPORT_LEGACY_GETTOTALCLIP
reed@google.com9c135db2014-03-12 18:28:35 +000028//#define SK_SUPPORT_LEGACY_GETTOPDEVICE
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000029
reed@android.com8a1c16f2008-12-17 15:59:43 +000030class SkBounder;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000031class SkBaseDevice;
reed@android.com8a1c16f2008-12-17 15:59:43 +000032class SkDraw;
33class SkDrawFilter;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000034class SkMetaData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000035class SkPicture;
reed@google.com4ed0fb72012-12-12 20:48:18 +000036class SkRRect;
reed@google.com76f10a32014-02-05 15:32:21 +000037class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000038class SkSurface_Base;
commit-bot@chromium.org644629c2013-11-21 06:21:58 +000039class GrContext;
reed@google.com9c135db2014-03-12 18:28:35 +000040class GrRenderTarget;
reed@android.com8a1c16f2008-12-17 15:59:43 +000041
42/** \class SkCanvas
43
44 A Canvas encapsulates all of the state about drawing into a device (bitmap).
45 This includes a reference to the device itself, and a stack of matrix/clip
46 values. For any given draw call (e.g. drawRect), the geometry of the object
47 being drawn is transformed by the concatenation of all the matrices in the
48 stack. The transformed geometry is clipped by the intersection of all of
49 the clips in the stack.
50
51 While the Canvas holds the state of the drawing device, the state (style)
52 of the object being drawn is held by the Paint, which is provided as a
53 parameter to each of the draw() methods. The Paint holds attributes such as
54 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
55 etc.
56*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000057class SK_API SkCanvas : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000058public:
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000059 SK_DECLARE_INST_COUNT(SkCanvas)
60
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000061 /**
commit-bot@chromium.org3107b6a2014-02-27 20:32:51 +000062 * Attempt to allocate an offscreen raster canvas, matching the ImageInfo.
63 * On success, return a new canvas that will draw into that offscreen.
64 *
65 * The caller can access the pixels after drawing into this canvas by
66 * calling readPixels() or peekPixels().
67 *
68 * If the requested ImageInfo is opaque (either the colortype is
69 * intrinsically opaque like RGB_565, or the info's alphatype is kOpaque)
70 * then the pixel memory may be uninitialized. Otherwise, the pixel memory
71 * will be initialized to 0, which is interpreted as transparent.
72 *
73 * On failure, return NULL. This can fail for several reasons:
74 * 1. the memory allocation failed (e.g. request is too large)
75 * 2. invalid ImageInfo (e.g. negative dimensions)
76 * 3. unsupported ImageInfo for a canvas
77 * - kUnknown_SkColorType, kIndex_8_SkColorType
78 * - kIgnore_SkAlphaType
79 * - this list is not complete, so others may also be unsupported
80 *
81 * Note: it is valid to request a supported ImageInfo, but with zero
82 * dimensions.
83 */
84 static SkCanvas* NewRaster(const SkImageInfo&);
85
86 static SkCanvas* NewRasterN32(int width, int height) {
87 return NewRaster(SkImageInfo::MakeN32Premul(width, height));
88 }
89
90 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000091 * Creates an empty canvas with no backing device/pixels, and zero
92 * dimensions.
93 */
reed@google.comcde92112011-07-06 20:00:52 +000094 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000095
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000096 /**
97 * Creates a canvas of the specified dimensions, but explicitly not backed
98 * by any device/pixels. Typically this use used by subclasses who handle
99 * the draw calls in some other way.
100 */
101 SkCanvas(int width, int height);
102
reed@google.com6dc74552011-07-21 18:00:46 +0000103 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000104
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000105 @param device Specifies a device for the canvas to draw into.
106 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000107 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000108
reed@google.com44699382013-10-31 17:28:30 +0000109 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000110 @param bitmap Specifies a bitmap for the canvas to draw into. Its
111 structure are copied to the canvas.
112 */
113 explicit SkCanvas(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114 virtual ~SkCanvas();
115
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000116 SkMetaData& getMetaData();
117
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000118 /**
119 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
120 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
121 */
122 SkImageInfo imageInfo() const;
123
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 ///////////////////////////////////////////////////////////////////////////
125
reed@google.com210ce002011-11-01 14:24:23 +0000126 /**
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000127 * Trigger the immediate execution of all pending draw operations.
128 */
129 void flush();
130
131 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000132 * Gets the size of the base or root layer in global canvas coordinates. The
133 * origin of the base layer is always (0,0). The current drawable area may be
134 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000135 */
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000136 SkISize getBaseLayerSize() const;
137
138 /**
139 * DEPRECATED: call getBaseLayerSize
140 */
141 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000142
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000143 /**
144 * DEPRECATED.
145 * Return the canvas' device object, which may be null. The device holds
146 * the bitmap of the pixels that the canvas draws into. The reference count
147 * of the returned device is not changed by this call.
148 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000149 SkBaseDevice* getDevice() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150
reed@google.com9266fed2011-03-30 00:18:03 +0000151 /**
152 * saveLayer() can create another device (which is later drawn onto
153 * the previous device). getTopDevice() returns the top-most device current
154 * installed. Note that this can change on other calls like save/restore,
155 * so do not access this device after subsequent canvas calls.
156 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000157 *
158 * @param updateMatrixClip If this is true, then before the device is
159 * returned, we ensure that its has been notified about the current
160 * matrix and clip. Note: this happens automatically when the device
161 * is drawn to, but is optional here, as there is a small perf hit
162 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000163 */
reed@google.com9c135db2014-03-12 18:28:35 +0000164#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
165private:
166#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000167 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000168public:
reed@google.com9266fed2011-03-30 00:18:03 +0000169
reed@google.com76f10a32014-02-05 15:32:21 +0000170 /**
171 * Create a new surface matching the specified info, one that attempts to
172 * be maximally compatible when used with this canvas.
173 */
174 SkSurface* newSurface(const SkImageInfo&);
bsalomon@google.come97f0852011-06-17 13:10:25 +0000175
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000176 /**
177 * Return the GPU context of the device that is associated with the canvas.
178 * For a canvas with non-GPU device, NULL is returned.
179 */
180 GrContext* getGrContext();
181
reed@google.com4b226022011-01-11 18:32:13 +0000182 ///////////////////////////////////////////////////////////////////////////
183
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000184 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000185 * If the canvas has writable pixels in its top layer (and is not recording to a picture
186 * or other non-raster target) and has direct access to its pixels (i.e. they are in
187 * local RAM) return the address of those pixels, and if not null,
188 * return the ImageInfo and rowBytes. The returned address is only valid
189 * while the canvas object is in scope and unchanged. Any API calls made on
190 * canvas (or its parent surface if any) will invalidate the
191 * returned address (and associated information).
192 *
193 * On failure, returns NULL and the info and rowBytes parameters are
194 * ignored.
195 */
196 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes);
197
198 /**
199 * If the canvas has readable pixels in its base layer (and is not recording to a picture
200 * or other non-raster target) and has direct access to its pixels (i.e. they are in
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000201 * local RAM) return the const-address of those pixels, and if not null,
202 * return the ImageInfo and rowBytes. The returned address is only valid
203 * while the canvas object is in scope and unchanged. Any API calls made on
204 * canvas (or its parent surface if any) will invalidate the
205 * returned address (and associated information).
206 *
207 * On failure, returns NULL and the info and rowBytes parameters are
208 * ignored.
209 */
210 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
211
212 /**
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000213 * This enum can be used with read/writePixels to perform a pixel ops to or
214 * from an 8888 config other than Skia's native config (SkPMColor). There
215 * are three byte orders supported: native, BGRA, and RGBA. Each has a
216 * premultiplied and unpremultiplied variant.
217 *
218 * Components of a 8888 pixel can be packed/unpacked from a 32bit word using
219 * either byte offsets or shift values. Byte offsets are endian-invariant
220 * while shifts are not. BGRA and RGBA configs are defined by byte
221 * orderings. The native config is defined by shift values (SK_A32_SHIFT,
222 * ..., SK_B32_SHIFT).
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000223 */
224 enum Config8888 {
225 /**
226 * Skia's native order specified by:
227 * SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
228 *
229 * kNative_Premul_Config8888 is equivalent to SkPMColor
230 * kNative_Unpremul_Config8888 has the same component order as SkPMColor
231 * but is not premultiplied.
232 */
233 kNative_Premul_Config8888,
234 kNative_Unpremul_Config8888,
235 /**
236 * low byte to high byte: B, G, R, A.
237 */
238 kBGRA_Premul_Config8888,
239 kBGRA_Unpremul_Config8888,
240 /**
241 * low byte to high byte: R, G, B, A.
242 */
243 kRGBA_Premul_Config8888,
tomhudson@google.com1f902872012-06-01 13:15:47 +0000244 kRGBA_Unpremul_Config8888
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000245 };
246
247 /**
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000248 * On success (returns true), copy the canvas pixels into the bitmap.
249 * On failure, the bitmap parameter is left unchanged and false is
250 * returned.
251 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000252 * The canvas' pixels are converted to the bitmap's config. The only
253 * supported config is kARGB_8888_Config, though this is likely to be
254 * relaxed in the future. The meaning of config kARGB_8888_Config is
255 * modified by the enum param config8888. The default value interprets
256 * kARGB_8888_Config as SkPMColor
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000257 *
258 * If the bitmap has pixels already allocated, the canvas pixels will be
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000259 * written there. If not, bitmap->allocPixels() will be called
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000260 * automatically. If the bitmap is backed by a texture readPixels will
261 * fail.
262 *
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000263 * The actual pixels written is the intersection of the canvas' bounds, and
264 * the rectangle formed by the bitmap's width,height and the specified x,y.
265 * If bitmap pixels extend outside of that intersection, they will not be
266 * modified.
267 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000268 * Other failure conditions:
269 * * If the canvas is backed by a non-raster device (e.g. PDF) then
270 * readPixels will fail.
271 * * If bitmap is texture-backed then readPixels will fail. (This may be
272 * relaxed in the future.)
273 *
274 * Example that reads the entire canvas into a bitmap using the native
275 * SkPMColor:
276 * SkISize size = canvas->getDeviceSize();
277 * bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
278 * size.fHeight);
279 * if (canvas->readPixels(bitmap, 0, 0)) {
280 * // use the pixels
281 * }
bsalomon@google.comc6980972011-11-02 19:57:21 +0000282 */
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000283 bool readPixels(SkBitmap* bitmap,
284 int x, int y,
285 Config8888 config8888 = kNative_Premul_Config8888);
bsalomon@google.comc6980972011-11-02 19:57:21 +0000286
reed@google.com4b226022011-01-11 18:32:13 +0000287 /**
bsalomon@google.comc6980972011-11-02 19:57:21 +0000288 * DEPRECATED: This will be removed as soon as webkit is no longer relying
289 * on it. The bitmap is resized to the intersection of srcRect and the
290 * canvas bounds. New pixels are always allocated on success. Bitmap is
291 * unmodified on failure.
reed@google.com51df9e32010-12-23 19:29:18 +0000292 */
293 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000294
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000295#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
reed@google.com51df9e32010-12-23 19:29:18 +0000296 /**
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000297 * DEPRECATED
reed@google.com51df9e32010-12-23 19:29:18 +0000298 * Similar to draw sprite, this method will copy the pixels in bitmap onto
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000299 * the canvas, with the top/left corner specified by (x, y). The canvas'
300 * pixel values are completely replaced: there is no blending.
301 *
302 * Currently if bitmap is backed by a texture this is a no-op. This may be
303 * relaxed in the future.
304 *
305 * If the bitmap has config kARGB_8888_Config then the config8888 param
306 * will determines how the pixel valuess are intepreted. If the bitmap is
307 * not kARGB_8888_Config then this parameter is ignored.
epoger@google.com4f1151a2011-07-25 15:47:33 +0000308 *
309 * Note: If you are recording drawing commands on this canvas to
310 * SkPicture, writePixels() is ignored!
reed@google.com51df9e32010-12-23 19:29:18 +0000311 */
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000312 void writePixels(const SkBitmap& bitmap, int x, int y, Config8888 config8888);
313#endif
314
315 /**
316 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
317 * ignoring the matrix and clip.
318 *
319 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
320 *
321 * target.setXYWH(x, y, info.width(), info.height());
322 *
323 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
324 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
325 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
326 * pixels, performing any colortype/alphatype transformations needed (in the case where the
327 * src and dst have different colortypes or alphatypes).
328 *
329 * This call can fail, returning false, for several reasons:
330 * - If the src colortype/alphatype cannot be converted to the canvas' types
331 * - If this canvas is not backed by pixels (e.g. picture or PDF)
332 */
333 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
334
335 /**
336 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
337 * is just wrapping a texture, returns false and does nothing.
338 */
339 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000340
reed@android.com8a1c16f2008-12-17 15:59:43 +0000341 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000342
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343 enum SaveFlags {
344 /** save the matrix state, restoring it on restore() */
345 kMatrix_SaveFlag = 0x01,
346 /** save the clip state, restoring it on restore() */
347 kClip_SaveFlag = 0x02,
348 /** the layer needs to support per-pixel alpha */
349 kHasAlphaLayer_SaveFlag = 0x04,
350 /** the layer needs to support 8-bits per color component */
351 kFullColorLayer_SaveFlag = 0x08,
reed@google.comb93ba452014-03-10 19:47:58 +0000352 /**
353 * the layer should clip against the bounds argument
354 *
355 * if SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG is undefined, this is treated as always on.
356 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000357 kClipToLayer_SaveFlag = 0x10,
358
359 // helper masks for common choices
360 kMatrixClip_SaveFlag = 0x03,
reed@google.comb93ba452014-03-10 19:47:58 +0000361#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
reed@android.com8a1c16f2008-12-17 15:59:43 +0000362 kARGB_NoClipLayer_SaveFlag = 0x0F,
reed@google.comb93ba452014-03-10 19:47:58 +0000363#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364 kARGB_ClipLayer_SaveFlag = 0x1F
365 };
366
reed@android.comdc3381f2010-02-11 16:05:15 +0000367 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000368 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000369 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
370 operate on this copy.
371 When the balancing call to restore() is made, the previous matrix, clip,
372 and drawFilter are restored.
djsollen@google.comd4236572013-08-13 14:29:06 +0000373 @param flags The flags govern what portion of the Matrix/Clip/drawFilter
374 state the save (and matching restore) effect. For example,
375 if only kMatrix is specified, then only the matrix state
376 will be pushed and popped. Likewise for the clip if kClip
377 is specified. However, the drawFilter is always affected
378 by calls to save/restore.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000379 @return The value to pass to restoreToCount() to balance this save()
380 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000381 int save(SaveFlags flags = kMatrixClip_SaveFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000382
383 /** This behaves the same as save(), but in addition it allocates an
384 offscreen bitmap. All drawing calls are directed there, and only when
385 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000386 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000387 @param bounds (may be null) This rect, if non-null, is used as a hint to
388 limit the size of the offscreen, and thus drawing may be
389 clipped to it, though that clipping is not guaranteed to
390 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000391 @param paint (may be null) This is copied, and is applied to the
392 offscreen when restore() is called
393 @param flags LayerFlags
394 @return The value to pass to restoreToCount() to balance this save()
395 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000396 int saveLayer(const SkRect* bounds, const SkPaint* paint,
397 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398
399 /** This behaves the same as save(), but in addition it allocates an
400 offscreen bitmap. All drawing calls are directed there, and only when
401 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000402 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000403 @param bounds (may be null) This rect, if non-null, is used as a hint to
404 limit the size of the offscreen, and thus drawing may be
405 clipped to it, though that clipping is not guaranteed to
406 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000407 @param alpha This is applied to the offscreen when restore() is called.
408 @param flags LayerFlags
409 @return The value to pass to restoreToCount() to balance this save()
410 */
411 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
412 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
413
414 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000415 modifications to the matrix/clip/drawFilter state since the last save
416 call.
417 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000419 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420
421 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000422 This will equal # save() calls - # restore() calls + 1. The save count on
423 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000425 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000426
427 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000428 count reached saveCount. It is an error for saveCount to be greater than
429 getSaveCount(). To pop all the way back to the initial matrix/clip context
430 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 @param saveCount The number of save() levels to restore from
432 */
433 void restoreToCount(int saveCount);
434
reed@google.com7c202932011-12-14 18:48:05 +0000435 /** Returns true if drawing is currently going to a layer (from saveLayer)
436 * rather than to the root device.
437 */
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000438 virtual bool isDrawingToLayer() const;
reed@google.com7c202932011-12-14 18:48:05 +0000439
reed@android.com8a1c16f2008-12-17 15:59:43 +0000440 /** Preconcat the current matrix with the specified translation
441 @param dx The distance to translate in X
442 @param dy The distance to translate in Y
443 returns true if the operation succeeded (e.g. did not overflow)
444 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000445 bool translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000446
447 /** Preconcat the current matrix with the specified scale.
448 @param sx The amount to scale in X
449 @param sy The amount to scale in Y
450 returns true if the operation succeeded (e.g. did not overflow)
451 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000452 bool scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000453
454 /** Preconcat the current matrix with the specified rotation.
455 @param degrees The amount to rotate, in degrees
456 returns true if the operation succeeded (e.g. did not overflow)
457 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000458 bool rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000459
460 /** Preconcat the current matrix with the specified skew.
461 @param sx The amount to skew in X
462 @param sy The amount to skew in Y
463 returns true if the operation succeeded (e.g. did not overflow)
464 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000465 bool skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000466
467 /** Preconcat the current matrix with the specified matrix.
468 @param matrix The matrix to preconcatenate with the current matrix
469 @return true if the operation succeeded (e.g. did not overflow)
470 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000471 bool concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000472
reed@android.com8a1c16f2008-12-17 15:59:43 +0000473 /** Replace the current matrix with a copy of the specified matrix.
474 @param matrix The matrix that will be copied into the current matrix.
475 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000476 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000477
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478 /** Helper for setMatrix(identity). Sets the current matrix to identity.
479 */
480 void resetMatrix();
481
reed@google.com4ed0fb72012-12-12 20:48:18 +0000482 /**
483 * Modify the current clip with the specified rectangle.
484 * @param rect The rect to combine with the current clip
485 * @param op The region op to apply to the current clip
486 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000487 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000488 void clipRect(const SkRect& rect,
489 SkRegion::Op op = SkRegion::kIntersect_Op,
490 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000491
reed@google.com4ed0fb72012-12-12 20:48:18 +0000492 /**
493 * Modify the current clip with the specified SkRRect.
494 * @param rrect The rrect to combine with the current clip
495 * @param op The region op to apply to the current clip
496 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000497 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000498 void clipRRect(const SkRRect& rrect,
499 SkRegion::Op op = SkRegion::kIntersect_Op,
500 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000501
502 /**
503 * Modify the current clip with the specified path.
504 * @param path The path to combine with the current clip
505 * @param op The region op to apply to the current clip
506 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000507 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000508 void clipPath(const SkPath& path,
509 SkRegion::Op op = SkRegion::kIntersect_Op,
510 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000511
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000512 /** EXPERIMENTAL -- only used for testing
513 Set to false to force clips to be hard, even if doAntiAlias=true is
514 passed to clipRect or clipPath.
515 */
516 void setAllowSoftClip(bool allow) {
517 fAllowSoftClip = allow;
518 }
519
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000520 /** EXPERIMENTAL -- only used for testing
521 Set to simplify clip stack using path ops.
522 */
523 void setAllowSimplifyClip(bool allow) {
524 fAllowSimplifyClip = allow;
525 }
526
reed@android.com8a1c16f2008-12-17 15:59:43 +0000527 /** Modify the current clip with the specified region. Note that unlike
528 clipRect() and clipPath() which transform their arguments by the current
529 matrix, clipRegion() assumes its argument is already in device
530 coordinates, and so no transformation is performed.
531 @param deviceRgn The region to apply to the current clip
532 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000533 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000534 void clipRegion(const SkRegion& deviceRgn,
535 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000536
537 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
538 specified region. This does not intersect or in any other way account
539 for the existing clip region.
540 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000541 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000542 void setClipRegion(const SkRegion& deviceRgn) {
543 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000544 }
545
reed@android.com8a1c16f2008-12-17 15:59:43 +0000546 /** Return true if the specified rectangle, after being transformed by the
547 current matrix, would lie completely outside of the current clip. Call
548 this to check if an area you intend to draw into is clipped out (and
549 therefore you can skip making the draw calls).
550 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000551 @return true if the rect (transformed by the canvas' matrix) does not
552 intersect with the canvas' clip
553 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000554 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555
556 /** Return true if the specified path, after being transformed by the
557 current matrix, would lie completely outside of the current clip. Call
558 this to check if an area you intend to draw into is clipped out (and
559 therefore you can skip making the draw calls). Note, for speed it may
560 return false even if the path itself might not intersect the clip
561 (i.e. the bounds of the path intersects, but the path does not).
562 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000563 @return true if the path (transformed by the canvas' matrix) does not
564 intersect with the canvas' clip
565 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000566 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000567
568 /** Return true if the horizontal band specified by top and bottom is
569 completely clipped out. This is a conservative calculation, meaning
570 that it is possible that if the method returns false, the band may still
571 in fact be clipped out, but the converse is not true. If this method
572 returns true, then the band is guaranteed to be clipped out.
573 @param top The top of the horizontal band to compare with the clip
574 @param bottom The bottom of the horizontal and to compare with the clip
575 @return true if the horizontal band is completely clipped out (i.e. does
576 not intersect the current clip)
577 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000578 bool quickRejectY(SkScalar top, SkScalar bottom) const {
reed@google.comc0784db2013-12-13 21:16:12 +0000579 SkASSERT(top <= bottom);
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000580
581#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
582 // TODO: add a hasPerspective method similar to getLocalClipBounds. This
583 // would cache the SkMatrix::hasPerspective result. Alternatively, have
584 // the MC stack just set a hasPerspective boolean as it is updated.
585 if (this->getTotalMatrix().hasPerspective()) {
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000586 // TODO: consider implementing some half-plane test between the
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000587 // two Y planes and the device-bounds (i.e., project the top and
588 // bottom Y planes and then determine if the clip bounds is completely
589 // outside either one).
590 return false;
591 }
592#endif
593
reed@google.comc0784db2013-12-13 21:16:12 +0000594 const SkRect& clipR = this->getLocalClipBounds();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000595 // In the case where the clip is empty and we are provided with a
596 // negative top and positive bottom parameter then this test will return
597 // false even though it will be clipped. We have chosen to exclude that
598 // check as it is rare and would result double the comparisons.
reed@google.comc0784db2013-12-13 21:16:12 +0000599 return top >= clipR.fBottom || bottom <= clipR.fTop;
djsollen@google.com92d2a292012-02-27 16:17:59 +0000600 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000601
602 /** Return the bounds of the current clip (in local coordinates) in the
603 bounds parameter, and return true if it is non-empty. This can be useful
604 in a way similar to quickReject, in that it tells you that drawing
605 outside of these bounds will be clipped out.
606 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000607 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000608
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000609 /** Return the bounds of the current clip, in device coordinates; returns
610 true if non-empty. Maybe faster than getting the clip explicitly and
611 then taking its bounds.
612 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000613 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000614
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000615
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000617 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000618 @param a the alpha component (0..255) of the color to fill the canvas
619 @param r the red component (0..255) of the color to fill the canvas
620 @param g the green component (0..255) of the color to fill the canvas
621 @param b the blue component (0..255) of the color to fill the canvas
622 @param mode the mode to apply the color in (defaults to SrcOver)
623 */
624 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000625 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000626
627 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000628 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000629 @param color the color to draw with
630 @param mode the mode to apply the color in (defaults to SrcOver)
631 */
632 void drawColor(SkColor color,
reed@android.com845fdac2009-06-23 03:01:32 +0000633 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000634
reed@google.com2a981812011-04-14 18:59:28 +0000635 /**
636 * This erases the entire drawing surface to the specified color,
637 * irrespective of the clip. It does not blend with the previous pixels,
638 * but always overwrites them.
639 *
640 * It is roughly equivalent to the following:
641 * canvas.save();
642 * canvas.clipRect(hugeRect, kReplace_Op);
643 * paint.setColor(color);
644 * paint.setXfermodeMode(kSrc_Mode);
645 * canvas.drawPaint(paint);
646 * canvas.restore();
647 * though it is almost always much more efficient.
648 */
649 virtual void clear(SkColor);
650
651 /**
652 * Fill the entire canvas' bitmap (restricted to the current clip) with the
653 * specified paint.
654 * @param paint The paint used to fill the canvas
655 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000656 virtual void drawPaint(const SkPaint& paint);
657
658 enum PointMode {
659 /** drawPoints draws each point separately */
660 kPoints_PointMode,
661 /** drawPoints draws each pair of points as a line segment */
662 kLines_PointMode,
663 /** drawPoints draws the array of points as a polygon */
664 kPolygon_PointMode
665 };
666
667 /** Draw a series of points, interpreted based on the PointMode mode. For
668 all modes, the count parameter is interpreted as the total number of
669 points. For kLine mode, count/2 line segments are drawn.
670 For kPoint mode, each point is drawn centered at its coordinate, and its
671 size is specified by the paint's stroke-width. It draws as a square,
672 unless the paint's cap-type is round, in which the points are drawn as
673 circles.
674 For kLine mode, each pair of points is drawn as a line segment,
675 respecting the paint's settings for cap/join/width.
676 For kPolygon mode, the entire array is drawn as a series of connected
677 line segments.
678 Note that, while similar, kLine and kPolygon modes draw slightly
679 differently than the equivalent path built with a series of moveto,
680 lineto calls, in that the path will draw all of its contours at once,
681 with no interactions if contours intersect each other (think XOR
682 xfermode). drawPoints always draws each element one at a time.
683 @param mode PointMode specifying how to draw the array of points.
684 @param count The number of points in the array
685 @param pts Array of points to draw
686 @param paint The paint used to draw the points
687 */
688 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
689 const SkPaint& paint);
690
691 /** Helper method for drawing a single point. See drawPoints() for a more
692 details.
693 */
694 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000695
reed@android.com8a1c16f2008-12-17 15:59:43 +0000696 /** Draws a single pixel in the specified color.
697 @param x The X coordinate of which pixel to draw
698 @param y The Y coordiante of which pixel to draw
699 @param color The color to draw
700 */
701 void drawPoint(SkScalar x, SkScalar y, SkColor color);
702
703 /** Draw a line segment with the specified start and stop x,y coordinates,
704 using the specified paint. NOTE: since a line is always "framed", the
705 paint's Style is ignored.
706 @param x0 The x-coordinate of the start point of the line
707 @param y0 The y-coordinate of the start point of the line
708 @param x1 The x-coordinate of the end point of the line
709 @param y1 The y-coordinate of the end point of the line
710 @param paint The paint used to draw the line
711 */
712 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
713 const SkPaint& paint);
714
715 /** Draw the specified rectangle using the specified paint. The rectangle
716 will be filled or stroked based on the Style in the paint.
717 @param rect The rect to be drawn
718 @param paint The paint used to draw the rect
719 */
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000720 virtual void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000721
722 /** Draw the specified rectangle using the specified paint. The rectangle
723 will be filled or framed based on the Style in the paint.
724 @param rect The rect to be drawn
725 @param paint The paint used to draw the rect
726 */
reed@google.com87001ed2014-02-17 16:28:05 +0000727 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728 SkRect r;
729 r.set(rect); // promotes the ints to scalars
730 this->drawRect(r, paint);
731 }
reed@google.com4b226022011-01-11 18:32:13 +0000732
reed@android.com8a1c16f2008-12-17 15:59:43 +0000733 /** Draw the specified rectangle using the specified paint. The rectangle
734 will be filled or framed based on the Style in the paint.
735 @param left The left side of the rectangle to be drawn
736 @param top The top side of the rectangle to be drawn
737 @param right The right side of the rectangle to be drawn
738 @param bottom The bottom side of the rectangle to be drawn
739 @param paint The paint used to draw the rect
740 */
741 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
742 SkScalar bottom, const SkPaint& paint);
743
744 /** Draw the specified oval using the specified paint. The oval will be
745 filled or framed based on the Style in the paint.
746 @param oval The rectangle bounds of the oval to be drawn
747 @param paint The paint used to draw the oval
748 */
reed@google.com4ed0fb72012-12-12 20:48:18 +0000749 virtual void drawOval(const SkRect& oval, const SkPaint&);
750
751 /**
752 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
753 * based on the Style in the paint.
754 *
755 * @param rrect The round-rect to draw
756 * @param paint The paint used to draw the round-rect
757 */
758 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000759
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000760 /**
761 * Draw the annulus formed by the outer and inner rrects. The results
762 * are undefined if the outer does not contain the inner.
763 */
764 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
765
reed@android.com8a1c16f2008-12-17 15:59:43 +0000766 /** Draw the specified circle using the specified paint. If radius is <= 0,
767 then nothing will be drawn. The circle will be filled
768 or framed based on the Style in the paint.
769 @param cx The x-coordinate of the center of the cirle to be drawn
770 @param cy The y-coordinate of the center of the cirle to be drawn
771 @param radius The radius of the cirle to be drawn
772 @param paint The paint used to draw the circle
773 */
774 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
775 const SkPaint& paint);
776
777 /** Draw the specified arc, which will be scaled to fit inside the
778 specified oval. If the sweep angle is >= 360, then the oval is drawn
779 completely. Note that this differs slightly from SkPath::arcTo, which
780 treats the sweep angle mod 360.
781 @param oval The bounds of oval used to define the shape of the arc
782 @param startAngle Starting angle (in degrees) where the arc begins
783 @param sweepAngle Sweep angle (in degrees) measured clockwise
784 @param useCenter true means include the center of the oval. For filling
785 this will draw a wedge. False means just use the arc.
786 @param paint The paint used to draw the arc
787 */
788 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
789 bool useCenter, const SkPaint& paint);
790
791 /** Draw the specified round-rect using the specified paint. The round-rect
792 will be filled or framed based on the Style in the paint.
793 @param rect The rectangular bounds of the roundRect to be drawn
794 @param rx The x-radius of the oval used to round the corners
795 @param ry The y-radius of the oval used to round the corners
796 @param paint The paint used to draw the roundRect
797 */
798 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
799 const SkPaint& paint);
800
801 /** Draw the specified path using the specified paint. The path will be
802 filled or framed based on the Style in the paint.
803 @param path The path to be drawn
804 @param paint The paint used to draw the path
805 */
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000806 virtual void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000807
808 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
809 specified paint, transformed by the current matrix. Note: if the paint
810 contains a maskfilter that generates a mask which extends beyond the
811 bitmap's original width/height, then the bitmap will be drawn as if it
812 were in a Shader with CLAMP mode. Thus the color outside of the original
813 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000814
815 If a shader is present on the paint it will be ignored, except in the
816 case where the bitmap is kA8_Config. In that case, the color is
817 generated by the shader.
818
reed@android.com8a1c16f2008-12-17 15:59:43 +0000819 @param bitmap The bitmap to be drawn
820 @param left The position of the left side of the bitmap being drawn
821 @param top The position of the top side of the bitmap being drawn
822 @param paint The paint used to draw the bitmap, or NULL
823 */
824 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
825 const SkPaint* paint = NULL);
826
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000827 enum DrawBitmapRectFlags {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000828 kNone_DrawBitmapRectFlag = 0x0,
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000829 /**
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000830 * When filtering is enabled, allow the color samples outside of
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000831 * the src rect (but still in the src bitmap) to bleed into the
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000832 * drawn portion
833 */
robertphillips@google.com31acc112013-08-20 12:13:48 +0000834 kBleed_DrawBitmapRectFlag = 0x1,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000835 };
836
reed@android.com8a1c16f2008-12-17 15:59:43 +0000837 /** Draw the specified bitmap, with the specified matrix applied (before the
838 canvas' matrix is applied).
839 @param bitmap The bitmap to be drawn
840 @param src Optional: specify the subset of the bitmap to be drawn
841 @param dst The destination rectangle where the scaled/translated
842 image will be drawn
843 @param paint The paint used to draw the bitmap, or NULL
844 */
reed@google.com71121732012-09-18 15:14:33 +0000845 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
846 const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000847 const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000848 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000849
reed@google.com71121732012-09-18 15:14:33 +0000850 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000851 const SkPaint* paint = NULL) {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000852 this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag);
reed@google.com71121732012-09-18 15:14:33 +0000853 }
854
855 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000856 const SkRect& dst, const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000857 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
reed@google.com71121732012-09-18 15:14:33 +0000858 SkRect realSrcStorage;
859 SkRect* realSrcPtr = NULL;
860 if (isrc) {
861 realSrcStorage.set(*isrc);
862 realSrcPtr = &realSrcStorage;
863 }
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000864 this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
reed@google.com71121732012-09-18 15:14:33 +0000865 }
skia.committer@gmail.comc1ad0222012-09-19 02:01:47 +0000866
reed@android.com8a1c16f2008-12-17 15:59:43 +0000867 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
868 const SkPaint* paint = NULL);
reed@google.com4b226022011-01-11 18:32:13 +0000869
reed@google.comf0b5e112011-09-07 11:57:34 +0000870 /**
871 * Draw the bitmap stretched differentially to fit into dst.
872 * center is a rect within the bitmap, and logically divides the bitmap
873 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
874 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
875 *
876 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000877 * - The 4 corners are not stretched at all.
878 * - The sides are stretched in only one axis.
879 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000880 * Else, for each axis where dst < bitmap,
881 * - The corners shrink proportionally
882 * - The sides (along the shrink axis) and center are not drawn
883 */
884 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
885 const SkRect& dst, const SkPaint* paint = NULL);
886
reed@android.com8a1c16f2008-12-17 15:59:43 +0000887 /** Draw the specified bitmap, with its top/left corner at (x,y),
888 NOT transformed by the current matrix. Note: if the paint
889 contains a maskfilter that generates a mask which extends beyond the
890 bitmap's original width/height, then the bitmap will be drawn as if it
891 were in a Shader with CLAMP mode. Thus the color outside of the original
892 width/height will be the edge color replicated.
893 @param bitmap The bitmap to be drawn
894 @param left The position of the left side of the bitmap being drawn
895 @param top The position of the top side of the bitmap being drawn
896 @param paint The paint used to draw the bitmap, or NULL
897 */
898 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
899 const SkPaint* paint = NULL);
900
901 /** Draw the text, with origin at (x,y), using the specified paint.
902 The origin is interpreted based on the Align setting in the paint.
903 @param text The text to be drawn
904 @param byteLength The number of bytes to read from the text parameter
905 @param x The x-coordinate of the origin of the text being drawn
906 @param y The y-coordinate of the origin of the text being drawn
907 @param paint The paint used for the text (e.g. color, size, style)
908 */
909 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
910 SkScalar y, const SkPaint& paint);
911
912 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000913 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000914 @param text The text to be drawn
915 @param byteLength The number of bytes to read from the text parameter
916 @param pos Array of positions, used to position each character
917 @param paint The paint used for the text (e.g. color, size, style)
918 */
919 virtual void drawPosText(const void* text, size_t byteLength,
920 const SkPoint pos[], const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000921
reed@android.com8a1c16f2008-12-17 15:59:43 +0000922 /** Draw the text, with each character/glyph origin specified by the x
923 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000924 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925 @param text The text to be drawn
926 @param byteLength The number of bytes to read from the text parameter
927 @param xpos Array of x-positions, used to position each character
928 @param constY The shared Y coordinate for all of the positions
929 @param paint The paint used for the text (e.g. color, size, style)
930 */
931 virtual void drawPosTextH(const void* text, size_t byteLength,
932 const SkScalar xpos[], SkScalar constY,
933 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000934
reed@android.com8a1c16f2008-12-17 15:59:43 +0000935 /** Draw the text, with origin at (x,y), using the specified paint, along
936 the specified path. The paint's Align setting determins where along the
937 path to start the text.
938 @param text The text to be drawn
939 @param byteLength The number of bytes to read from the text parameter
940 @param path The path the text should follow for its baseline
941 @param hOffset The distance along the path to add to the text's
942 starting position
943 @param vOffset The distance above(-) or below(+) the path to
944 position the text
945 @param paint The paint used for the text
946 */
947 void drawTextOnPathHV(const void* text, size_t byteLength,
948 const SkPath& path, SkScalar hOffset,
949 SkScalar vOffset, const SkPaint& paint);
950
951 /** Draw the text, with origin at (x,y), using the specified paint, along
952 the specified path. The paint's Align setting determins where along the
953 path to start the text.
954 @param text The text to be drawn
955 @param byteLength The number of bytes to read from the text parameter
956 @param path The path the text should follow for its baseline
957 @param matrix (may be null) Applied to the text before it is
958 mapped onto the path
959 @param paint The paint used for the text
960 */
961 virtual void drawTextOnPath(const void* text, size_t byteLength,
962 const SkPath& path, const SkMatrix* matrix,
963 const SkPaint& paint);
964
commit-bot@chromium.org145d1c02014-03-16 19:46:36 +0000965 /** PRIVATE / EXPERIMENTAL -- do not call
966 Perform back-end analysis/optimization of a picture. This may attach
967 optimization data to the picture which can be used by a later
968 drawPicture call.
969 @param picture The recorded drawing commands to analyze/optimize
970 */
971 void EXPERIMENTAL_optimize(SkPicture* picture);
972
reed@android.com8a1c16f2008-12-17 15:59:43 +0000973 /** Draw the picture into this canvas. This method effective brackets the
974 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +0000975 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976 @param picture The recorded drawing commands to playback into this
977 canvas.
978 */
979 virtual void drawPicture(SkPicture& picture);
reed@google.com4b226022011-01-11 18:32:13 +0000980
reed@android.com8a1c16f2008-12-17 15:59:43 +0000981 enum VertexMode {
982 kTriangles_VertexMode,
983 kTriangleStrip_VertexMode,
984 kTriangleFan_VertexMode
985 };
reed@google.com4b226022011-01-11 18:32:13 +0000986
reed@android.com8a1c16f2008-12-17 15:59:43 +0000987 /** Draw the array of vertices, interpreted as triangles (based on mode).
988 @param vmode How to interpret the array of vertices
989 @param vertexCount The number of points in the vertices array (and
990 corresponding texs and colors arrays if non-null)
991 @param vertices Array of vertices for the mesh
992 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +0000993 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000994 @param colors May be null. If not null, specifies a color for each
995 vertex, to be interpolated across the triangle.
996 @param xmode Used if both texs and colors are present. In this
997 case the colors are combined with the texture using mode,
998 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +0000999 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000 @param indices If not null, array of indices to reference into the
1001 vertex (texs, colors) array.
1002 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001003 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001004 */
1005 virtual void drawVertices(VertexMode vmode, int vertexCount,
1006 const SkPoint vertices[], const SkPoint texs[],
1007 const SkColor colors[], SkXfermode* xmode,
1008 const uint16_t indices[], int indexCount,
1009 const SkPaint& paint);
1010
reed@android.comcb608442009-12-04 21:32:27 +00001011 /** Send a blob of data to the canvas.
1012 For canvases that draw, this call is effectively a no-op, as the data
1013 is not parsed, but just ignored. However, this call exists for
1014 subclasses like SkPicture's recording canvas, that can store the data
1015 and then play it back later (via another call to drawData).
1016 */
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001017 virtual void drawData(const void* data, size_t length) {
1018 // do nothing. Subclasses may do something with the data
1019 }
1020
skia.committer@gmail.coma5d3e772013-05-30 07:01:29 +00001021 /** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
1022 Each comment added via addComment is notionally attached to its
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001023 enclosing group. Top-level comments simply belong to no group.
1024 */
1025 virtual void beginCommentGroup(const char* description) {
1026 // do nothing. Subclasses may do something
1027 }
1028 virtual void addComment(const char* kywd, const char* value) {
1029 // do nothing. Subclasses may do something
1030 }
1031 virtual void endCommentGroup() {
1032 // do nothing. Subclasses may do something
1033 }
1034
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001035 /**
1036 * With this call the client asserts that subsequent draw operations (up to the
1037 * matching popCull()) are fully contained within the given bounding box. The assertion
1038 * is not enforced, but the information might be used to quick-reject command blocks,
1039 * so an incorrect bounding box may result in incomplete rendering.
1040 */
1041 void pushCull(const SkRect& cullRect) {
1042 ++fCullCount;
1043 this->onPushCull(cullRect);
1044 }
reed@android.comcb608442009-12-04 21:32:27 +00001045
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001046 /**
1047 * Terminates the current culling block, and restores the previous one (if any).
1048 */
1049 void popCull() {
1050 if (fCullCount > 0) {
1051 --fCullCount;
1052 this->onPopCull();
1053 }
1054 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001055 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +00001056
reed@android.com8a1c16f2008-12-17 15:59:43 +00001057 /** Get the current bounder object.
1058 The bounder's reference count is unchaged.
1059 @return the canva's bounder (or NULL).
1060 */
1061 SkBounder* getBounder() const { return fBounder; }
1062
1063 /** Set a new bounder (or NULL).
1064 Pass NULL to clear any previous bounder.
1065 As a convenience, the parameter passed is also returned.
1066 If a previous bounder exists, its reference count is decremented.
1067 If bounder is not NULL, its reference count is incremented.
1068 @param bounder the new bounder (or NULL) to be installed in the canvas
1069 @return the set bounder object
1070 */
1071 virtual SkBounder* setBounder(SkBounder* bounder);
reed@google.com4b226022011-01-11 18:32:13 +00001072
reed@android.com8a1c16f2008-12-17 15:59:43 +00001073 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001074 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001075 @return the canvas' filter (or NULL).
1076 */
1077 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001078
reed@android.com8a1c16f2008-12-17 15:59:43 +00001079 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1080 As a convenience, the parameter is returned. If an existing filter
1081 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001082 refcnt is incremented. The filter is saved/restored, just like the
1083 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001084 @param filter the new filter (or NULL)
1085 @return the new filter
1086 */
1087 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
1088
1089 //////////////////////////////////////////////////////////////////////////
1090
reed@google.com754de5f2014-02-24 19:38:20 +00001091 /**
1092 * Return true if the current clip is empty (i.e. nothing will draw).
1093 * Note: this is not always a free call, so it should not be used
1094 * more often than necessary. However, once the canvas has computed this
1095 * result, subsequent calls will be cheap (until the clip state changes,
1096 * which can happen on any clip..() or restore() call.
1097 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001098 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001099
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001100 /**
1101 * Returns true if the current clip is just a (non-empty) rectangle.
1102 * Returns false if the clip is empty, or if it is complex.
1103 */
1104 virtual bool isClipRect() const;
1105
reed@android.com8a1c16f2008-12-17 15:59:43 +00001106 /** Return the current matrix on the canvas.
1107 This does not account for the translate in any of the devices.
1108 @return The current matrix on the canvas.
1109 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001110 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001111
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001112#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
tomhudson@google.combcb671c2011-09-13 15:07:58 +00001113 enum ClipType {
1114 kEmpty_ClipType = 0,
1115 kRect_ClipType,
1116 kComplex_ClipType
1117 };
tomhudson@google.combcb671c2011-09-13 15:07:58 +00001118 /** Returns a description of the total clip; may be cheaper than
1119 getting the clip and querying it directly.
1120 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001121 virtual ClipType getClipType() const;
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001122#endif
tomhudson@google.combcb671c2011-09-13 15:07:58 +00001123
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001124#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
reed@google.com44699382013-10-31 17:28:30 +00001125 /** DEPRECATED -- need to move this guy to private/friend
1126 * Return the current device clip (concatenation of all clip calls).
reed@google.coma707f602012-04-12 16:12:16 +00001127 * This does not account for the translate in any of the devices.
1128 * @return the current device clip (concatenation of all clip calls).
reed@google.com5e2457e2011-10-10 21:24:37 +00001129 */
reed@google.coma707f602012-04-12 16:12:16 +00001130 const SkRegion& getTotalClip() const;
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001131#endif
reed@google.com5e2457e2011-10-10 21:24:37 +00001132
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001133 /** Return the clip stack. The clip stack stores all the individual
1134 * clips organized by the save/restore frame in which they were
1135 * added.
1136 * @return the current clip stack ("list" of individual clip elements)
1137 */
1138 const SkClipStack* getClipStack() const {
1139 return &fClipStack;
1140 }
1141
reed@google.com90c07ea2012-04-13 13:50:27 +00001142 class ClipVisitor {
1143 public:
justinlin@google.com20a550c2012-07-27 17:37:12 +00001144 virtual ~ClipVisitor();
reed@google.com90c07ea2012-04-13 13:50:27 +00001145 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +00001146 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
reed@google.com90c07ea2012-04-13 13:50:27 +00001147 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1148 };
1149
1150 /**
1151 * Replays the clip operations, back to front, that have been applied to
1152 * the canvas, calling the appropriate method on the visitor for each
1153 * clip. All clips have already been transformed into device space.
1154 */
1155 void replayClips(ClipVisitor*) const;
1156
reed@android.com8a1c16f2008-12-17 15:59:43 +00001157 ///////////////////////////////////////////////////////////////////////////
1158
1159 /** After calling saveLayer(), there can be any number of devices that make
1160 up the top-most drawing area. LayerIter can be used to iterate through
1161 those devices. Note that the iterator is only valid until the next API
1162 call made on the canvas. Ownership of all pointers in the iterator stays
1163 with the canvas, so none of them should be modified or deleted.
1164 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +00001165 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001166 public:
1167 /** Initialize iterator with canvas, and set values for 1st device */
1168 LayerIter(SkCanvas*, bool skipEmptyClips);
1169 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +00001170
reed@android.com8a1c16f2008-12-17 15:59:43 +00001171 /** Return true if the iterator is done */
1172 bool done() const { return fDone; }
1173 /** Cycle to the next device */
1174 void next();
reed@google.com4b226022011-01-11 18:32:13 +00001175
reed@android.com8a1c16f2008-12-17 15:59:43 +00001176 // These reflect the current device in the iterator
1177
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001178 SkBaseDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001179 const SkMatrix& matrix() const;
1180 const SkRegion& clip() const;
1181 const SkPaint& paint() const;
1182 int x() const;
1183 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001184
reed@android.com8a1c16f2008-12-17 15:59:43 +00001185 private:
1186 // used to embed the SkDrawIter object directly in our instance, w/o
1187 // having to expose that class def to the public. There is an assert
1188 // in our constructor to ensure that fStorage is large enough
1189 // (though needs to be a compile-time-assert!). We use intptr_t to work
1190 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001191 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001192 class SkDrawIter* fImpl; // this points at fStorage
1193 SkPaint fDefaultPaint;
1194 bool fDone;
1195 };
1196
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001197 // don't call
1198 const SkRegion& internal_private_getTotalClip() const;
1199 // don't call
1200 void internal_private_getTotalClipAsPath(SkPath*) const;
reed@google.com9c135db2014-03-12 18:28:35 +00001201 // don't call
1202 GrRenderTarget* internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001203
reed@android.com8a1c16f2008-12-17 15:59:43 +00001204protected:
reed@google.com76f10a32014-02-05 15:32:21 +00001205 // default impl defers to getDevice()->newSurface(info)
1206 virtual SkSurface* onNewSurface(const SkImageInfo&);
1207
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001208 // default impl defers to its device
1209 virtual const void* onPeekPixels(SkImageInfo*, size_t* rowBytes);
reed@google.com9c135db2014-03-12 18:28:35 +00001210 virtual void* onAccessTopLayerPixels(SkImageInfo*, size_t* rowBytes);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001211
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001212 // Subclass save/restore notifiers.
1213 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1214 // willSaveLayer()'s return value may suppress full layer allocation.
1215 enum SaveLayerStrategy {
1216 kFullLayer_SaveLayerStrategy,
1217 kNoLayer_SaveLayerStrategy
1218 };
1219 virtual void willSave(SaveFlags);
1220 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags);
1221 virtual void willRestore();
1222
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001223 virtual void didTranslate(SkScalar, SkScalar);
1224 virtual void didScale(SkScalar, SkScalar);
1225 virtual void didRotate(SkScalar);
1226 virtual void didSkew(SkScalar, SkScalar);
1227 virtual void didConcat(const SkMatrix&);
1228 virtual void didSetMatrix(const SkMatrix&);
1229
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001230 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1231
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001232 enum ClipEdgeStyle {
1233 kHard_ClipEdgeStyle,
1234 kSoft_ClipEdgeStyle
1235 };
1236
1237 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1238 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1239 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1240 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1241
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001242 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001243 // returns this. Subclasses that encapsulate an indirect canvas may
1244 // need to overload this method. The impl must keep track of this, as it
1245 // is not released or deleted by the caller.
1246 virtual SkCanvas* canvasForDrawIter();
1247
junov@chromium.orga907ac32012-02-24 21:54:07 +00001248 // Clip rectangle bounds. Called internally by saveLayer.
1249 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001250 // If non-NULL, The imageFilter parameter will be used to expand the clip
1251 // and offscreen bounds for any margin required by the filter DAG.
junov@chromium.orga907ac32012-02-24 21:54:07 +00001252 bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001253 SkIRect* intersection,
1254 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001255
junov@chromium.orged8d6bb2013-05-29 19:09:48 +00001256 // Called by child classes that override clipPath and clipRRect to only
1257 // track fast conservative clip bounds, rather than exact clips.
commit-bot@chromium.org759cf482014-03-06 13:18:07 +00001258 void updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op,
junov@chromium.orged8d6bb2013-05-29 19:09:48 +00001259 bool inverseFilled);
1260
reed@google.com97af1a62012-08-28 12:19:02 +00001261 // notify our surface (if we have one) that we are about to draw, so it
1262 // can perform copy-on-write or invalidate any cached images
1263 void predrawNotify();
1264
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001265 virtual void onPushCull(const SkRect& cullRect);
1266 virtual void onPopCull();
1267
reed@android.com8a1c16f2008-12-17 15:59:43 +00001268private:
1269 class MCRec;
1270
reed@google.com5c3d1472011-02-22 19:12:23 +00001271 SkClipStack fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001272 SkDeque fMCStack;
1273 // points to top of stack
1274 MCRec* fMCRec;
1275 // the first N recs that can fit here mean we won't call malloc
1276 uint32_t fMCRecStorage[32];
1277
1278 SkBounder* fBounder;
junov@chromium.orgb0a7ace2012-04-05 18:33:23 +00001279 int fSaveLayerCount; // number of successful saveLayer calls
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001280 int fCullCount; // number of active culls
reed@android.com8a1c16f2008-12-17 15:59:43 +00001281
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001282 SkMetaData* fMetaData;
1283
reed@google.com97af1a62012-08-28 12:19:02 +00001284 SkSurface_Base* fSurfaceBase;
1285 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1286 void setSurfaceBase(SkSurface_Base* sb) {
1287 fSurfaceBase = sb;
1288 }
1289 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001290 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001291
reed@android.com8a1c16f2008-12-17 15:59:43 +00001292 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1293 void updateDeviceCMCache();
1294
reed@google.com9c135db2014-03-12 18:28:35 +00001295 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001296 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001297 friend class SkLua; // needs top layer size and offset
1298 friend class SkDeferredDevice; // needs getTopDevice()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001299
commit-bot@chromium.org15a14052014-02-16 00:59:25 +00001300 SkBaseDevice* createLayerDevice(const SkImageInfo&);
bsalomon@google.come97f0852011-06-17 13:10:25 +00001301
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001302 SkBaseDevice* init(SkBaseDevice*);
reed@google.comf0b5e112011-09-07 11:57:34 +00001303
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001304 /**
1305 * DEPRECATED
1306 *
1307 * Specify a device for this canvas to draw into. If it is not null, its
1308 * reference count is incremented. If the canvas was already holding a
1309 * device, its reference count is decremented. The new device is returned.
1310 */
1311 SkBaseDevice* setRootDevice(SkBaseDevice* device);
skia.committer@gmail.com31acdea2014-02-18 03:01:51 +00001312
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00001313 /**
1314 * Gets the size/origin of the top level layer in global canvas coordinates. We don't want this
1315 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1316 */
1317 SkISize getTopLayerSize() const;
1318 SkIPoint getTopLayerOrigin() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001319
reed@google.comf0b5e112011-09-07 11:57:34 +00001320 // internal methods are not virtual, so they can safely be called by other
1321 // canvas apis, without confusing subclasses (like SkPictureRecording)
robertphillips@google.com9bf380c2013-07-25 12:10:42 +00001322 void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
reed@google.com71121732012-09-18 15:14:33 +00001323 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001324 const SkRect& dst, const SkPaint* paint,
1325 DrawBitmapRectFlags flags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001326 void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1327 const SkRect& dst, const SkPaint* paint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001328 void internalDrawPaint(const SkPaint& paint);
reed@google.com8926b162012-03-23 15:36:36 +00001329 int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001330 SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy);
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001331 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001332
reed@android.com8a1c16f2008-12-17 15:59:43 +00001333 // shared by save() and saveLayer()
1334 int internalSave(SaveFlags flags);
1335 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001336 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1337 const SkRect& r, SkScalar textSize);
1338 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1339 const char text[], size_t byteLength,
1340 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001341
reed@android.com8a1c16f2008-12-17 15:59:43 +00001342 /* These maintain a cache of the clip bounds in local coordinates,
1343 (converted to 2s-compliment if floats are slow).
1344 */
reed@google.comc0784db2013-12-13 21:16:12 +00001345 mutable SkRect fCachedLocalClipBounds;
1346 mutable bool fCachedLocalClipBoundsDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001347 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001348 bool fAllowSimplifyClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001349
reed@google.comc0784db2013-12-13 21:16:12 +00001350 const SkRect& getLocalClipBounds() const {
1351 if (fCachedLocalClipBoundsDirty) {
1352 if (!this->getClipBounds(&fCachedLocalClipBounds)) {
1353 fCachedLocalClipBounds.setEmpty();
1354 }
1355 fCachedLocalClipBoundsDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001356 }
reed@google.comc0784db2013-12-13 21:16:12 +00001357 return fCachedLocalClipBounds;
reed@android.comba09de42010-02-05 20:46:05 +00001358 }
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001359
reed@google.com5c3d1472011-02-22 19:12:23 +00001360 class AutoValidateClip : ::SkNoncopyable {
1361 public:
1362 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1363 fCanvas->validateClip();
1364 }
1365 ~AutoValidateClip() { fCanvas->validateClip(); }
1366
1367 private:
1368 const SkCanvas* fCanvas;
1369 };
1370
1371#ifdef SK_DEBUG
1372 void validateClip() const;
1373#else
1374 void validateClip() const {}
1375#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001376
1377 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001378};
1379
1380/** Stack helper class to automatically call restoreToCount() on the canvas
1381 when this object goes out of scope. Use this to guarantee that the canvas
1382 is restored to a known state.
1383*/
1384class SkAutoCanvasRestore : SkNoncopyable {
1385public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001386 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1387 if (fCanvas) {
1388 fSaveCount = canvas->getSaveCount();
1389 if (doSave) {
1390 canvas->save();
1391 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001392 }
1393 }
1394 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001395 if (fCanvas) {
1396 fCanvas->restoreToCount(fSaveCount);
1397 }
1398 }
1399
1400 /**
1401 * Perform the restore now, instead of waiting for the destructor. Will
1402 * only do this once.
1403 */
1404 void restore() {
1405 if (fCanvas) {
1406 fCanvas->restoreToCount(fSaveCount);
1407 fCanvas = NULL;
1408 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001409 }
1410
1411private:
1412 SkCanvas* fCanvas;
1413 int fSaveCount;
1414};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001415#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001416
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001417/** Stack helper class to automatically open and close a comment block
1418 */
1419class SkAutoCommentBlock : SkNoncopyable {
1420public:
1421 SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
1422 fCanvas = canvas;
1423 if (NULL != fCanvas) {
1424 fCanvas->beginCommentGroup(description);
1425 }
1426 }
1427
1428 ~SkAutoCommentBlock() {
1429 if (NULL != fCanvas) {
1430 fCanvas->endCommentGroup();
1431 }
1432 }
1433
1434private:
1435 SkCanvas* fCanvas;
1436};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001437#define SkAutoCommentBlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoCommentBlock)
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001438
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001439/**
1440 * If the caller wants read-only access to the pixels in a canvas, it can just
1441 * call canvas->peekPixels(), since that is the fastest way to "peek" at the
1442 * pixels on a raster-backed canvas.
1443 *
1444 * If the canvas has pixels, but they are not readily available to the CPU
1445 * (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will
1446 * succeed (though be slower, since it will return a copy of the pixels).
1447 *
1448 * SkAutoROCanvasPixels encapsulates these two techniques, trying first to call
1449 * peekPixels() (for performance), but if that fails, calling readPixels() and
1450 * storing the copy locally.
1451 *
1452 * The caller must respect the restrictions associated with peekPixels(), since
1453 * that may have been called: The returned information is invalidated if...
1454 * - any API is called on the canvas (or its parent surface if present)
1455 * - the canvas goes out of scope
1456 */
1457class SkAutoROCanvasPixels : SkNoncopyable {
1458public:
1459 SkAutoROCanvasPixels(SkCanvas* canvas);
1460
1461 // returns NULL on failure
1462 const void* addr() const { return fAddr; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001463
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001464 // undefined if addr() == NULL
1465 size_t rowBytes() const { return fRowBytes; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001466
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001467 // undefined if addr() == NULL
1468 const SkImageInfo& info() const { return fInfo; }
1469
1470 // helper that, if returns true, installs the pixels into the bitmap. Note
1471 // that the bitmap may reference the address returned by peekPixels(), so
1472 // the caller must respect the restrictions associated with peekPixels().
1473 bool asROBitmap(SkBitmap*) const;
1474
1475private:
1476 SkBitmap fBitmap; // used if peekPixels() fails
1477 const void* fAddr; // NULL on failure
1478 SkImageInfo fInfo;
1479 size_t fRowBytes;
1480};
1481
reed@android.com8a1c16f2008-12-17 15:59:43 +00001482#endif