blob: f5d4fe63cf49e307c44bb42b72293383df48cd5a [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
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +000021//#define SK_SUPPORT_LEGACY_READPIXELSCONFIG
22
reed@google.comb93ba452014-03-10 19:47:58 +000023// if not defined, we always assume ClipToLayer for saveLayer()
24//#define SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
25
26
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +000027//#define SK_SUPPORT_LEGACY_GETCLIPTYPE
28//#define SK_SUPPORT_LEGACY_GETTOTALCLIP
reed@google.com9c135db2014-03-12 18:28:35 +000029//#define SK_SUPPORT_LEGACY_GETTOPDEVICE
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +000030
reed@android.com8a1c16f2008-12-17 15:59:43 +000031class SkBounder;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000032class SkBaseDevice;
reed@android.com8a1c16f2008-12-17 15:59:43 +000033class SkDraw;
34class SkDrawFilter;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000035class SkMetaData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000036class SkPicture;
reed@google.com4ed0fb72012-12-12 20:48:18 +000037class SkRRect;
reed@google.com76f10a32014-02-05 15:32:21 +000038class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000039class SkSurface_Base;
commit-bot@chromium.org644629c2013-11-21 06:21:58 +000040class GrContext;
reed@google.com9c135db2014-03-12 18:28:35 +000041class GrRenderTarget;
reed@android.com8a1c16f2008-12-17 15:59:43 +000042
43/** \class SkCanvas
44
45 A Canvas encapsulates all of the state about drawing into a device (bitmap).
46 This includes a reference to the device itself, and a stack of matrix/clip
47 values. For any given draw call (e.g. drawRect), the geometry of the object
48 being drawn is transformed by the concatenation of all the matrices in the
49 stack. The transformed geometry is clipped by the intersection of all of
50 the clips in the stack.
51
52 While the Canvas holds the state of the drawing device, the state (style)
53 of the object being drawn is held by the Paint, which is provided as a
54 parameter to each of the draw() methods. The Paint holds attributes such as
55 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
56 etc.
57*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000058class SK_API SkCanvas : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000059public:
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000060 SK_DECLARE_INST_COUNT(SkCanvas)
61
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000062 /**
commit-bot@chromium.org3107b6a2014-02-27 20:32:51 +000063 * Attempt to allocate an offscreen raster canvas, matching the ImageInfo.
64 * On success, return a new canvas that will draw into that offscreen.
65 *
66 * The caller can access the pixels after drawing into this canvas by
67 * calling readPixels() or peekPixels().
68 *
69 * If the requested ImageInfo is opaque (either the colortype is
70 * intrinsically opaque like RGB_565, or the info's alphatype is kOpaque)
71 * then the pixel memory may be uninitialized. Otherwise, the pixel memory
72 * will be initialized to 0, which is interpreted as transparent.
73 *
74 * On failure, return NULL. This can fail for several reasons:
75 * 1. the memory allocation failed (e.g. request is too large)
76 * 2. invalid ImageInfo (e.g. negative dimensions)
77 * 3. unsupported ImageInfo for a canvas
78 * - kUnknown_SkColorType, kIndex_8_SkColorType
79 * - kIgnore_SkAlphaType
80 * - this list is not complete, so others may also be unsupported
81 *
82 * Note: it is valid to request a supported ImageInfo, but with zero
83 * dimensions.
84 */
85 static SkCanvas* NewRaster(const SkImageInfo&);
86
87 static SkCanvas* NewRasterN32(int width, int height) {
88 return NewRaster(SkImageInfo::MakeN32Premul(width, height));
89 }
90
91 /**
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000092 * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
93 * specified pixels. To access the pixels after drawing to them, the caller should call
94 * flush() or call peekPixels(...).
95 *
96 * On failure, return NULL. This can fail for several reasons:
97 * 1. invalid ImageInfo (e.g. negative dimensions)
98 * 2. unsupported ImageInfo for a canvas
99 * - kUnknown_SkColorType, kIndex_8_SkColorType
100 * - kIgnore_SkAlphaType
101 * - this list is not complete, so others may also be unsupported
102 *
103 * Note: it is valid to request a supported ImageInfo, but with zero
104 * dimensions.
105 */
106 static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t);
107
108 static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
109 return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
110 }
111
112 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +0000113 * Creates an empty canvas with no backing device/pixels, and zero
114 * dimensions.
115 */
reed@google.comcde92112011-07-06 20:00:52 +0000116 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000117
commit-bot@chromium.orge2543102014-01-31 19:42:58 +0000118 /**
119 * Creates a canvas of the specified dimensions, but explicitly not backed
120 * by any device/pixels. Typically this use used by subclasses who handle
121 * the draw calls in some other way.
122 */
123 SkCanvas(int width, int height);
124
reed@google.com6dc74552011-07-21 18:00:46 +0000125 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000126
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000127 @param device Specifies a device for the canvas to draw into.
128 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000129 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000130
reed@google.com44699382013-10-31 17:28:30 +0000131 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 @param bitmap Specifies a bitmap for the canvas to draw into. Its
133 structure are copied to the canvas.
134 */
135 explicit SkCanvas(const SkBitmap& bitmap);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136 virtual ~SkCanvas();
137
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000138 SkMetaData& getMetaData();
139
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000140 /**
141 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
142 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
143 */
144 SkImageInfo imageInfo() const;
145
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146 ///////////////////////////////////////////////////////////////////////////
147
reed@google.com210ce002011-11-01 14:24:23 +0000148 /**
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000149 * Trigger the immediate execution of all pending draw operations.
150 */
151 void flush();
152
153 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000154 * Gets the size of the base or root layer in global canvas coordinates. The
155 * origin of the base layer is always (0,0). The current drawable area may be
156 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000157 */
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000158 SkISize getBaseLayerSize() const;
159
160 /**
161 * DEPRECATED: call getBaseLayerSize
162 */
163 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000164
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000165 /**
166 * DEPRECATED.
167 * Return the canvas' device object, which may be null. The device holds
168 * the bitmap of the pixels that the canvas draws into. The reference count
169 * of the returned device is not changed by this call.
170 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000171 SkBaseDevice* getDevice() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172
reed@google.com9266fed2011-03-30 00:18:03 +0000173 /**
174 * saveLayer() can create another device (which is later drawn onto
175 * the previous device). getTopDevice() returns the top-most device current
176 * installed. Note that this can change on other calls like save/restore,
177 * so do not access this device after subsequent canvas calls.
178 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000179 *
180 * @param updateMatrixClip If this is true, then before the device is
181 * returned, we ensure that its has been notified about the current
182 * matrix and clip. Note: this happens automatically when the device
183 * is drawn to, but is optional here, as there is a small perf hit
184 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000185 */
reed@google.com9c135db2014-03-12 18:28:35 +0000186#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
187private:
188#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000189 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000190public:
reed@google.com9266fed2011-03-30 00:18:03 +0000191
reed@google.com76f10a32014-02-05 15:32:21 +0000192 /**
193 * Create a new surface matching the specified info, one that attempts to
194 * be maximally compatible when used with this canvas.
195 */
196 SkSurface* newSurface(const SkImageInfo&);
bsalomon@google.come97f0852011-06-17 13:10:25 +0000197
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000198 /**
199 * Return the GPU context of the device that is associated with the canvas.
200 * For a canvas with non-GPU device, NULL is returned.
201 */
202 GrContext* getGrContext();
203
reed@google.com4b226022011-01-11 18:32:13 +0000204 ///////////////////////////////////////////////////////////////////////////
205
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000206 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000207 * If the canvas has writable pixels in its top layer (and is not recording to a picture
208 * or other non-raster target) and has direct access to its pixels (i.e. they are in
209 * local RAM) return the address of those pixels, and if not null,
210 * return the ImageInfo and rowBytes. The returned address is only valid
211 * while the canvas object is in scope and unchanged. Any API calls made on
212 * canvas (or its parent surface if any) will invalidate the
213 * returned address (and associated information).
214 *
215 * On failure, returns NULL and the info and rowBytes parameters are
216 * ignored.
217 */
218 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes);
219
220 /**
221 * If the canvas has readable pixels in its base layer (and is not recording to a picture
222 * 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 +0000223 * local RAM) return the const-address of those pixels, and if not null,
224 * return the ImageInfo and rowBytes. The returned address is only valid
225 * while the canvas object is in scope and unchanged. Any API calls made on
226 * canvas (or its parent surface if any) will invalidate the
227 * returned address (and associated information).
228 *
229 * On failure, returns NULL and the info and rowBytes parameters are
230 * ignored.
231 */
232 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
233
234 /**
bsalomon@google.comd58a1cd2011-11-10 20:57:43 +0000235 * This enum can be used with read/writePixels to perform a pixel ops to or
236 * from an 8888 config other than Skia's native config (SkPMColor). There
237 * are three byte orders supported: native, BGRA, and RGBA. Each has a
238 * premultiplied and unpremultiplied variant.
239 *
240 * Components of a 8888 pixel can be packed/unpacked from a 32bit word using
241 * either byte offsets or shift values. Byte offsets are endian-invariant
242 * while shifts are not. BGRA and RGBA configs are defined by byte
243 * orderings. The native config is defined by shift values (SK_A32_SHIFT,
244 * ..., SK_B32_SHIFT).
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000245 */
246 enum Config8888 {
247 /**
248 * Skia's native order specified by:
249 * SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
250 *
251 * kNative_Premul_Config8888 is equivalent to SkPMColor
252 * kNative_Unpremul_Config8888 has the same component order as SkPMColor
253 * but is not premultiplied.
254 */
255 kNative_Premul_Config8888,
256 kNative_Unpremul_Config8888,
257 /**
258 * low byte to high byte: B, G, R, A.
259 */
260 kBGRA_Premul_Config8888,
261 kBGRA_Unpremul_Config8888,
262 /**
263 * low byte to high byte: R, G, B, A.
264 */
265 kRGBA_Premul_Config8888,
tomhudson@google.com1f902872012-06-01 13:15:47 +0000266 kRGBA_Unpremul_Config8888
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000267 };
268
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000269#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000270 /**
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000271 * On success (returns true), copy the canvas pixels into the bitmap.
272 * On failure, the bitmap parameter is left unchanged and false is
273 * returned.
274 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000275 * The canvas' pixels are converted to the bitmap's config. The only
276 * supported config is kARGB_8888_Config, though this is likely to be
277 * relaxed in the future. The meaning of config kARGB_8888_Config is
278 * modified by the enum param config8888. The default value interprets
279 * kARGB_8888_Config as SkPMColor
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000280 *
281 * If the bitmap has pixels already allocated, the canvas pixels will be
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000282 * written there. If not, bitmap->allocPixels() will be called
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000283 * automatically. If the bitmap is backed by a texture readPixels will
284 * fail.
285 *
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000286 * The actual pixels written is the intersection of the canvas' bounds, and
287 * the rectangle formed by the bitmap's width,height and the specified x,y.
288 * If bitmap pixels extend outside of that intersection, they will not be
289 * modified.
290 *
bsalomon@google.com6850eab2011-11-03 20:29:47 +0000291 * Other failure conditions:
292 * * If the canvas is backed by a non-raster device (e.g. PDF) then
293 * readPixels will fail.
294 * * If bitmap is texture-backed then readPixels will fail. (This may be
295 * relaxed in the future.)
296 *
297 * Example that reads the entire canvas into a bitmap using the native
298 * SkPMColor:
299 * SkISize size = canvas->getDeviceSize();
300 * bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
301 * size.fHeight);
302 * if (canvas->readPixels(bitmap, 0, 0)) {
303 * // use the pixels
304 * }
bsalomon@google.comc6980972011-11-02 19:57:21 +0000305 */
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000306 bool readPixels(SkBitmap* bitmap, int x, int y, Config8888 config8888);
307#endif
bsalomon@google.comc6980972011-11-02 19:57:21 +0000308
reed@google.com4b226022011-01-11 18:32:13 +0000309 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000310 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
311 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
312 * starting at the specified (x,y) location in the coordinate system of the base-layer.
313 *
314 * The specified ImageInfo and (x,y) offset specifies a source rectangle
315 *
316 * srcR(x, y, info.width(), info.height());
317 *
318 * SrcR is intersected with the bounds of the base-layer. If this intersection is not empty,
319 * then we have two sets of pixels (of equal size), the "src" specified by base-layer at (x,y)
320 * and the "dst" by info+pixels+rowBytes. Replace the dst pixels with the corresponding src
321 * pixels, performing any colortype/alphatype transformations needed (in the case where the
322 * src and dst have different colortypes or alphatypes).
323 *
324 * This call can fail, returning false, for several reasons:
325 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
326 * - If this canvas is not backed by pixels (e.g. picture or PDF)
327 */
328 bool readPixels(const SkImageInfo&, void* pixels, size_t rowBytes, int x, int y);
329
330 /**
331 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
332 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
333 * it calls through to readPixels(info, ...) and returns its result.
334 */
335 bool readPixels(SkBitmap* bitmap, int x, int y);
336
337 /**
338 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
339 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
340 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
341 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000342 */
343 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000344
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000345 /**
346 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
347 * ignoring the matrix and clip.
348 *
349 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
350 *
351 * target.setXYWH(x, y, info.width(), info.height());
352 *
353 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
354 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
355 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
356 * pixels, performing any colortype/alphatype transformations needed (in the case where the
357 * src and dst have different colortypes or alphatypes).
358 *
359 * This call can fail, returning false, for several reasons:
360 * - If the src colortype/alphatype cannot be converted to the canvas' types
361 * - If this canvas is not backed by pixels (e.g. picture or PDF)
362 */
363 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
364
365 /**
366 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
367 * is just wrapping a texture, returns false and does nothing.
368 */
369 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000370
reed@android.com8a1c16f2008-12-17 15:59:43 +0000371 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000372
reed@android.com8a1c16f2008-12-17 15:59:43 +0000373 enum SaveFlags {
374 /** save the matrix state, restoring it on restore() */
375 kMatrix_SaveFlag = 0x01,
376 /** save the clip state, restoring it on restore() */
377 kClip_SaveFlag = 0x02,
378 /** the layer needs to support per-pixel alpha */
379 kHasAlphaLayer_SaveFlag = 0x04,
380 /** the layer needs to support 8-bits per color component */
381 kFullColorLayer_SaveFlag = 0x08,
reed@google.comb93ba452014-03-10 19:47:58 +0000382 /**
383 * the layer should clip against the bounds argument
384 *
385 * if SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG is undefined, this is treated as always on.
386 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000387 kClipToLayer_SaveFlag = 0x10,
388
389 // helper masks for common choices
390 kMatrixClip_SaveFlag = 0x03,
reed@google.comb93ba452014-03-10 19:47:58 +0000391#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 kARGB_NoClipLayer_SaveFlag = 0x0F,
reed@google.comb93ba452014-03-10 19:47:58 +0000393#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000394 kARGB_ClipLayer_SaveFlag = 0x1F
395 };
396
reed@android.comdc3381f2010-02-11 16:05:15 +0000397 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000399 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
400 operate on this copy.
401 When the balancing call to restore() is made, the previous matrix, clip,
402 and drawFilter are restored.
djsollen@google.comd4236572013-08-13 14:29:06 +0000403 @param flags The flags govern what portion of the Matrix/Clip/drawFilter
404 state the save (and matching restore) effect. For example,
405 if only kMatrix is specified, then only the matrix state
406 will be pushed and popped. Likewise for the clip if kClip
407 is specified. However, the drawFilter is always affected
408 by calls to save/restore.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000409 @return The value to pass to restoreToCount() to balance this save()
410 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000411 int save(SaveFlags flags = kMatrixClip_SaveFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000412
413 /** This behaves the same as save(), but in addition it allocates an
414 offscreen bitmap. All drawing calls are directed there, and only when
415 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000416 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000417 @param bounds (may be null) This rect, if non-null, is used as a hint to
418 limit the size of the offscreen, and thus drawing may be
419 clipped to it, though that clipping is not guaranteed to
420 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421 @param paint (may be null) This is copied, and is applied to the
422 offscreen when restore() is called
423 @param flags LayerFlags
424 @return The value to pass to restoreToCount() to balance this save()
425 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000426 int saveLayer(const SkRect* bounds, const SkPaint* paint,
427 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428
429 /** This behaves the same as save(), but in addition it allocates an
430 offscreen bitmap. All drawing calls are directed there, and only when
431 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000432 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000433 @param bounds (may be null) This rect, if non-null, is used as a hint to
434 limit the size of the offscreen, and thus drawing may be
435 clipped to it, though that clipping is not guaranteed to
436 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000437 @param alpha This is applied to the offscreen when restore() is called.
438 @param flags LayerFlags
439 @return The value to pass to restoreToCount() to balance this save()
440 */
441 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
442 SaveFlags flags = kARGB_ClipLayer_SaveFlag);
443
444 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000445 modifications to the matrix/clip/drawFilter state since the last save
446 call.
447 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000448 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000449 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000450
451 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000452 This will equal # save() calls - # restore() calls + 1. The save count on
453 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000454 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000455 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000456
457 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000458 count reached saveCount. It is an error for saveCount to be greater than
459 getSaveCount(). To pop all the way back to the initial matrix/clip context
460 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000461 @param saveCount The number of save() levels to restore from
462 */
463 void restoreToCount(int saveCount);
464
reed@google.com7c202932011-12-14 18:48:05 +0000465 /** Returns true if drawing is currently going to a layer (from saveLayer)
466 * rather than to the root device.
467 */
junov@chromium.org8f9ecbd2012-02-13 21:53:45 +0000468 virtual bool isDrawingToLayer() const;
reed@google.com7c202932011-12-14 18:48:05 +0000469
reed@android.com8a1c16f2008-12-17 15:59:43 +0000470 /** Preconcat the current matrix with the specified translation
471 @param dx The distance to translate in X
472 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000473 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000474 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475
476 /** Preconcat the current matrix with the specified scale.
477 @param sx The amount to scale in X
478 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000480 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000481
482 /** Preconcat the current matrix with the specified rotation.
483 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000484 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000485 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000486
487 /** Preconcat the current matrix with the specified skew.
488 @param sx The amount to skew in X
489 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000490 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000491 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000492
493 /** Preconcat the current matrix with the specified matrix.
494 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000495 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000496 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000497
reed@android.com8a1c16f2008-12-17 15:59:43 +0000498 /** Replace the current matrix with a copy of the specified matrix.
499 @param matrix The matrix that will be copied into the current matrix.
500 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000501 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000502
reed@android.com8a1c16f2008-12-17 15:59:43 +0000503 /** Helper for setMatrix(identity). Sets the current matrix to identity.
504 */
505 void resetMatrix();
506
reed@google.com4ed0fb72012-12-12 20:48:18 +0000507 /**
508 * Modify the current clip with the specified rectangle.
509 * @param rect The rect to combine with the current clip
510 * @param op The region op to apply to the current clip
511 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000512 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000513 void clipRect(const SkRect& rect,
514 SkRegion::Op op = SkRegion::kIntersect_Op,
515 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000516
reed@google.com4ed0fb72012-12-12 20:48:18 +0000517 /**
518 * Modify the current clip with the specified SkRRect.
519 * @param rrect The rrect to combine with the current clip
520 * @param op The region op to apply to the current clip
521 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000522 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000523 void clipRRect(const SkRRect& rrect,
524 SkRegion::Op op = SkRegion::kIntersect_Op,
525 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000526
527 /**
528 * Modify the current clip with the specified path.
529 * @param path The path to combine with the current clip
530 * @param op The region op to apply to the current clip
531 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000532 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000533 void clipPath(const SkPath& path,
534 SkRegion::Op op = SkRegion::kIntersect_Op,
535 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000536
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000537 /** EXPERIMENTAL -- only used for testing
538 Set to false to force clips to be hard, even if doAntiAlias=true is
539 passed to clipRect or clipPath.
540 */
541 void setAllowSoftClip(bool allow) {
542 fAllowSoftClip = allow;
543 }
544
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000545 /** EXPERIMENTAL -- only used for testing
546 Set to simplify clip stack using path ops.
547 */
548 void setAllowSimplifyClip(bool allow) {
549 fAllowSimplifyClip = allow;
550 }
551
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552 /** Modify the current clip with the specified region. Note that unlike
553 clipRect() and clipPath() which transform their arguments by the current
554 matrix, clipRegion() assumes its argument is already in device
555 coordinates, and so no transformation is performed.
556 @param deviceRgn The region to apply to the current clip
557 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000558 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000559 void clipRegion(const SkRegion& deviceRgn,
560 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561
562 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
563 specified region. This does not intersect or in any other way account
564 for the existing clip region.
565 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000566 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000567 void setClipRegion(const SkRegion& deviceRgn) {
568 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000569 }
570
reed@android.com8a1c16f2008-12-17 15:59:43 +0000571 /** Return true if the specified rectangle, after being transformed by the
572 current matrix, would lie completely outside of the current clip. Call
573 this to check if an area you intend to draw into is clipped out (and
574 therefore you can skip making the draw calls).
575 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000576 @return true if the rect (transformed by the canvas' matrix) does not
577 intersect with the canvas' clip
578 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000579 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000580
581 /** Return true if the specified path, after being transformed by the
582 current matrix, would lie completely outside of the current clip. Call
583 this to check if an area you intend to draw into is clipped out (and
584 therefore you can skip making the draw calls). Note, for speed it may
585 return false even if the path itself might not intersect the clip
586 (i.e. the bounds of the path intersects, but the path does not).
587 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000588 @return true if the path (transformed by the canvas' matrix) does not
589 intersect with the canvas' clip
590 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000591 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000592
593 /** Return true if the horizontal band specified by top and bottom is
594 completely clipped out. This is a conservative calculation, meaning
595 that it is possible that if the method returns false, the band may still
596 in fact be clipped out, but the converse is not true. If this method
597 returns true, then the band is guaranteed to be clipped out.
598 @param top The top of the horizontal band to compare with the clip
599 @param bottom The bottom of the horizontal and to compare with the clip
600 @return true if the horizontal band is completely clipped out (i.e. does
601 not intersect the current clip)
602 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000603 bool quickRejectY(SkScalar top, SkScalar bottom) const {
reed@google.comc0784db2013-12-13 21:16:12 +0000604 SkASSERT(top <= bottom);
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000605
606#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
607 // TODO: add a hasPerspective method similar to getLocalClipBounds. This
608 // would cache the SkMatrix::hasPerspective result. Alternatively, have
609 // the MC stack just set a hasPerspective boolean as it is updated.
610 if (this->getTotalMatrix().hasPerspective()) {
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000611 // TODO: consider implementing some half-plane test between the
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000612 // two Y planes and the device-bounds (i.e., project the top and
613 // bottom Y planes and then determine if the clip bounds is completely
614 // outside either one).
615 return false;
616 }
617#endif
618
reed@google.comc0784db2013-12-13 21:16:12 +0000619 const SkRect& clipR = this->getLocalClipBounds();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000620 // In the case where the clip is empty and we are provided with a
621 // negative top and positive bottom parameter then this test will return
622 // false even though it will be clipped. We have chosen to exclude that
623 // check as it is rare and would result double the comparisons.
reed@google.comc0784db2013-12-13 21:16:12 +0000624 return top >= clipR.fBottom || bottom <= clipR.fTop;
djsollen@google.com92d2a292012-02-27 16:17:59 +0000625 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000626
627 /** Return the bounds of the current clip (in local coordinates) in the
628 bounds parameter, and return true if it is non-empty. This can be useful
629 in a way similar to quickReject, in that it tells you that drawing
630 outside of these bounds will be clipped out.
631 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000632 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000633
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000634 /** Return the bounds of the current clip, in device coordinates; returns
635 true if non-empty. Maybe faster than getting the clip explicitly and
636 then taking its bounds.
637 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000638 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000639
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000640
reed@android.com8a1c16f2008-12-17 15:59:43 +0000641 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000642 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000643 @param a the alpha component (0..255) of the color to fill the canvas
644 @param r the red component (0..255) of the color to fill the canvas
645 @param g the green component (0..255) of the color to fill the canvas
646 @param b the blue component (0..255) of the color to fill the canvas
647 @param mode the mode to apply the color in (defaults to SrcOver)
648 */
649 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000650 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000651
652 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000653 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000654 @param color the color to draw with
655 @param mode the mode to apply the color in (defaults to SrcOver)
656 */
657 void drawColor(SkColor color,
reed@android.com845fdac2009-06-23 03:01:32 +0000658 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000659
reed@google.com2a981812011-04-14 18:59:28 +0000660 /**
661 * This erases the entire drawing surface to the specified color,
662 * irrespective of the clip. It does not blend with the previous pixels,
663 * but always overwrites them.
664 *
665 * It is roughly equivalent to the following:
666 * canvas.save();
667 * canvas.clipRect(hugeRect, kReplace_Op);
668 * paint.setColor(color);
669 * paint.setXfermodeMode(kSrc_Mode);
670 * canvas.drawPaint(paint);
671 * canvas.restore();
672 * though it is almost always much more efficient.
673 */
674 virtual void clear(SkColor);
675
676 /**
677 * Fill the entire canvas' bitmap (restricted to the current clip) with the
678 * specified paint.
679 * @param paint The paint used to fill the canvas
680 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000681 virtual void drawPaint(const SkPaint& paint);
682
683 enum PointMode {
684 /** drawPoints draws each point separately */
685 kPoints_PointMode,
686 /** drawPoints draws each pair of points as a line segment */
687 kLines_PointMode,
688 /** drawPoints draws the array of points as a polygon */
689 kPolygon_PointMode
690 };
691
692 /** Draw a series of points, interpreted based on the PointMode mode. For
693 all modes, the count parameter is interpreted as the total number of
694 points. For kLine mode, count/2 line segments are drawn.
695 For kPoint mode, each point is drawn centered at its coordinate, and its
696 size is specified by the paint's stroke-width. It draws as a square,
697 unless the paint's cap-type is round, in which the points are drawn as
698 circles.
699 For kLine mode, each pair of points is drawn as a line segment,
700 respecting the paint's settings for cap/join/width.
701 For kPolygon mode, the entire array is drawn as a series of connected
702 line segments.
703 Note that, while similar, kLine and kPolygon modes draw slightly
704 differently than the equivalent path built with a series of moveto,
705 lineto calls, in that the path will draw all of its contours at once,
706 with no interactions if contours intersect each other (think XOR
707 xfermode). drawPoints always draws each element one at a time.
708 @param mode PointMode specifying how to draw the array of points.
709 @param count The number of points in the array
710 @param pts Array of points to draw
711 @param paint The paint used to draw the points
712 */
713 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
714 const SkPaint& paint);
715
716 /** Helper method for drawing a single point. See drawPoints() for a more
717 details.
718 */
719 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000720
reed@android.com8a1c16f2008-12-17 15:59:43 +0000721 /** Draws a single pixel in the specified color.
722 @param x The X coordinate of which pixel to draw
723 @param y The Y coordiante of which pixel to draw
724 @param color The color to draw
725 */
726 void drawPoint(SkScalar x, SkScalar y, SkColor color);
727
728 /** Draw a line segment with the specified start and stop x,y coordinates,
729 using the specified paint. NOTE: since a line is always "framed", the
730 paint's Style is ignored.
731 @param x0 The x-coordinate of the start point of the line
732 @param y0 The y-coordinate of the start point of the line
733 @param x1 The x-coordinate of the end point of the line
734 @param y1 The y-coordinate of the end point of the line
735 @param paint The paint used to draw the line
736 */
737 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
738 const SkPaint& paint);
739
740 /** Draw the specified rectangle using the specified paint. The rectangle
741 will be filled or stroked based on the Style in the paint.
742 @param rect The rect to be drawn
743 @param paint The paint used to draw the rect
744 */
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000745 virtual void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000746
747 /** Draw the specified rectangle using the specified paint. The rectangle
748 will be filled or framed based on the Style in the paint.
749 @param rect The rect to be drawn
750 @param paint The paint used to draw the rect
751 */
reed@google.com87001ed2014-02-17 16:28:05 +0000752 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000753 SkRect r;
754 r.set(rect); // promotes the ints to scalars
755 this->drawRect(r, paint);
756 }
reed@google.com4b226022011-01-11 18:32:13 +0000757
reed@android.com8a1c16f2008-12-17 15:59:43 +0000758 /** Draw the specified rectangle using the specified paint. The rectangle
759 will be filled or framed based on the Style in the paint.
760 @param left The left side of the rectangle to be drawn
761 @param top The top side of the rectangle to be drawn
762 @param right The right side of the rectangle to be drawn
763 @param bottom The bottom side of the rectangle to be drawn
764 @param paint The paint used to draw the rect
765 */
766 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
767 SkScalar bottom, const SkPaint& paint);
768
769 /** Draw the specified oval using the specified paint. The oval will be
770 filled or framed based on the Style in the paint.
771 @param oval The rectangle bounds of the oval to be drawn
772 @param paint The paint used to draw the oval
773 */
reed@google.com4ed0fb72012-12-12 20:48:18 +0000774 virtual void drawOval(const SkRect& oval, const SkPaint&);
775
776 /**
777 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
778 * based on the Style in the paint.
779 *
780 * @param rrect The round-rect to draw
781 * @param paint The paint used to draw the round-rect
782 */
783 virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000784
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000785 /**
786 * Draw the annulus formed by the outer and inner rrects. The results
787 * are undefined if the outer does not contain the inner.
788 */
789 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
790
reed@android.com8a1c16f2008-12-17 15:59:43 +0000791 /** Draw the specified circle using the specified paint. If radius is <= 0,
792 then nothing will be drawn. The circle will be filled
793 or framed based on the Style in the paint.
794 @param cx The x-coordinate of the center of the cirle to be drawn
795 @param cy The y-coordinate of the center of the cirle to be drawn
796 @param radius The radius of the cirle to be drawn
797 @param paint The paint used to draw the circle
798 */
799 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
800 const SkPaint& paint);
801
802 /** Draw the specified arc, which will be scaled to fit inside the
803 specified oval. If the sweep angle is >= 360, then the oval is drawn
804 completely. Note that this differs slightly from SkPath::arcTo, which
805 treats the sweep angle mod 360.
806 @param oval The bounds of oval used to define the shape of the arc
807 @param startAngle Starting angle (in degrees) where the arc begins
808 @param sweepAngle Sweep angle (in degrees) measured clockwise
809 @param useCenter true means include the center of the oval. For filling
810 this will draw a wedge. False means just use the arc.
811 @param paint The paint used to draw the arc
812 */
813 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
814 bool useCenter, const SkPaint& paint);
815
816 /** Draw the specified round-rect using the specified paint. The round-rect
817 will be filled or framed based on the Style in the paint.
818 @param rect The rectangular bounds of the roundRect to be drawn
819 @param rx The x-radius of the oval used to round the corners
820 @param ry The y-radius of the oval used to round the corners
821 @param paint The paint used to draw the roundRect
822 */
823 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
824 const SkPaint& paint);
825
826 /** Draw the specified path using the specified paint. The path will be
827 filled or framed based on the Style in the paint.
828 @param path The path to be drawn
829 @param paint The paint used to draw the path
830 */
bsalomon@google.com7ce564c2013-10-22 16:54:15 +0000831 virtual void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000832
833 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
834 specified paint, transformed by the current matrix. Note: if the paint
835 contains a maskfilter that generates a mask which extends beyond the
836 bitmap's original width/height, then the bitmap will be drawn as if it
837 were in a Shader with CLAMP mode. Thus the color outside of the original
838 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000839
840 If a shader is present on the paint it will be ignored, except in the
841 case where the bitmap is kA8_Config. In that case, the color is
842 generated by the shader.
843
reed@android.com8a1c16f2008-12-17 15:59:43 +0000844 @param bitmap The bitmap to be drawn
845 @param left The position of the left side of the bitmap being drawn
846 @param top The position of the top side of the bitmap being drawn
847 @param paint The paint used to draw the bitmap, or NULL
848 */
849 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
850 const SkPaint* paint = NULL);
851
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000852 enum DrawBitmapRectFlags {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000853 kNone_DrawBitmapRectFlag = 0x0,
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000854 /**
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000855 * When filtering is enabled, allow the color samples outside of
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000856 * the src rect (but still in the src bitmap) to bleed into the
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000857 * drawn portion
858 */
robertphillips@google.com31acc112013-08-20 12:13:48 +0000859 kBleed_DrawBitmapRectFlag = 0x1,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000860 };
861
reed@android.com8a1c16f2008-12-17 15:59:43 +0000862 /** Draw the specified bitmap, with the specified matrix applied (before the
863 canvas' matrix is applied).
864 @param bitmap The bitmap to be drawn
865 @param src Optional: specify the subset of the bitmap to be drawn
866 @param dst The destination rectangle where the scaled/translated
867 image will be drawn
868 @param paint The paint used to draw the bitmap, or NULL
869 */
reed@google.com71121732012-09-18 15:14:33 +0000870 virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src,
871 const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000872 const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000873 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000874
reed@google.com71121732012-09-18 15:14:33 +0000875 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000876 const SkPaint* paint = NULL) {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000877 this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag);
reed@google.com71121732012-09-18 15:14:33 +0000878 }
879
880 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000881 const SkRect& dst, const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000882 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
reed@google.com71121732012-09-18 15:14:33 +0000883 SkRect realSrcStorage;
884 SkRect* realSrcPtr = NULL;
885 if (isrc) {
886 realSrcStorage.set(*isrc);
887 realSrcPtr = &realSrcStorage;
888 }
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000889 this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
reed@google.com71121732012-09-18 15:14:33 +0000890 }
skia.committer@gmail.comc1ad0222012-09-19 02:01:47 +0000891
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m,
893 const SkPaint* paint = NULL);
reed@google.com4b226022011-01-11 18:32:13 +0000894
reed@google.comf0b5e112011-09-07 11:57:34 +0000895 /**
896 * Draw the bitmap stretched differentially to fit into dst.
897 * center is a rect within the bitmap, and logically divides the bitmap
898 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
899 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
900 *
901 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000902 * - The 4 corners are not stretched at all.
903 * - The sides are stretched in only one axis.
904 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000905 * Else, for each axis where dst < bitmap,
906 * - The corners shrink proportionally
907 * - The sides (along the shrink axis) and center are not drawn
908 */
909 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
910 const SkRect& dst, const SkPaint* paint = NULL);
911
reed@android.com8a1c16f2008-12-17 15:59:43 +0000912 /** Draw the specified bitmap, with its top/left corner at (x,y),
913 NOT transformed by the current matrix. Note: if the paint
914 contains a maskfilter that generates a mask which extends beyond the
915 bitmap's original width/height, then the bitmap will be drawn as if it
916 were in a Shader with CLAMP mode. Thus the color outside of the original
917 width/height will be the edge color replicated.
918 @param bitmap The bitmap to be drawn
919 @param left The position of the left side of the bitmap being drawn
920 @param top The position of the top side of the bitmap being drawn
921 @param paint The paint used to draw the bitmap, or NULL
922 */
923 virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
924 const SkPaint* paint = NULL);
925
926 /** Draw the text, with origin at (x,y), using the specified paint.
927 The origin is interpreted based on the Align setting in the paint.
928 @param text The text to be drawn
929 @param byteLength The number of bytes to read from the text parameter
930 @param x The x-coordinate of the origin of the text being drawn
931 @param y The y-coordinate of the origin of the text being drawn
932 @param paint The paint used for the text (e.g. color, size, style)
933 */
934 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
935 SkScalar y, const SkPaint& paint);
936
937 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000938 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939 @param text The text to be drawn
940 @param byteLength The number of bytes to read from the text parameter
941 @param pos Array of positions, used to position each character
942 @param paint The paint used for the text (e.g. color, size, style)
943 */
944 virtual void drawPosText(const void* text, size_t byteLength,
945 const SkPoint pos[], const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000946
reed@android.com8a1c16f2008-12-17 15:59:43 +0000947 /** Draw the text, with each character/glyph origin specified by the x
948 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000949 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000950 @param text The text to be drawn
951 @param byteLength The number of bytes to read from the text parameter
952 @param xpos Array of x-positions, used to position each character
953 @param constY The shared Y coordinate for all of the positions
954 @param paint The paint used for the text (e.g. color, size, style)
955 */
956 virtual void drawPosTextH(const void* text, size_t byteLength,
957 const SkScalar xpos[], SkScalar constY,
958 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000959
reed@android.com8a1c16f2008-12-17 15:59:43 +0000960 /** Draw the text, with origin at (x,y), using the specified paint, along
961 the specified path. The paint's Align setting determins where along the
962 path to start the text.
963 @param text The text to be drawn
964 @param byteLength The number of bytes to read from the text parameter
965 @param path The path the text should follow for its baseline
966 @param hOffset The distance along the path to add to the text's
967 starting position
968 @param vOffset The distance above(-) or below(+) the path to
969 position the text
970 @param paint The paint used for the text
971 */
972 void drawTextOnPathHV(const void* text, size_t byteLength,
973 const SkPath& path, SkScalar hOffset,
974 SkScalar vOffset, const SkPaint& paint);
975
976 /** Draw the text, with origin at (x,y), using the specified paint, along
977 the specified path. The paint's Align setting determins where along the
978 path to start the text.
979 @param text The text to be drawn
980 @param byteLength The number of bytes to read from the text parameter
981 @param path The path the text should follow for its baseline
982 @param matrix (may be null) Applied to the text before it is
983 mapped onto the path
984 @param paint The paint used for the text
985 */
986 virtual void drawTextOnPath(const void* text, size_t byteLength,
987 const SkPath& path, const SkMatrix* matrix,
988 const SkPaint& paint);
989
commit-bot@chromium.org145d1c02014-03-16 19:46:36 +0000990 /** PRIVATE / EXPERIMENTAL -- do not call
991 Perform back-end analysis/optimization of a picture. This may attach
992 optimization data to the picture which can be used by a later
993 drawPicture call.
994 @param picture The recorded drawing commands to analyze/optimize
995 */
996 void EXPERIMENTAL_optimize(SkPicture* picture);
997
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998 /** Draw the picture into this canvas. This method effective brackets the
999 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +00001000 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001001 @param picture The recorded drawing commands to playback into this
1002 canvas.
1003 */
1004 virtual void drawPicture(SkPicture& picture);
reed@google.com4b226022011-01-11 18:32:13 +00001005
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006 enum VertexMode {
1007 kTriangles_VertexMode,
1008 kTriangleStrip_VertexMode,
1009 kTriangleFan_VertexMode
1010 };
reed@google.com4b226022011-01-11 18:32:13 +00001011
reed@android.com8a1c16f2008-12-17 15:59:43 +00001012 /** Draw the array of vertices, interpreted as triangles (based on mode).
1013 @param vmode How to interpret the array of vertices
1014 @param vertexCount The number of points in the vertices array (and
1015 corresponding texs and colors arrays if non-null)
1016 @param vertices Array of vertices for the mesh
1017 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +00001018 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001019 @param colors May be null. If not null, specifies a color for each
1020 vertex, to be interpolated across the triangle.
1021 @param xmode Used if both texs and colors are present. In this
1022 case the colors are combined with the texture using mode,
1023 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +00001024 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001025 @param indices If not null, array of indices to reference into the
1026 vertex (texs, colors) array.
1027 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001028 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001029 */
1030 virtual void drawVertices(VertexMode vmode, int vertexCount,
1031 const SkPoint vertices[], const SkPoint texs[],
1032 const SkColor colors[], SkXfermode* xmode,
1033 const uint16_t indices[], int indexCount,
1034 const SkPaint& paint);
1035
reed@android.comcb608442009-12-04 21:32:27 +00001036 /** Send a blob of data to the canvas.
1037 For canvases that draw, this call is effectively a no-op, as the data
1038 is not parsed, but just ignored. However, this call exists for
1039 subclasses like SkPicture's recording canvas, that can store the data
1040 and then play it back later (via another call to drawData).
1041 */
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001042 virtual void drawData(const void* data, size_t length) {
1043 // do nothing. Subclasses may do something with the data
1044 }
1045
skia.committer@gmail.coma5d3e772013-05-30 07:01:29 +00001046 /** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
1047 Each comment added via addComment is notionally attached to its
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001048 enclosing group. Top-level comments simply belong to no group.
1049 */
1050 virtual void beginCommentGroup(const char* description) {
1051 // do nothing. Subclasses may do something
1052 }
1053 virtual void addComment(const char* kywd, const char* value) {
1054 // do nothing. Subclasses may do something
1055 }
1056 virtual void endCommentGroup() {
1057 // do nothing. Subclasses may do something
1058 }
1059
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001060 /**
1061 * With this call the client asserts that subsequent draw operations (up to the
1062 * matching popCull()) are fully contained within the given bounding box. The assertion
1063 * is not enforced, but the information might be used to quick-reject command blocks,
1064 * so an incorrect bounding box may result in incomplete rendering.
1065 */
commit-bot@chromium.org520cf8b2014-03-20 20:25:14 +00001066 void pushCull(const SkRect& cullRect);
reed@android.comcb608442009-12-04 21:32:27 +00001067
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001068 /**
1069 * Terminates the current culling block, and restores the previous one (if any).
1070 */
commit-bot@chromium.org520cf8b2014-03-20 20:25:14 +00001071 void popCull();
1072
reed@android.com8a1c16f2008-12-17 15:59:43 +00001073 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +00001074
reed@android.com8a1c16f2008-12-17 15:59:43 +00001075 /** Get the current bounder object.
1076 The bounder's reference count is unchaged.
1077 @return the canva's bounder (or NULL).
1078 */
1079 SkBounder* getBounder() const { return fBounder; }
1080
1081 /** Set a new bounder (or NULL).
1082 Pass NULL to clear any previous bounder.
1083 As a convenience, the parameter passed is also returned.
1084 If a previous bounder exists, its reference count is decremented.
1085 If bounder is not NULL, its reference count is incremented.
1086 @param bounder the new bounder (or NULL) to be installed in the canvas
1087 @return the set bounder object
1088 */
1089 virtual SkBounder* setBounder(SkBounder* bounder);
reed@google.com4b226022011-01-11 18:32:13 +00001090
reed@android.com8a1c16f2008-12-17 15:59:43 +00001091 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001092 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001093 @return the canvas' filter (or NULL).
1094 */
1095 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001096
reed@android.com8a1c16f2008-12-17 15:59:43 +00001097 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1098 As a convenience, the parameter is returned. If an existing filter
1099 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001100 refcnt is incremented. The filter is saved/restored, just like the
1101 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001102 @param filter the new filter (or NULL)
1103 @return the new filter
1104 */
1105 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
1106
1107 //////////////////////////////////////////////////////////////////////////
1108
reed@google.com754de5f2014-02-24 19:38:20 +00001109 /**
1110 * Return true if the current clip is empty (i.e. nothing will draw).
1111 * Note: this is not always a free call, so it should not be used
1112 * more often than necessary. However, once the canvas has computed this
1113 * result, subsequent calls will be cheap (until the clip state changes,
1114 * which can happen on any clip..() or restore() call.
1115 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001116 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001117
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001118 /**
1119 * Returns true if the current clip is just a (non-empty) rectangle.
1120 * Returns false if the clip is empty, or if it is complex.
1121 */
1122 virtual bool isClipRect() const;
1123
reed@android.com8a1c16f2008-12-17 15:59:43 +00001124 /** Return the current matrix on the canvas.
1125 This does not account for the translate in any of the devices.
1126 @return The current matrix on the canvas.
1127 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001128 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001129
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001130#ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE
tomhudson@google.combcb671c2011-09-13 15:07:58 +00001131 enum ClipType {
1132 kEmpty_ClipType = 0,
1133 kRect_ClipType,
1134 kComplex_ClipType
1135 };
tomhudson@google.combcb671c2011-09-13 15:07:58 +00001136 /** Returns a description of the total clip; may be cheaper than
1137 getting the clip and querying it directly.
1138 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001139 virtual ClipType getClipType() const;
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001140#endif
tomhudson@google.combcb671c2011-09-13 15:07:58 +00001141
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001142#ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP
reed@google.com44699382013-10-31 17:28:30 +00001143 /** DEPRECATED -- need to move this guy to private/friend
1144 * Return the current device clip (concatenation of all clip calls).
reed@google.coma707f602012-04-12 16:12:16 +00001145 * This does not account for the translate in any of the devices.
1146 * @return the current device clip (concatenation of all clip calls).
reed@google.com5e2457e2011-10-10 21:24:37 +00001147 */
reed@google.coma707f602012-04-12 16:12:16 +00001148 const SkRegion& getTotalClip() const;
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001149#endif
reed@google.com5e2457e2011-10-10 21:24:37 +00001150
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001151 /** Return the clip stack. The clip stack stores all the individual
1152 * clips organized by the save/restore frame in which they were
1153 * added.
1154 * @return the current clip stack ("list" of individual clip elements)
1155 */
1156 const SkClipStack* getClipStack() const {
1157 return &fClipStack;
1158 }
1159
reed@google.com90c07ea2012-04-13 13:50:27 +00001160 class ClipVisitor {
1161 public:
justinlin@google.com20a550c2012-07-27 17:37:12 +00001162 virtual ~ClipVisitor();
reed@google.com90c07ea2012-04-13 13:50:27 +00001163 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
commit-bot@chromium.orge5b2af92014-02-16 13:25:24 +00001164 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
reed@google.com90c07ea2012-04-13 13:50:27 +00001165 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1166 };
1167
1168 /**
1169 * Replays the clip operations, back to front, that have been applied to
1170 * the canvas, calling the appropriate method on the visitor for each
1171 * clip. All clips have already been transformed into device space.
1172 */
1173 void replayClips(ClipVisitor*) const;
1174
reed@android.com8a1c16f2008-12-17 15:59:43 +00001175 ///////////////////////////////////////////////////////////////////////////
1176
1177 /** After calling saveLayer(), there can be any number of devices that make
1178 up the top-most drawing area. LayerIter can be used to iterate through
1179 those devices. Note that the iterator is only valid until the next API
1180 call made on the canvas. Ownership of all pointers in the iterator stays
1181 with the canvas, so none of them should be modified or deleted.
1182 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +00001183 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001184 public:
1185 /** Initialize iterator with canvas, and set values for 1st device */
1186 LayerIter(SkCanvas*, bool skipEmptyClips);
1187 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +00001188
reed@android.com8a1c16f2008-12-17 15:59:43 +00001189 /** Return true if the iterator is done */
1190 bool done() const { return fDone; }
1191 /** Cycle to the next device */
1192 void next();
reed@google.com4b226022011-01-11 18:32:13 +00001193
reed@android.com8a1c16f2008-12-17 15:59:43 +00001194 // These reflect the current device in the iterator
1195
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001196 SkBaseDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001197 const SkMatrix& matrix() const;
1198 const SkRegion& clip() const;
1199 const SkPaint& paint() const;
1200 int x() const;
1201 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001202
reed@android.com8a1c16f2008-12-17 15:59:43 +00001203 private:
1204 // used to embed the SkDrawIter object directly in our instance, w/o
1205 // having to expose that class def to the public. There is an assert
1206 // in our constructor to ensure that fStorage is large enough
1207 // (though needs to be a compile-time-assert!). We use intptr_t to work
1208 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001209 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001210 class SkDrawIter* fImpl; // this points at fStorage
1211 SkPaint fDefaultPaint;
1212 bool fDone;
1213 };
1214
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001215 // don't call
1216 const SkRegion& internal_private_getTotalClip() const;
1217 // don't call
1218 void internal_private_getTotalClipAsPath(SkPath*) const;
reed@google.com9c135db2014-03-12 18:28:35 +00001219 // don't call
1220 GrRenderTarget* internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001221
reed@android.com8a1c16f2008-12-17 15:59:43 +00001222protected:
reed@google.com76f10a32014-02-05 15:32:21 +00001223 // default impl defers to getDevice()->newSurface(info)
1224 virtual SkSurface* onNewSurface(const SkImageInfo&);
1225
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001226 // default impl defers to its device
1227 virtual const void* onPeekPixels(SkImageInfo*, size_t* rowBytes);
reed@google.com9c135db2014-03-12 18:28:35 +00001228 virtual void* onAccessTopLayerPixels(SkImageInfo*, size_t* rowBytes);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001229
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001230 // Subclass save/restore notifiers.
1231 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1232 // willSaveLayer()'s return value may suppress full layer allocation.
1233 enum SaveLayerStrategy {
1234 kFullLayer_SaveLayerStrategy,
1235 kNoLayer_SaveLayerStrategy
1236 };
1237 virtual void willSave(SaveFlags);
1238 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags);
1239 virtual void willRestore();
1240
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001241 virtual void didTranslate(SkScalar, SkScalar);
1242 virtual void didScale(SkScalar, SkScalar);
1243 virtual void didRotate(SkScalar);
1244 virtual void didSkew(SkScalar, SkScalar);
1245 virtual void didConcat(const SkMatrix&);
1246 virtual void didSetMatrix(const SkMatrix&);
1247
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001248 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1249
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001250 enum ClipEdgeStyle {
1251 kHard_ClipEdgeStyle,
1252 kSoft_ClipEdgeStyle
1253 };
1254
1255 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1256 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1257 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1258 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1259
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001260 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001261 // returns this. Subclasses that encapsulate an indirect canvas may
1262 // need to overload this method. The impl must keep track of this, as it
1263 // is not released or deleted by the caller.
1264 virtual SkCanvas* canvasForDrawIter();
1265
junov@chromium.orga907ac32012-02-24 21:54:07 +00001266 // Clip rectangle bounds. Called internally by saveLayer.
1267 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001268 // If non-NULL, The imageFilter parameter will be used to expand the clip
1269 // and offscreen bounds for any margin required by the filter DAG.
junov@chromium.orga907ac32012-02-24 21:54:07 +00001270 bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001271 SkIRect* intersection,
1272 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001273
junov@chromium.orged8d6bb2013-05-29 19:09:48 +00001274 // Called by child classes that override clipPath and clipRRect to only
1275 // track fast conservative clip bounds, rather than exact clips.
commit-bot@chromium.org759cf482014-03-06 13:18:07 +00001276 void updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op,
junov@chromium.orged8d6bb2013-05-29 19:09:48 +00001277 bool inverseFilled);
1278
reed@google.com97af1a62012-08-28 12:19:02 +00001279 // notify our surface (if we have one) that we are about to draw, so it
1280 // can perform copy-on-write or invalidate any cached images
1281 void predrawNotify();
1282
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001283 virtual void onPushCull(const SkRect& cullRect);
1284 virtual void onPopCull();
1285
reed@android.com8a1c16f2008-12-17 15:59:43 +00001286private:
1287 class MCRec;
1288
reed@google.com5c3d1472011-02-22 19:12:23 +00001289 SkClipStack fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001290 SkDeque fMCStack;
1291 // points to top of stack
1292 MCRec* fMCRec;
1293 // the first N recs that can fit here mean we won't call malloc
1294 uint32_t fMCRecStorage[32];
1295
1296 SkBounder* fBounder;
junov@chromium.orgb0a7ace2012-04-05 18:33:23 +00001297 int fSaveLayerCount; // number of successful saveLayer calls
commit-bot@chromium.org210ae2a2014-02-27 17:40:13 +00001298 int fCullCount; // number of active culls
reed@android.com8a1c16f2008-12-17 15:59:43 +00001299
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001300 SkMetaData* fMetaData;
1301
reed@google.com97af1a62012-08-28 12:19:02 +00001302 SkSurface_Base* fSurfaceBase;
1303 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1304 void setSurfaceBase(SkSurface_Base* sb) {
1305 fSurfaceBase = sb;
1306 }
1307 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001308 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001309
reed@android.com8a1c16f2008-12-17 15:59:43 +00001310 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1311 void updateDeviceCMCache();
1312
reed@google.com9c135db2014-03-12 18:28:35 +00001313 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001314 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001315 friend class SkLua; // needs top layer size and offset
1316 friend class SkDeferredDevice; // needs getTopDevice()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001317
commit-bot@chromium.org15a14052014-02-16 00:59:25 +00001318 SkBaseDevice* createLayerDevice(const SkImageInfo&);
bsalomon@google.come97f0852011-06-17 13:10:25 +00001319
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001320 SkBaseDevice* init(SkBaseDevice*);
reed@google.comf0b5e112011-09-07 11:57:34 +00001321
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001322 /**
1323 * DEPRECATED
1324 *
1325 * Specify a device for this canvas to draw into. If it is not null, its
1326 * reference count is incremented. If the canvas was already holding a
1327 * device, its reference count is decremented. The new device is returned.
1328 */
1329 SkBaseDevice* setRootDevice(SkBaseDevice* device);
skia.committer@gmail.com31acdea2014-02-18 03:01:51 +00001330
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00001331 /**
1332 * Gets the size/origin of the top level layer in global canvas coordinates. We don't want this
1333 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1334 */
1335 SkISize getTopLayerSize() const;
1336 SkIPoint getTopLayerOrigin() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001337
reed@google.comf0b5e112011-09-07 11:57:34 +00001338 // internal methods are not virtual, so they can safely be called by other
1339 // canvas apis, without confusing subclasses (like SkPictureRecording)
robertphillips@google.com9bf380c2013-07-25 12:10:42 +00001340 void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
reed@google.com71121732012-09-18 15:14:33 +00001341 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001342 const SkRect& dst, const SkPaint* paint,
1343 DrawBitmapRectFlags flags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001344 void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1345 const SkRect& dst, const SkPaint* paint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001346 void internalDrawPaint(const SkPaint& paint);
reed@google.com8926b162012-03-23 15:36:36 +00001347 int internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001348 SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy);
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001349 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001350
reed@android.com8a1c16f2008-12-17 15:59:43 +00001351 // shared by save() and saveLayer()
1352 int internalSave(SaveFlags flags);
1353 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001354 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1355 const SkRect& r, SkScalar textSize);
1356 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1357 const char text[], size_t byteLength,
1358 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001359
reed@android.com8a1c16f2008-12-17 15:59:43 +00001360 /* These maintain a cache of the clip bounds in local coordinates,
1361 (converted to 2s-compliment if floats are slow).
1362 */
reed@google.comc0784db2013-12-13 21:16:12 +00001363 mutable SkRect fCachedLocalClipBounds;
1364 mutable bool fCachedLocalClipBoundsDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001365 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001366 bool fAllowSimplifyClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001367
reed@google.comc0784db2013-12-13 21:16:12 +00001368 const SkRect& getLocalClipBounds() const {
1369 if (fCachedLocalClipBoundsDirty) {
1370 if (!this->getClipBounds(&fCachedLocalClipBounds)) {
1371 fCachedLocalClipBounds.setEmpty();
1372 }
1373 fCachedLocalClipBoundsDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001374 }
reed@google.comc0784db2013-12-13 21:16:12 +00001375 return fCachedLocalClipBounds;
reed@android.comba09de42010-02-05 20:46:05 +00001376 }
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001377
reed@google.com5c3d1472011-02-22 19:12:23 +00001378 class AutoValidateClip : ::SkNoncopyable {
1379 public:
1380 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1381 fCanvas->validateClip();
1382 }
1383 ~AutoValidateClip() { fCanvas->validateClip(); }
1384
1385 private:
1386 const SkCanvas* fCanvas;
1387 };
1388
1389#ifdef SK_DEBUG
commit-bot@chromium.org520cf8b2014-03-20 20:25:14 +00001390 // The cull stack rects are in device-space
1391 SkTDArray<SkIRect> fCullStack;
1392 void validateCull(const SkIRect&);
reed@google.com5c3d1472011-02-22 19:12:23 +00001393 void validateClip() const;
1394#else
1395 void validateClip() const {}
1396#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001397
1398 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001399};
1400
1401/** Stack helper class to automatically call restoreToCount() on the canvas
1402 when this object goes out of scope. Use this to guarantee that the canvas
1403 is restored to a known state.
1404*/
1405class SkAutoCanvasRestore : SkNoncopyable {
1406public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001407 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1408 if (fCanvas) {
1409 fSaveCount = canvas->getSaveCount();
1410 if (doSave) {
1411 canvas->save();
1412 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001413 }
1414 }
1415 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001416 if (fCanvas) {
1417 fCanvas->restoreToCount(fSaveCount);
1418 }
1419 }
1420
1421 /**
1422 * Perform the restore now, instead of waiting for the destructor. Will
1423 * only do this once.
1424 */
1425 void restore() {
1426 if (fCanvas) {
1427 fCanvas->restoreToCount(fSaveCount);
1428 fCanvas = NULL;
1429 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001430 }
1431
1432private:
1433 SkCanvas* fCanvas;
1434 int fSaveCount;
1435};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001436#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001437
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001438/** Stack helper class to automatically open and close a comment block
1439 */
1440class SkAutoCommentBlock : SkNoncopyable {
1441public:
1442 SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
1443 fCanvas = canvas;
1444 if (NULL != fCanvas) {
1445 fCanvas->beginCommentGroup(description);
1446 }
1447 }
1448
1449 ~SkAutoCommentBlock() {
1450 if (NULL != fCanvas) {
1451 fCanvas->endCommentGroup();
1452 }
1453 }
1454
1455private:
1456 SkCanvas* fCanvas;
1457};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001458#define SkAutoCommentBlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoCommentBlock)
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001459
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001460/**
1461 * If the caller wants read-only access to the pixels in a canvas, it can just
1462 * call canvas->peekPixels(), since that is the fastest way to "peek" at the
1463 * pixels on a raster-backed canvas.
1464 *
1465 * If the canvas has pixels, but they are not readily available to the CPU
1466 * (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will
1467 * succeed (though be slower, since it will return a copy of the pixels).
1468 *
1469 * SkAutoROCanvasPixels encapsulates these two techniques, trying first to call
1470 * peekPixels() (for performance), but if that fails, calling readPixels() and
1471 * storing the copy locally.
1472 *
1473 * The caller must respect the restrictions associated with peekPixels(), since
1474 * that may have been called: The returned information is invalidated if...
1475 * - any API is called on the canvas (or its parent surface if present)
1476 * - the canvas goes out of scope
1477 */
1478class SkAutoROCanvasPixels : SkNoncopyable {
1479public:
1480 SkAutoROCanvasPixels(SkCanvas* canvas);
1481
1482 // returns NULL on failure
1483 const void* addr() const { return fAddr; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001484
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001485 // undefined if addr() == NULL
1486 size_t rowBytes() const { return fRowBytes; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001487
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001488 // undefined if addr() == NULL
1489 const SkImageInfo& info() const { return fInfo; }
1490
1491 // helper that, if returns true, installs the pixels into the bitmap. Note
1492 // that the bitmap may reference the address returned by peekPixels(), so
1493 // the caller must respect the restrictions associated with peekPixels().
1494 bool asROBitmap(SkBitmap*) const;
1495
1496private:
1497 SkBitmap fBitmap; // used if peekPixels() fails
1498 const void* fAddr; // NULL on failure
1499 SkImageInfo fInfo;
1500 size_t fRowBytes;
1501};
1502
reed@android.com8a1c16f2008-12-17 15:59:43 +00001503#endif