blob: a57f4cd943e4af5322467f9e42dab3872af5d324 [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"
reed4a8126e2014-09-22 07:29:03 -070019#include "SkSurfaceProps.h"
reed@android.com845fdac2009-06-23 03:01:32 +000020#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000021
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000022class SkBaseDevice;
reed6a070dc2014-11-11 19:36:09 -080023class SkCanvasClipVisitor;
reed@android.com8a1c16f2008-12-17 15:59:43 +000024class SkDraw;
reed3cb38402015-02-06 08:36:15 -080025class SkDrawable;
reed@android.com8a1c16f2008-12-17 15:59:43 +000026class SkDrawFilter;
piotaixrb5fae932014-09-24 13:03:30 -070027class SkImage;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000028class SkMetaData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000029class SkPicture;
reed@google.com4ed0fb72012-12-12 20:48:18 +000030class SkRRect;
reed@google.com76f10a32014-02-05 15:32:21 +000031class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000032class SkSurface_Base;
fmalita00d5c2c2014-08-21 08:53:26 -070033class SkTextBlob;
commit-bot@chromium.org644629c2013-11-21 06:21:58 +000034class GrContext;
reed@google.com9c135db2014-03-12 18:28:35 +000035class GrRenderTarget;
reed@android.com8a1c16f2008-12-17 15:59:43 +000036
reedfa35f8e2014-09-04 12:14:36 -070037class SkCanvasState;
38
reed@android.com8a1c16f2008-12-17 15:59:43 +000039/** \class SkCanvas
40
41 A Canvas encapsulates all of the state about drawing into a device (bitmap).
42 This includes a reference to the device itself, and a stack of matrix/clip
43 values. For any given draw call (e.g. drawRect), the geometry of the object
44 being drawn is transformed by the concatenation of all the matrices in the
45 stack. The transformed geometry is clipped by the intersection of all of
46 the clips in the stack.
47
48 While the Canvas holds the state of the drawing device, the state (style)
49 of the object being drawn is held by the Paint, which is provided as a
50 parameter to each of the draw() methods. The Paint holds attributes such as
51 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
52 etc.
53*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000054class SK_API SkCanvas : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000055public:
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +000056 SK_DECLARE_INST_COUNT(SkCanvas)
57
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000058 /**
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000059 * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
60 * specified pixels. To access the pixels after drawing to them, the caller should call
61 * flush() or call peekPixels(...).
62 *
63 * On failure, return NULL. This can fail for several reasons:
64 * 1. invalid ImageInfo (e.g. negative dimensions)
65 * 2. unsupported ImageInfo for a canvas
66 * - kUnknown_SkColorType, kIndex_8_SkColorType
67 * - kIgnore_SkAlphaType
68 * - this list is not complete, so others may also be unsupported
69 *
70 * Note: it is valid to request a supported ImageInfo, but with zero
71 * dimensions.
72 */
73 static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t);
74
75 static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
76 return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
77 }
78
79 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000080 * Creates an empty canvas with no backing device/pixels, and zero
81 * dimensions.
82 */
reed@google.comcde92112011-07-06 20:00:52 +000083 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000084
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000085 /**
86 * Creates a canvas of the specified dimensions, but explicitly not backed
87 * by any device/pixels. Typically this use used by subclasses who handle
88 * the draw calls in some other way.
89 */
reed96a857e2015-01-25 10:33:58 -080090 SkCanvas(int width, int height, const SkSurfaceProps* = NULL);
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000091
reed@google.com6dc74552011-07-21 18:00:46 +000092 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +000093
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000094 @param device Specifies a device for the canvas to draw into.
95 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000096 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000097
reed@google.com44699382013-10-31 17:28:30 +000098 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +000099 @param bitmap Specifies a bitmap for the canvas to draw into. Its
100 structure are copied to the canvas.
101 */
102 explicit SkCanvas(const SkBitmap& bitmap);
fmalita3d91aad2015-02-02 05:25:04 -0800103
104 /** Construct a canvas with the specified bitmap to draw into.
105 @param bitmap Specifies a bitmap for the canvas to draw into. Its
106 structure are copied to the canvas.
107 @param props New canvas surface properties.
108 */
109 SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
110
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111 virtual ~SkCanvas();
112
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000113 SkMetaData& getMetaData();
114
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000115 /**
116 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
117 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
118 */
119 SkImageInfo imageInfo() const;
120
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121 ///////////////////////////////////////////////////////////////////////////
122
reed@google.com210ce002011-11-01 14:24:23 +0000123 /**
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000124 * Trigger the immediate execution of all pending draw operations.
125 */
126 void flush();
127
128 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000129 * Gets the size of the base or root layer in global canvas coordinates. The
130 * origin of the base layer is always (0,0). The current drawable area may be
131 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000132 */
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000133 SkISize getBaseLayerSize() const;
134
135 /**
136 * DEPRECATED: call getBaseLayerSize
137 */
138 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000139
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000140 /**
141 * DEPRECATED.
142 * Return the canvas' device object, which may be null. The device holds
143 * the bitmap of the pixels that the canvas draws into. The reference count
144 * of the returned device is not changed by this call.
145 */
reed52d9ac62014-06-30 09:05:34 -0700146#ifndef SK_SUPPORT_LEGACY_GETDEVICE
147protected: // Can we make this private?
148#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000149 SkBaseDevice* getDevice() const;
reed52d9ac62014-06-30 09:05:34 -0700150public:
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151
reed@google.com9266fed2011-03-30 00:18:03 +0000152 /**
153 * saveLayer() can create another device (which is later drawn onto
154 * the previous device). getTopDevice() returns the top-most device current
155 * installed. Note that this can change on other calls like save/restore,
156 * so do not access this device after subsequent canvas calls.
157 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000158 *
159 * @param updateMatrixClip If this is true, then before the device is
160 * returned, we ensure that its has been notified about the current
161 * matrix and clip. Note: this happens automatically when the device
162 * is drawn to, but is optional here, as there is a small perf hit
163 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000164 */
reed@google.com9c135db2014-03-12 18:28:35 +0000165#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
166private:
167#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000168 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000169public:
reed@google.com9266fed2011-03-30 00:18:03 +0000170
reed@google.com76f10a32014-02-05 15:32:21 +0000171 /**
172 * Create a new surface matching the specified info, one that attempts to
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000173 * be maximally compatible when used with this canvas. If there is no matching Surface type,
174 * NULL is returned.
reed4a8126e2014-09-22 07:29:03 -0700175 *
176 * If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
177 * inherits the properties of the surface that owns this canvas. If this canvas has no parent
178 * surface, then the new surface is created with default properties.
reed@google.com76f10a32014-02-05 15:32:21 +0000179 */
reed4a8126e2014-09-22 07:29:03 -0700180 SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps* = NULL);
bsalomon@google.come97f0852011-06-17 13:10:25 +0000181
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000182 /**
183 * Return the GPU context of the device that is associated with the canvas.
184 * For a canvas with non-GPU device, NULL is returned.
185 */
186 GrContext* getGrContext();
187
reed@google.com4b226022011-01-11 18:32:13 +0000188 ///////////////////////////////////////////////////////////////////////////
189
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000190 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000191 * If the canvas has writable pixels in its top layer (and is not recording to a picture
192 * or other non-raster target) and has direct access to its pixels (i.e. they are in
193 * local RAM) return the address of those pixels, and if not null,
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000194 * return the ImageInfo, rowBytes and origin. The returned address is only valid
reed@google.com9c135db2014-03-12 18:28:35 +0000195 * while the canvas object is in scope and unchanged. Any API calls made on
196 * canvas (or its parent surface if any) will invalidate the
197 * returned address (and associated information).
198 *
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000199 * On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
reed@google.com9c135db2014-03-12 18:28:35 +0000200 */
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000201 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
reed@google.com9c135db2014-03-12 18:28:35 +0000202
203 /**
204 * If the canvas has readable pixels in its base layer (and is not recording to a picture
205 * 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 +0000206 * local RAM) return the const-address of those pixels, and if not null,
207 * return the ImageInfo and rowBytes. The returned address is only valid
208 * while the canvas object is in scope and unchanged. Any API calls made on
209 * canvas (or its parent surface if any) will invalidate the
210 * returned address (and associated information).
211 *
212 * On failure, returns NULL and the info and rowBytes parameters are
213 * ignored.
214 */
215 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
216
reed@google.com4b226022011-01-11 18:32:13 +0000217 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000218 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
219 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
reedb184f7f2014-07-13 04:32:32 -0700220 * starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000221 *
reedb184f7f2014-07-13 04:32:32 -0700222 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000223 *
reedb184f7f2014-07-13 04:32:32 -0700224 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000225 *
reedb184f7f2014-07-13 04:32:32 -0700226 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
227 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
228 * corresponding src pixels, performing any colortype/alphatype transformations needed
229 * (in the case where the src and dst have different colortypes or alphatypes).
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000230 *
231 * This call can fail, returning false, for several reasons:
reedb184f7f2014-07-13 04:32:32 -0700232 * - If srcR does not intersect the base-layer bounds.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000233 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
234 * - If this canvas is not backed by pixels (e.g. picture or PDF)
235 */
reedb184f7f2014-07-13 04:32:32 -0700236 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
237 int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000238
239 /**
240 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
241 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
242 * it calls through to readPixels(info, ...) and returns its result.
243 */
reedb184f7f2014-07-13 04:32:32 -0700244 bool readPixels(SkBitmap* bitmap, int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000245
246 /**
247 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
248 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
249 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
250 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000251 */
252 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000253
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000254 /**
255 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
256 * ignoring the matrix and clip.
257 *
258 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
259 *
260 * target.setXYWH(x, y, info.width(), info.height());
261 *
262 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
263 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
264 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
265 * pixels, performing any colortype/alphatype transformations needed (in the case where the
266 * src and dst have different colortypes or alphatypes).
267 *
268 * This call can fail, returning false, for several reasons:
269 * - If the src colortype/alphatype cannot be converted to the canvas' types
270 * - If this canvas is not backed by pixels (e.g. picture or PDF)
271 */
272 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
273
274 /**
275 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
276 * is just wrapping a texture, returns false and does nothing.
277 */
278 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000279
reed@android.com8a1c16f2008-12-17 15:59:43 +0000280 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000281
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282 enum SaveFlags {
283 /** save the matrix state, restoring it on restore() */
Florin Malita5f6102d2014-06-30 10:13:28 -0400284 // [deprecated] kMatrix_SaveFlag = 0x01,
fmalita696d3612014-07-01 11:55:41 -0700285 kMatrix_SaveFlag = 0x01,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286 /** save the clip state, restoring it on restore() */
Florin Malita5f6102d2014-06-30 10:13:28 -0400287 // [deprecated] kClip_SaveFlag = 0x02,
fmalita696d3612014-07-01 11:55:41 -0700288 kClip_SaveFlag = 0x02,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000289 /** the layer needs to support per-pixel alpha */
290 kHasAlphaLayer_SaveFlag = 0x04,
291 /** the layer needs to support 8-bits per color component */
292 kFullColorLayer_SaveFlag = 0x08,
reed@google.comb93ba452014-03-10 19:47:58 +0000293 /**
294 * the layer should clip against the bounds argument
295 *
296 * if SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG is undefined, this is treated as always on.
297 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 kClipToLayer_SaveFlag = 0x10,
299
300 // helper masks for common choices
Florin Malita5f6102d2014-06-30 10:13:28 -0400301 // [deprecated] kMatrixClip_SaveFlag = 0x03,
fmalita696d3612014-07-01 11:55:41 -0700302 kMatrixClip_SaveFlag = 0x03,
reed@google.comb93ba452014-03-10 19:47:58 +0000303#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304 kARGB_NoClipLayer_SaveFlag = 0x0F,
reed@google.comb93ba452014-03-10 19:47:58 +0000305#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000306 kARGB_ClipLayer_SaveFlag = 0x1F
307 };
308
reed@android.comdc3381f2010-02-11 16:05:15 +0000309 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000311 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
312 operate on this copy.
313 When the balancing call to restore() is made, the previous matrix, clip,
314 and drawFilter are restored.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000315
316 @return The value to pass to restoreToCount() to balance this save()
317 */
318 int save();
319
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320 /** This behaves the same as save(), but in addition it allocates an
321 offscreen bitmap. All drawing calls are directed there, and only when
322 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000323 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000324 @param bounds (may be null) This rect, if non-null, is used as a hint to
325 limit the size of the offscreen, and thus drawing may be
326 clipped to it, though that clipping is not guaranteed to
327 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000328 @param paint (may be null) This is copied, and is applied to the
329 offscreen when restore() is called
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000330 @return The value to pass to restoreToCount() to balance this save()
331 */
332 int saveLayer(const SkRect* bounds, const SkPaint* paint);
333
334 /** DEPRECATED - use saveLayer(const SkRect*, const SkPaint*) instead.
335
336 This behaves the same as saveLayer(const SkRect*, const SkPaint*),
337 but it allows fine-grained control of which state bits to be saved
338 (and subsequently restored).
339
340 @param bounds (may be null) This rect, if non-null, is used as a hint to
341 limit the size of the offscreen, and thus drawing may be
342 clipped to it, though that clipping is not guaranteed to
343 happen. If exact clipping is desired, use clipRect().
344 @param paint (may be null) This is copied, and is applied to the
345 offscreen when restore() is called
reed@android.com8a1c16f2008-12-17 15:59:43 +0000346 @param flags LayerFlags
347 @return The value to pass to restoreToCount() to balance this save()
348 */
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000349 SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
350 int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000351
352 /** This behaves the same as save(), but in addition it allocates an
353 offscreen bitmap. All drawing calls are directed there, and only when
354 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000355 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000356 @param bounds (may be null) This rect, if non-null, is used as a hint to
357 limit the size of the offscreen, and thus drawing may be
358 clipped to it, though that clipping is not guaranteed to
359 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000360 @param alpha This is applied to the offscreen when restore() is called.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000361 @return The value to pass to restoreToCount() to balance this save()
362 */
363 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
364
365 /** DEPRECATED - use saveLayerAlpha(const SkRect*, U8CPU) instead.
366
367 This behaves the same as saveLayerAlpha(const SkRect*, U8CPU),
368 but it allows fine-grained control of which state bits to be saved
369 (and subsequently restored).
370
371 @param bounds (may be null) This rect, if non-null, is used as a hint to
372 limit the size of the offscreen, and thus drawing may be
373 clipped to it, though that clipping is not guaranteed to
374 happen. If exact clipping is desired, use clipRect().
375 @param alpha This is applied to the offscreen when restore() is called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000376 @param flags LayerFlags
377 @return The value to pass to restoreToCount() to balance this save()
378 */
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000379 SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
380 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, SaveFlags flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381
382 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000383 modifications to the matrix/clip/drawFilter state since the last save
384 call.
385 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000386 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000387 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000388
389 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000390 This will equal # save() calls - # restore() calls + 1. The save count on
391 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000393 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000394
395 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000396 count reached saveCount. It is an error for saveCount to be greater than
397 getSaveCount(). To pop all the way back to the initial matrix/clip context
398 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000399 @param saveCount The number of save() levels to restore from
400 */
401 void restoreToCount(int saveCount);
402
403 /** Preconcat the current matrix with the specified translation
404 @param dx The distance to translate in X
405 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000406 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000407 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408
409 /** Preconcat the current matrix with the specified scale.
410 @param sx The amount to scale in X
411 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000412 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000413 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414
415 /** Preconcat the current matrix with the specified rotation.
416 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000418 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419
420 /** Preconcat the current matrix with the specified skew.
421 @param sx The amount to skew in X
422 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000424 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425
426 /** Preconcat the current matrix with the specified matrix.
427 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000429 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000430
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431 /** Replace the current matrix with a copy of the specified matrix.
432 @param matrix The matrix that will be copied into the current matrix.
433 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000434 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000435
reed@android.com8a1c16f2008-12-17 15:59:43 +0000436 /** Helper for setMatrix(identity). Sets the current matrix to identity.
437 */
438 void resetMatrix();
439
reed@google.com4ed0fb72012-12-12 20:48:18 +0000440 /**
441 * Modify the current clip with the specified rectangle.
442 * @param rect The rect to combine with the current clip
443 * @param op The region op to apply to the current clip
444 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000445 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000446 void clipRect(const SkRect& rect,
447 SkRegion::Op op = SkRegion::kIntersect_Op,
448 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000449
reed@google.com4ed0fb72012-12-12 20:48:18 +0000450 /**
451 * Modify the current clip with the specified SkRRect.
452 * @param rrect The rrect to combine with the current clip
453 * @param op The region op to apply to the current clip
454 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000455 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000456 void clipRRect(const SkRRect& rrect,
457 SkRegion::Op op = SkRegion::kIntersect_Op,
458 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000459
460 /**
461 * Modify the current clip with the specified path.
462 * @param path The path to combine with the current clip
463 * @param op The region op to apply to the current clip
464 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000465 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000466 void clipPath(const SkPath& path,
467 SkRegion::Op op = SkRegion::kIntersect_Op,
468 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000469
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000470 /** EXPERIMENTAL -- only used for testing
471 Set to false to force clips to be hard, even if doAntiAlias=true is
472 passed to clipRect or clipPath.
473 */
474 void setAllowSoftClip(bool allow) {
475 fAllowSoftClip = allow;
476 }
477
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000478 /** EXPERIMENTAL -- only used for testing
479 Set to simplify clip stack using path ops.
480 */
481 void setAllowSimplifyClip(bool allow) {
482 fAllowSimplifyClip = allow;
483 }
484
reed@android.com8a1c16f2008-12-17 15:59:43 +0000485 /** Modify the current clip with the specified region. Note that unlike
486 clipRect() and clipPath() which transform their arguments by the current
487 matrix, clipRegion() assumes its argument is already in device
488 coordinates, and so no transformation is performed.
489 @param deviceRgn The region to apply to the current clip
490 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000491 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000492 void clipRegion(const SkRegion& deviceRgn,
493 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000494
495 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
496 specified region. This does not intersect or in any other way account
497 for the existing clip region.
498 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000499 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000500 void setClipRegion(const SkRegion& deviceRgn) {
501 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000502 }
503
reed@android.com8a1c16f2008-12-17 15:59:43 +0000504 /** Return true if the specified rectangle, after being transformed by the
505 current matrix, would lie completely outside of the current clip. Call
506 this to check if an area you intend to draw into is clipped out (and
507 therefore you can skip making the draw calls).
508 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000509 @return true if the rect (transformed by the canvas' matrix) does not
510 intersect with the canvas' clip
511 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000512 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000513
514 /** Return true if the specified path, after being transformed by the
515 current matrix, would lie completely outside of the current clip. Call
516 this to check if an area you intend to draw into is clipped out (and
517 therefore you can skip making the draw calls). Note, for speed it may
518 return false even if the path itself might not intersect the clip
519 (i.e. the bounds of the path intersects, but the path does not).
520 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000521 @return true if the path (transformed by the canvas' matrix) does not
522 intersect with the canvas' clip
523 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000524 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000525
526 /** Return true if the horizontal band specified by top and bottom is
527 completely clipped out. This is a conservative calculation, meaning
528 that it is possible that if the method returns false, the band may still
529 in fact be clipped out, but the converse is not true. If this method
530 returns true, then the band is guaranteed to be clipped out.
531 @param top The top of the horizontal band to compare with the clip
532 @param bottom The bottom of the horizontal and to compare with the clip
533 @return true if the horizontal band is completely clipped out (i.e. does
534 not intersect the current clip)
535 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000536 bool quickRejectY(SkScalar top, SkScalar bottom) const {
reed@google.comc0784db2013-12-13 21:16:12 +0000537 SkASSERT(top <= bottom);
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000538
539#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
540 // TODO: add a hasPerspective method similar to getLocalClipBounds. This
541 // would cache the SkMatrix::hasPerspective result. Alternatively, have
542 // the MC stack just set a hasPerspective boolean as it is updated.
543 if (this->getTotalMatrix().hasPerspective()) {
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000544 // TODO: consider implementing some half-plane test between the
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000545 // two Y planes and the device-bounds (i.e., project the top and
546 // bottom Y planes and then determine if the clip bounds is completely
547 // outside either one).
548 return false;
549 }
550#endif
551
reed@google.comc0784db2013-12-13 21:16:12 +0000552 const SkRect& clipR = this->getLocalClipBounds();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000553 // In the case where the clip is empty and we are provided with a
554 // negative top and positive bottom parameter then this test will return
555 // false even though it will be clipped. We have chosen to exclude that
556 // check as it is rare and would result double the comparisons.
reed@google.comc0784db2013-12-13 21:16:12 +0000557 return top >= clipR.fBottom || bottom <= clipR.fTop;
djsollen@google.com92d2a292012-02-27 16:17:59 +0000558 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000559
560 /** Return the bounds of the current clip (in local coordinates) in the
561 bounds parameter, and return true if it is non-empty. This can be useful
562 in a way similar to quickReject, in that it tells you that drawing
563 outside of these bounds will be clipped out.
564 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000565 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000566
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000567 /** Return the bounds of the current clip, in device coordinates; returns
568 true if non-empty. Maybe faster than getting the clip explicitly and
569 then taking its bounds.
570 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000571 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000572
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000573
reed@android.com8a1c16f2008-12-17 15:59:43 +0000574 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000575 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000576 @param a the alpha component (0..255) of the color to fill the canvas
577 @param r the red component (0..255) of the color to fill the canvas
578 @param g the green component (0..255) of the color to fill the canvas
579 @param b the blue component (0..255) of the color to fill the canvas
580 @param mode the mode to apply the color in (defaults to SrcOver)
581 */
582 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000583 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000584
585 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000586 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587 @param color the color to draw with
588 @param mode the mode to apply the color in (defaults to SrcOver)
589 */
reed8eddfb52014-12-04 07:50:14 -0800590 void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000591
reedf4e0d9e2014-12-05 20:49:03 -0800592 /**
593 * Helper method for drawing a color in SRC mode, completely replacing all the pixels
594 * in the current clip with this color.
595 */
596 void clear(SkColor color) {
reed8eddfb52014-12-04 07:50:14 -0800597 this->drawColor(color, SkXfermode::kSrc_Mode);
598 }
reed@google.com2a981812011-04-14 18:59:28 +0000599
600 /**
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000601 * This makes the contents of the canvas undefined. Subsequent calls that
602 * require reading the canvas contents will produce undefined results. Examples
603 * include blending and readPixels. The actual implementation is backend-
604 * dependent and one legal implementation is to do nothing. Like clear(), this
605 * ignores the clip.
606 *
607 * This function should only be called if the caller intends to subsequently
608 * draw to the canvas. The canvas may do real work at discard() time in order
609 * to optimize performance on subsequent draws. Thus, if you call this and then
610 * never draw to the canvas subsequently you may pay a perfomance penalty.
611 */
612 void discard() { this->onDiscard(); }
613
614 /**
reed@google.com2a981812011-04-14 18:59:28 +0000615 * Fill the entire canvas' bitmap (restricted to the current clip) with the
616 * specified paint.
617 * @param paint The paint used to fill the canvas
618 */
reed0846f1b2015-01-09 14:17:40 -0800619 void drawPaint(const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000620
621 enum PointMode {
622 /** drawPoints draws each point separately */
623 kPoints_PointMode,
624 /** drawPoints draws each pair of points as a line segment */
625 kLines_PointMode,
626 /** drawPoints draws the array of points as a polygon */
627 kPolygon_PointMode
628 };
629
630 /** Draw a series of points, interpreted based on the PointMode mode. For
631 all modes, the count parameter is interpreted as the total number of
632 points. For kLine mode, count/2 line segments are drawn.
633 For kPoint mode, each point is drawn centered at its coordinate, and its
634 size is specified by the paint's stroke-width. It draws as a square,
635 unless the paint's cap-type is round, in which the points are drawn as
636 circles.
637 For kLine mode, each pair of points is drawn as a line segment,
638 respecting the paint's settings for cap/join/width.
639 For kPolygon mode, the entire array is drawn as a series of connected
640 line segments.
641 Note that, while similar, kLine and kPolygon modes draw slightly
642 differently than the equivalent path built with a series of moveto,
643 lineto calls, in that the path will draw all of its contours at once,
644 with no interactions if contours intersect each other (think XOR
645 xfermode). drawPoints always draws each element one at a time.
646 @param mode PointMode specifying how to draw the array of points.
647 @param count The number of points in the array
648 @param pts Array of points to draw
649 @param paint The paint used to draw the points
650 */
reed0846f1b2015-01-09 14:17:40 -0800651 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000652
653 /** Helper method for drawing a single point. See drawPoints() for a more
654 details.
655 */
656 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000657
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658 /** Draws a single pixel in the specified color.
659 @param x The X coordinate of which pixel to draw
660 @param y The Y coordiante of which pixel to draw
661 @param color The color to draw
662 */
663 void drawPoint(SkScalar x, SkScalar y, SkColor color);
664
665 /** Draw a line segment with the specified start and stop x,y coordinates,
666 using the specified paint. NOTE: since a line is always "framed", the
667 paint's Style is ignored.
668 @param x0 The x-coordinate of the start point of the line
669 @param y0 The y-coordinate of the start point of the line
670 @param x1 The x-coordinate of the end point of the line
671 @param y1 The y-coordinate of the end point of the line
672 @param paint The paint used to draw the line
673 */
674 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
675 const SkPaint& paint);
676
677 /** Draw the specified rectangle using the specified paint. The rectangle
678 will be filled or stroked based on the Style in the paint.
679 @param rect The rect to be drawn
680 @param paint The paint used to draw the rect
681 */
reed0846f1b2015-01-09 14:17:40 -0800682 void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000683
684 /** Draw the specified rectangle using the specified paint. The rectangle
685 will be filled or framed based on the Style in the paint.
686 @param rect The rect to be drawn
687 @param paint The paint used to draw the rect
688 */
reed@google.com87001ed2014-02-17 16:28:05 +0000689 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000690 SkRect r;
691 r.set(rect); // promotes the ints to scalars
692 this->drawRect(r, paint);
693 }
reed@google.com4b226022011-01-11 18:32:13 +0000694
reed@android.com8a1c16f2008-12-17 15:59:43 +0000695 /** Draw the specified rectangle using the specified paint. The rectangle
696 will be filled or framed based on the Style in the paint.
697 @param left The left side of the rectangle to be drawn
698 @param top The top side of the rectangle to be drawn
699 @param right The right side of the rectangle to be drawn
700 @param bottom The bottom side of the rectangle to be drawn
701 @param paint The paint used to draw the rect
702 */
703 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
704 SkScalar bottom, const SkPaint& paint);
705
706 /** Draw the specified oval using the specified paint. The oval will be
707 filled or framed based on the Style in the paint.
708 @param oval The rectangle bounds of the oval to be drawn
709 @param paint The paint used to draw the oval
710 */
reed0846f1b2015-01-09 14:17:40 -0800711 void drawOval(const SkRect& oval, const SkPaint&);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000712
713 /**
714 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
715 * based on the Style in the paint.
716 *
717 * @param rrect The round-rect to draw
718 * @param paint The paint used to draw the round-rect
719 */
reed0846f1b2015-01-09 14:17:40 -0800720 void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000721
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000722 /**
723 * Draw the annulus formed by the outer and inner rrects. The results
724 * are undefined if the outer does not contain the inner.
725 */
726 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
727
reed@android.com8a1c16f2008-12-17 15:59:43 +0000728 /** Draw the specified circle using the specified paint. If radius is <= 0,
729 then nothing will be drawn. The circle will be filled
730 or framed based on the Style in the paint.
731 @param cx The x-coordinate of the center of the cirle to be drawn
732 @param cy The y-coordinate of the center of the cirle to be drawn
733 @param radius The radius of the cirle to be drawn
734 @param paint The paint used to draw the circle
735 */
736 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
737 const SkPaint& paint);
738
739 /** Draw the specified arc, which will be scaled to fit inside the
740 specified oval. If the sweep angle is >= 360, then the oval is drawn
741 completely. Note that this differs slightly from SkPath::arcTo, which
742 treats the sweep angle mod 360.
743 @param oval The bounds of oval used to define the shape of the arc
744 @param startAngle Starting angle (in degrees) where the arc begins
745 @param sweepAngle Sweep angle (in degrees) measured clockwise
746 @param useCenter true means include the center of the oval. For filling
747 this will draw a wedge. False means just use the arc.
748 @param paint The paint used to draw the arc
749 */
750 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
751 bool useCenter, const SkPaint& paint);
752
753 /** Draw the specified round-rect using the specified paint. The round-rect
754 will be filled or framed based on the Style in the paint.
755 @param rect The rectangular bounds of the roundRect to be drawn
756 @param rx The x-radius of the oval used to round the corners
757 @param ry The y-radius of the oval used to round the corners
758 @param paint The paint used to draw the roundRect
759 */
760 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
761 const SkPaint& paint);
762
763 /** Draw the specified path using the specified paint. The path will be
764 filled or framed based on the Style in the paint.
765 @param path The path to be drawn
766 @param paint The paint used to draw the path
767 */
reed0846f1b2015-01-09 14:17:40 -0800768 void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000769
piotaixrd52893c2014-09-25 14:39:40 -0700770 /** Draw the specified image, with its top/left corner at (x,y), using the
771 specified paint, transformed by the current matrix.
772
773 @param image The image to be drawn
774 @param left The position of the left side of the image being drawn
775 @param top The position of the top side of the image being drawn
776 @param paint The paint used to draw the image, or NULL
777 */
reed0846f1b2015-01-09 14:17:40 -0800778 void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
piotaixrd52893c2014-09-25 14:39:40 -0700779 /** Draw the specified image, with the specified matrix applied (before the
780 canvas' matrix is applied).
piotaixrb5fae932014-09-24 13:03:30 -0700781
piotaixrd52893c2014-09-25 14:39:40 -0700782 @param image The image to be drawn
783 @param src Optional: specify the subset of the image to be drawn
784 @param dst The destination rectangle where the scaled/translated
785 image will be drawn
786 @param paint The paint used to draw the image, or NULL
787 */
reed0846f1b2015-01-09 14:17:40 -0800788 void drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
789 const SkPaint* paint = NULL);
piotaixrb5fae932014-09-24 13:03:30 -0700790
reed@android.com8a1c16f2008-12-17 15:59:43 +0000791 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
792 specified paint, transformed by the current matrix. Note: if the paint
793 contains a maskfilter that generates a mask which extends beyond the
794 bitmap's original width/height, then the bitmap will be drawn as if it
795 were in a Shader with CLAMP mode. Thus the color outside of the original
796 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000797
798 If a shader is present on the paint it will be ignored, except in the
reed@google.comf20fc242014-03-26 13:44:58 +0000799 case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000800 generated by the shader.
801
reed@android.com8a1c16f2008-12-17 15:59:43 +0000802 @param bitmap The bitmap to be drawn
803 @param left The position of the left side of the bitmap being drawn
804 @param top The position of the top side of the bitmap being drawn
805 @param paint The paint used to draw the bitmap, or NULL
806 */
reed0846f1b2015-01-09 14:17:40 -0800807 void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
808 const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000809
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000810 enum DrawBitmapRectFlags {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000811 kNone_DrawBitmapRectFlag = 0x0,
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000812 /**
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000813 * When filtering is enabled, allow the color samples outside of
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000814 * the src rect (but still in the src bitmap) to bleed into the
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000815 * drawn portion
816 */
robertphillips@google.com31acc112013-08-20 12:13:48 +0000817 kBleed_DrawBitmapRectFlag = 0x1,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000818 };
819
reed@android.com8a1c16f2008-12-17 15:59:43 +0000820 /** Draw the specified bitmap, with the specified matrix applied (before the
821 canvas' matrix is applied).
822 @param bitmap The bitmap to be drawn
823 @param src Optional: specify the subset of the bitmap to be drawn
824 @param dst The destination rectangle where the scaled/translated
825 image will be drawn
826 @param paint The paint used to draw the bitmap, or NULL
827 */
reed0846f1b2015-01-09 14:17:40 -0800828 void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
829 const SkPaint* paint = NULL,
830 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000831
reed@google.com71121732012-09-18 15:14:33 +0000832 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000833 const SkPaint* paint = NULL) {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000834 this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag);
reed@google.com71121732012-09-18 15:14:33 +0000835 }
836
837 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000838 const SkRect& dst, const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000839 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
reed@google.com71121732012-09-18 15:14:33 +0000840 SkRect realSrcStorage;
841 SkRect* realSrcPtr = NULL;
842 if (isrc) {
843 realSrcStorage.set(*isrc);
844 realSrcPtr = &realSrcStorage;
845 }
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000846 this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
reed@google.com71121732012-09-18 15:14:33 +0000847 }
skia.committer@gmail.comc1ad0222012-09-19 02:01:47 +0000848
reed@google.comf0b5e112011-09-07 11:57:34 +0000849 /**
850 * Draw the bitmap stretched differentially to fit into dst.
851 * center is a rect within the bitmap, and logically divides the bitmap
852 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
853 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
854 *
855 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000856 * - The 4 corners are not stretched at all.
857 * - The sides are stretched in only one axis.
858 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000859 * Else, for each axis where dst < bitmap,
860 * - The corners shrink proportionally
861 * - The sides (along the shrink axis) and center are not drawn
862 */
reed0846f1b2015-01-09 14:17:40 -0800863 void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
864 const SkPaint* paint = NULL);
reed@google.comf0b5e112011-09-07 11:57:34 +0000865
reed@android.com8a1c16f2008-12-17 15:59:43 +0000866 /** Draw the specified bitmap, with its top/left corner at (x,y),
867 NOT transformed by the current matrix. Note: if the paint
868 contains a maskfilter that generates a mask which extends beyond the
869 bitmap's original width/height, then the bitmap will be drawn as if it
870 were in a Shader with CLAMP mode. Thus the color outside of the original
871 width/height will be the edge color replicated.
872 @param bitmap The bitmap to be drawn
873 @param left The position of the left side of the bitmap being drawn
874 @param top The position of the top side of the bitmap being drawn
875 @param paint The paint used to draw the bitmap, or NULL
876 */
reed0846f1b2015-01-09 14:17:40 -0800877 void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000878
879 /** Draw the text, with origin at (x,y), using the specified paint.
880 The origin is interpreted based on the Align setting in the paint.
881 @param text The text to be drawn
882 @param byteLength The number of bytes to read from the text parameter
883 @param x The x-coordinate of the origin of the text being drawn
884 @param y The y-coordinate of the origin of the text being drawn
885 @param paint The paint used for the text (e.g. color, size, style)
886 */
reedf7430cc2014-12-21 11:38:35 -0800887 void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
888 const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000889
890 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000891 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000892 @param text The text to be drawn
893 @param byteLength The number of bytes to read from the text parameter
894 @param pos Array of positions, used to position each character
895 @param paint The paint used for the text (e.g. color, size, style)
896 */
reedf7430cc2014-12-21 11:38:35 -0800897 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
898 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000899
reed@android.com8a1c16f2008-12-17 15:59:43 +0000900 /** Draw the text, with each character/glyph origin specified by the x
901 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000902 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000903 @param text The text to be drawn
904 @param byteLength The number of bytes to read from the text parameter
905 @param xpos Array of x-positions, used to position each character
906 @param constY The shared Y coordinate for all of the positions
907 @param paint The paint used for the text (e.g. color, size, style)
908 */
reedf7430cc2014-12-21 11:38:35 -0800909 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
910 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000911
reed@android.com8a1c16f2008-12-17 15:59:43 +0000912 /** Draw the text, with origin at (x,y), using the specified paint, along
913 the specified path. The paint's Align setting determins where along the
914 path to start the text.
915 @param text The text to be drawn
916 @param byteLength The number of bytes to read from the text parameter
917 @param path The path the text should follow for its baseline
918 @param hOffset The distance along the path to add to the text's
919 starting position
920 @param vOffset The distance above(-) or below(+) the path to
921 position the text
922 @param paint The paint used for the text
923 */
reedf7430cc2014-12-21 11:38:35 -0800924 void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925 SkScalar vOffset, const SkPaint& paint);
926
927 /** Draw the text, with origin at (x,y), using the specified paint, along
928 the specified path. The paint's Align setting determins where along the
929 path to start the text.
930 @param text The text to be drawn
931 @param byteLength The number of bytes to read from the text parameter
932 @param path The path the text should follow for its baseline
933 @param matrix (may be null) Applied to the text before it is
934 mapped onto the path
935 @param paint The paint used for the text
936 */
reedf7430cc2014-12-21 11:38:35 -0800937 void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
938 const SkMatrix* matrix, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000939
fmalita00d5c2c2014-08-21 08:53:26 -0700940 /** Draw the text blob, offset by (x,y), using the specified paint.
941 @param blob The text blob to be drawn
942 @param x The x-offset of the text being drawn
943 @param y The y-offset of the text being drawn
944 @param paint The paint used for the text (e.g. color, size, style)
945 */
946 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
947
reed@android.com8a1c16f2008-12-17 15:59:43 +0000948 /** Draw the picture into this canvas. This method effective brackets the
949 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +0000950 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000951 @param picture The recorded drawing commands to playback into this
952 canvas.
953 */
robertphillips9b14f262014-06-04 05:40:44 -0700954 void drawPicture(const SkPicture* picture);
955
reedd5fa1a42014-08-09 11:08:05 -0700956 /**
957 * Draw the picture into this canvas.
958 *
959 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
960 * logically equivalent to
961 * save/concat/drawPicture/restore
962 *
963 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
964 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
965 * This is logically equivalent to
966 * saveLayer(paint)/drawPicture/restore
967 */
968 void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
969
reed@android.com8a1c16f2008-12-17 15:59:43 +0000970 enum VertexMode {
971 kTriangles_VertexMode,
972 kTriangleStrip_VertexMode,
973 kTriangleFan_VertexMode
974 };
reed@google.com4b226022011-01-11 18:32:13 +0000975
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976 /** Draw the array of vertices, interpreted as triangles (based on mode).
commit-bot@chromium.org559a8832014-05-30 10:08:22 +0000977
978 If both textures and vertex-colors are NULL, it strokes hairlines with
979 the paint's color. This behavior is a useful debugging mode to visualize
980 the mesh.
981
reed@android.com8a1c16f2008-12-17 15:59:43 +0000982 @param vmode How to interpret the array of vertices
983 @param vertexCount The number of points in the vertices array (and
984 corresponding texs and colors arrays if non-null)
985 @param vertices Array of vertices for the mesh
986 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +0000987 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988 @param colors May be null. If not null, specifies a color for each
989 vertex, to be interpolated across the triangle.
990 @param xmode Used if both texs and colors are present. In this
991 case the colors are combined with the texture using mode,
992 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +0000993 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000994 @param indices If not null, array of indices to reference into the
995 vertex (texs, colors) array.
996 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +0000997 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998 */
reed0846f1b2015-01-09 14:17:40 -0800999 void drawVertices(VertexMode vmode, int vertexCount,
1000 const SkPoint vertices[], const SkPoint texs[],
1001 const SkColor colors[], SkXfermode* xmode,
1002 const uint16_t indices[], int indexCount,
1003 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001004
dandovb3c9d1c2014-08-12 08:34:29 -07001005 /**
1006 Draw a cubic coons patch
mtklein6cfa73a2014-08-13 13:33:49 -07001007
dandovb3c9d1c2014-08-12 08:34:29 -07001008 @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1009 starting at the top left corner.
1010 @param colors specifies the colors for the corners which will be bilerp across the patch,
1011 their order is clockwise starting at the top left corner.
mtklein6cfa73a2014-08-13 13:33:49 -07001012 @param texCoords specifies the texture coordinates that will be bilerp across the patch,
dandovb3c9d1c2014-08-12 08:34:29 -07001013 their order is the same as the colors.
mtklein6cfa73a2014-08-13 13:33:49 -07001014 @param xmode specifies how are the colors and the textures combined if both of them are
dandovb3c9d1c2014-08-12 08:34:29 -07001015 present.
dandov963137b2014-08-07 07:49:53 -07001016 @param paint Specifies the shader/texture if present.
1017 */
dandovb3c9d1c2014-08-12 08:34:29 -07001018 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1019 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001020
reed3cb38402015-02-06 08:36:15 -08001021 /**
1022 * Draw the contents of this drawable into the canvas. If the canvas is async
1023 * (e.g. it is recording into a picture) then the drawable will be referenced instead,
1024 * to have its draw() method called when the picture is finalized.
1025 *
1026 * If the intent is to force the contents of the drawable into this canvas immediately,
1027 * then drawable->draw(canvas) may be called.
1028 */
1029 void drawDrawable(SkDrawable* drawable);
reed6a070dc2014-11-11 19:36:09 -08001030
skia.committer@gmail.coma5d3e772013-05-30 07:01:29 +00001031 /** Add comments. beginCommentGroup/endCommentGroup open/close a new group.
1032 Each comment added via addComment is notionally attached to its
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001033 enclosing group. Top-level comments simply belong to no group.
1034 */
djsollenc87dd2c2014-11-14 11:11:46 -08001035 virtual void beginCommentGroup(const char* /*description*/) {
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001036 // do nothing. Subclasses may do something
1037 }
djsollenc87dd2c2014-11-14 11:11:46 -08001038 virtual void addComment(const char* /*kywd*/, const char* /*value*/) {
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001039 // do nothing. Subclasses may do something
1040 }
1041 virtual void endCommentGroup() {
1042 // do nothing. Subclasses may do something
1043 }
1044
reed@android.com8a1c16f2008-12-17 15:59:43 +00001045 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +00001046
reed@android.com8a1c16f2008-12-17 15:59:43 +00001047 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001048 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001049 @return the canvas' filter (or NULL).
1050 */
1051 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001052
reed@android.com8a1c16f2008-12-17 15:59:43 +00001053 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1054 As a convenience, the parameter is returned. If an existing filter
1055 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001056 refcnt is incremented. The filter is saved/restored, just like the
1057 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001058 @param filter the new filter (or NULL)
1059 @return the new filter
1060 */
1061 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
1062
1063 //////////////////////////////////////////////////////////////////////////
1064
reed@google.com754de5f2014-02-24 19:38:20 +00001065 /**
1066 * Return true if the current clip is empty (i.e. nothing will draw).
1067 * Note: this is not always a free call, so it should not be used
1068 * more often than necessary. However, once the canvas has computed this
1069 * result, subsequent calls will be cheap (until the clip state changes,
1070 * which can happen on any clip..() or restore() call.
1071 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001072 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001073
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001074 /**
1075 * Returns true if the current clip is just a (non-empty) rectangle.
1076 * Returns false if the clip is empty, or if it is complex.
1077 */
1078 virtual bool isClipRect() const;
1079
reed@android.com8a1c16f2008-12-17 15:59:43 +00001080 /** Return the current matrix on the canvas.
1081 This does not account for the translate in any of the devices.
1082 @return The current matrix on the canvas.
1083 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001084 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001085
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001086 /** Return the clip stack. The clip stack stores all the individual
1087 * clips organized by the save/restore frame in which they were
1088 * added.
1089 * @return the current clip stack ("list" of individual clip elements)
1090 */
1091 const SkClipStack* getClipStack() const {
joshualittde358a92015-02-05 08:19:35 -08001092 return fClipStack;
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001093 }
1094
fmalitac3b589a2014-06-05 12:40:07 -07001095 typedef SkCanvasClipVisitor ClipVisitor;
reed@google.com90c07ea2012-04-13 13:50:27 +00001096 /**
1097 * Replays the clip operations, back to front, that have been applied to
1098 * the canvas, calling the appropriate method on the visitor for each
1099 * clip. All clips have already been transformed into device space.
1100 */
1101 void replayClips(ClipVisitor*) const;
1102
reed@android.com8a1c16f2008-12-17 15:59:43 +00001103 ///////////////////////////////////////////////////////////////////////////
1104
1105 /** After calling saveLayer(), there can be any number of devices that make
1106 up the top-most drawing area. LayerIter can be used to iterate through
1107 those devices. Note that the iterator is only valid until the next API
1108 call made on the canvas. Ownership of all pointers in the iterator stays
1109 with the canvas, so none of them should be modified or deleted.
1110 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +00001111 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001112 public:
1113 /** Initialize iterator with canvas, and set values for 1st device */
1114 LayerIter(SkCanvas*, bool skipEmptyClips);
1115 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +00001116
reed@android.com8a1c16f2008-12-17 15:59:43 +00001117 /** Return true if the iterator is done */
1118 bool done() const { return fDone; }
1119 /** Cycle to the next device */
1120 void next();
reed@google.com4b226022011-01-11 18:32:13 +00001121
reed@android.com8a1c16f2008-12-17 15:59:43 +00001122 // These reflect the current device in the iterator
1123
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001124 SkBaseDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001125 const SkMatrix& matrix() const;
1126 const SkRegion& clip() const;
1127 const SkPaint& paint() const;
1128 int x() const;
1129 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001130
reed@android.com8a1c16f2008-12-17 15:59:43 +00001131 private:
1132 // used to embed the SkDrawIter object directly in our instance, w/o
1133 // having to expose that class def to the public. There is an assert
1134 // in our constructor to ensure that fStorage is large enough
1135 // (though needs to be a compile-time-assert!). We use intptr_t to work
1136 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001137 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001138 class SkDrawIter* fImpl; // this points at fStorage
1139 SkPaint fDefaultPaint;
1140 bool fDone;
1141 };
1142
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001143 // don't call
reed@google.com9c135db2014-03-12 18:28:35 +00001144 GrRenderTarget* internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001145
reedd990e2f2014-12-22 11:58:30 -08001146 // don't call
1147 static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1148 static bool Internal_Private_GetIgnoreSaveLayerBounds();
reed0acf1b42014-12-22 16:12:38 -08001149 static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1150 static bool Internal_Private_GetTreatSpriteAsBitmap();
reedd990e2f2014-12-22 11:58:30 -08001151
reed@android.com8a1c16f2008-12-17 15:59:43 +00001152protected:
reed@google.com76f10a32014-02-05 15:32:21 +00001153 // default impl defers to getDevice()->newSurface(info)
reed4a8126e2014-09-22 07:29:03 -07001154 virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
reed@google.com76f10a32014-02-05 15:32:21 +00001155
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001156 // default impl defers to its device
1157 virtual const void* onPeekPixels(SkImageInfo*, size_t* rowBytes);
reed@google.com9c135db2014-03-12 18:28:35 +00001158 virtual void* onAccessTopLayerPixels(SkImageInfo*, size_t* rowBytes);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001159
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001160 // Subclass save/restore notifiers.
1161 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1162 // willSaveLayer()'s return value may suppress full layer allocation.
1163 enum SaveLayerStrategy {
1164 kFullLayer_SaveLayerStrategy,
1165 kNoLayer_SaveLayerStrategy
1166 };
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001167
fmalita6ca763f2014-06-17 13:52:18 -07001168 virtual void willSave() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001169 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) {
1170 return kFullLayer_SaveLayerStrategy;
1171 }
1172 virtual void willRestore() {}
mtklein6cfa73a2014-08-13 13:33:49 -07001173 virtual void didRestore() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001174 virtual void didConcat(const SkMatrix&) {}
1175 virtual void didSetMatrix(const SkMatrix&) {}
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001176
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001177 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1178
reed@google.come0d9ce82014-04-23 04:00:17 +00001179 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1180 SkScalar y, const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001181
reed@google.come0d9ce82014-04-23 04:00:17 +00001182 virtual void onDrawPosText(const void* text, size_t byteLength,
1183 const SkPoint pos[], const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001184
reed@google.come0d9ce82014-04-23 04:00:17 +00001185 virtual void onDrawPosTextH(const void* text, size_t byteLength,
1186 const SkScalar xpos[], SkScalar constY,
1187 const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001188
reed@google.come0d9ce82014-04-23 04:00:17 +00001189 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1190 const SkPath& path, const SkMatrix* matrix,
1191 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001192
fmalita00d5c2c2014-08-21 08:53:26 -07001193 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1194 const SkPaint& paint);
1195
dandovb3c9d1c2014-08-12 08:34:29 -07001196 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
1197 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@google.come0d9ce82014-04-23 04:00:17 +00001198
reed3cb38402015-02-06 08:36:15 -08001199 virtual void onDrawDrawable(SkDrawable*);
reed6a070dc2014-11-11 19:36:09 -08001200
reed41af9662015-01-05 07:49:08 -08001201 virtual void onDrawPaint(const SkPaint&);
1202 virtual void onDrawRect(const SkRect&, const SkPaint&);
1203 virtual void onDrawOval(const SkRect&, const SkPaint&);
1204 virtual void onDrawRRect(const SkRRect&, const SkPaint&);
1205 virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
1206 virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
1207 const SkPoint texs[], const SkColor colors[], SkXfermode*,
1208 const uint16_t indices[], int indexCount, const SkPaint&);
1209 virtual void onDrawPath(const SkPath&, const SkPaint&);
1210 virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
1211 virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*);
1212 virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
1213 virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
1214 DrawBitmapRectFlags);
1215 virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
1216 const SkPaint*);
1217 virtual void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*);
1218
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001219 enum ClipEdgeStyle {
1220 kHard_ClipEdgeStyle,
1221 kSoft_ClipEdgeStyle
1222 };
1223
1224 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1225 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1226 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1227 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1228
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +00001229 virtual void onDiscard();
1230
reedd5fa1a42014-08-09 11:08:05 -07001231 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
robertphillips9b14f262014-06-04 05:40:44 -07001232
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001233 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001234 // returns this. Subclasses that encapsulate an indirect canvas may
1235 // need to overload this method. The impl must keep track of this, as it
1236 // is not released or deleted by the caller.
1237 virtual SkCanvas* canvasForDrawIter();
1238
junov@chromium.orga907ac32012-02-24 21:54:07 +00001239 // Clip rectangle bounds. Called internally by saveLayer.
1240 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001241 // If non-NULL, The imageFilter parameter will be used to expand the clip
1242 // and offscreen bounds for any margin required by the filter DAG.
junov@chromium.orga907ac32012-02-24 21:54:07 +00001243 bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001244 SkIRect* intersection,
1245 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001246
reed@google.com97af1a62012-08-28 12:19:02 +00001247 // notify our surface (if we have one) that we are about to draw, so it
1248 // can perform copy-on-write or invalidate any cached images
1249 void predrawNotify();
1250
reed@android.com8a1c16f2008-12-17 15:59:43 +00001251private:
1252 class MCRec;
1253
joshualittde358a92015-02-05 08:19:35 -08001254 SkAutoTUnref<SkClipStack> fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001255 SkDeque fMCStack;
1256 // points to top of stack
1257 MCRec* fMCRec;
1258 // the first N recs that can fit here mean we won't call malloc
1259 uint32_t fMCRecStorage[32];
1260
reed4a8126e2014-09-22 07:29:03 -07001261 const SkSurfaceProps fProps;
1262
reed2ff1fce2014-12-11 07:07:37 -08001263 int fSaveCount; // value returned by getSaveCount()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001264
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001265 SkMetaData* fMetaData;
1266
reed@google.com97af1a62012-08-28 12:19:02 +00001267 SkSurface_Base* fSurfaceBase;
1268 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1269 void setSurfaceBase(SkSurface_Base* sb) {
1270 fSurfaceBase = sb;
1271 }
1272 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001273 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001274
reed@android.com8a1c16f2008-12-17 15:59:43 +00001275 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1276 void updateDeviceCMCache();
1277
reed2ff1fce2014-12-11 07:07:37 -08001278 void doSave();
1279 void checkForDeferredSave();
1280
reed@google.com9c135db2014-03-12 18:28:35 +00001281 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001282 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001283 friend class SkLua; // needs top layer size and offset
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +00001284 friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
reed@google.com9c135db2014-03-12 18:28:35 +00001285 friend class SkDeferredDevice; // needs getTopDevice()
reed52d9ac62014-06-30 09:05:34 -07001286 friend class SkSurface_Raster; // needs getDevice()
reedd9544982014-09-09 18:46:22 -07001287 friend class SkRecorder; // InitFlags
1288 friend class SkNoSaveLayerCanvas; // InitFlags
fmalita2d97bc12014-11-20 10:44:58 -08001289 friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
piotaixrb5fae932014-09-24 13:03:30 -07001290
reedd9544982014-09-09 18:46:22 -07001291 enum InitFlags {
1292 kDefault_InitFlags = 0,
1293 kConservativeRasterClip_InitFlag = 1 << 0,
1294 };
reed78e27682014-11-19 08:04:34 -08001295 SkCanvas(const SkIRect& bounds, InitFlags);
reed4a8126e2014-09-22 07:29:03 -07001296 SkCanvas(SkBaseDevice*, const SkSurfaceProps*, InitFlags);
reedd9544982014-09-09 18:46:22 -07001297
reed8f2e7912014-09-04 12:45:18 -07001298 // needs gettotalclip()
tfarinaa5414c42014-10-10 06:19:09 -07001299 friend class SkCanvasStateUtils;
piotaixrb5fae932014-09-24 13:03:30 -07001300
reed4a8126e2014-09-22 07:29:03 -07001301 // call this each time we attach ourselves to a device
1302 // - constructor
1303 // - internalSaveLayer
1304 void setupDevice(SkBaseDevice*);
1305
reedd9544982014-09-09 18:46:22 -07001306 SkBaseDevice* init(SkBaseDevice*, InitFlags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001307
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001308 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00001309 * Gets the size/origin of the top level layer in global canvas coordinates. We don't want this
1310 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1311 */
1312 SkISize getTopLayerSize() const;
1313 SkIPoint getTopLayerOrigin() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001314
reed@google.comf0b5e112011-09-07 11:57:34 +00001315 // internal methods are not virtual, so they can safely be called by other
1316 // canvas apis, without confusing subclasses (like SkPictureRecording)
robertphillips@google.com9bf380c2013-07-25 12:10:42 +00001317 void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
reed@google.com71121732012-09-18 15:14:33 +00001318 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001319 const SkRect& dst, const SkPaint* paint,
1320 DrawBitmapRectFlags flags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001321 void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
1322 const SkRect& dst, const SkPaint* paint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001323 void internalDrawPaint(const SkPaint& paint);
reed2ff1fce2014-12-11 07:07:37 -08001324 void internalSaveLayer(const SkRect* bounds, const SkPaint* paint,
1325 SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy);
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001326 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001327
reed@android.com8a1c16f2008-12-17 15:59:43 +00001328 // shared by save() and saveLayer()
reed2ff1fce2014-12-11 07:07:37 -08001329 void internalSave();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001330 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001331 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1332 const SkRect& r, SkScalar textSize);
1333 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1334 const char text[], size_t byteLength,
1335 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001336
reedfa35f8e2014-09-04 12:14:36 -07001337 // only for canvasutils
1338 const SkRegion& internal_private_getTotalClip() const;
1339
reed@android.com8a1c16f2008-12-17 15:59:43 +00001340 /* These maintain a cache of the clip bounds in local coordinates,
1341 (converted to 2s-compliment if floats are slow).
1342 */
reed@google.comc0784db2013-12-13 21:16:12 +00001343 mutable SkRect fCachedLocalClipBounds;
1344 mutable bool fCachedLocalClipBoundsDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001345 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001346 bool fAllowSimplifyClip;
reedd9544982014-09-09 18:46:22 -07001347 bool fConservativeRasterClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001348
reed@google.comc0784db2013-12-13 21:16:12 +00001349 const SkRect& getLocalClipBounds() const {
1350 if (fCachedLocalClipBoundsDirty) {
1351 if (!this->getClipBounds(&fCachedLocalClipBounds)) {
1352 fCachedLocalClipBounds.setEmpty();
1353 }
1354 fCachedLocalClipBoundsDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001355 }
reed@google.comc0784db2013-12-13 21:16:12 +00001356 return fCachedLocalClipBounds;
reed@android.comba09de42010-02-05 20:46:05 +00001357 }
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001358
reed@google.com5c3d1472011-02-22 19:12:23 +00001359 class AutoValidateClip : ::SkNoncopyable {
1360 public:
1361 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1362 fCanvas->validateClip();
1363 }
1364 ~AutoValidateClip() { fCanvas->validateClip(); }
1365
1366 private:
1367 const SkCanvas* fCanvas;
1368 };
1369
1370#ifdef SK_DEBUG
1371 void validateClip() const;
1372#else
1373 void validateClip() const {}
1374#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001375
1376 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001377};
1378
1379/** Stack helper class to automatically call restoreToCount() on the canvas
1380 when this object goes out of scope. Use this to guarantee that the canvas
1381 is restored to a known state.
1382*/
1383class SkAutoCanvasRestore : SkNoncopyable {
1384public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001385 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1386 if (fCanvas) {
1387 fSaveCount = canvas->getSaveCount();
1388 if (doSave) {
1389 canvas->save();
1390 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001391 }
1392 }
1393 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001394 if (fCanvas) {
1395 fCanvas->restoreToCount(fSaveCount);
1396 }
1397 }
1398
1399 /**
1400 * Perform the restore now, instead of waiting for the destructor. Will
1401 * only do this once.
1402 */
1403 void restore() {
1404 if (fCanvas) {
1405 fCanvas->restoreToCount(fSaveCount);
1406 fCanvas = NULL;
1407 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001408 }
1409
1410private:
1411 SkCanvas* fCanvas;
1412 int fSaveCount;
1413};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001414#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001415
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001416/** Stack helper class to automatically open and close a comment block
1417 */
1418class SkAutoCommentBlock : SkNoncopyable {
1419public:
1420 SkAutoCommentBlock(SkCanvas* canvas, const char* description) {
1421 fCanvas = canvas;
bsalomon49f085d2014-09-05 13:34:00 -07001422 if (fCanvas) {
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001423 fCanvas->beginCommentGroup(description);
1424 }
1425 }
1426
1427 ~SkAutoCommentBlock() {
bsalomon49f085d2014-09-05 13:34:00 -07001428 if (fCanvas) {
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001429 fCanvas->endCommentGroup();
1430 }
1431 }
1432
1433private:
1434 SkCanvas* fCanvas;
1435};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001436#define SkAutoCommentBlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoCommentBlock)
robertphillips@google.com0a4805e2013-05-29 13:24:23 +00001437
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001438/**
1439 * If the caller wants read-only access to the pixels in a canvas, it can just
1440 * call canvas->peekPixels(), since that is the fastest way to "peek" at the
1441 * pixels on a raster-backed canvas.
1442 *
1443 * If the canvas has pixels, but they are not readily available to the CPU
1444 * (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will
1445 * succeed (though be slower, since it will return a copy of the pixels).
1446 *
1447 * SkAutoROCanvasPixels encapsulates these two techniques, trying first to call
1448 * peekPixels() (for performance), but if that fails, calling readPixels() and
1449 * storing the copy locally.
1450 *
1451 * The caller must respect the restrictions associated with peekPixels(), since
1452 * that may have been called: The returned information is invalidated if...
1453 * - any API is called on the canvas (or its parent surface if present)
1454 * - the canvas goes out of scope
1455 */
1456class SkAutoROCanvasPixels : SkNoncopyable {
1457public:
1458 SkAutoROCanvasPixels(SkCanvas* canvas);
1459
1460 // returns NULL on failure
1461 const void* addr() const { return fAddr; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001462
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001463 // undefined if addr() == NULL
1464 size_t rowBytes() const { return fRowBytes; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001465
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001466 // undefined if addr() == NULL
1467 const SkImageInfo& info() const { return fInfo; }
1468
1469 // helper that, if returns true, installs the pixels into the bitmap. Note
1470 // that the bitmap may reference the address returned by peekPixels(), so
1471 // the caller must respect the restrictions associated with peekPixels().
1472 bool asROBitmap(SkBitmap*) const;
1473
1474private:
1475 SkBitmap fBitmap; // used if peekPixels() fails
1476 const void* fAddr; // NULL on failure
1477 SkImageInfo fInfo;
1478 size_t fRowBytes;
1479};
1480
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001481static inline SkCanvas::SaveFlags operator|(const SkCanvas::SaveFlags lhs,
1482 const SkCanvas::SaveFlags rhs) {
commit-bot@chromium.org92a89162014-05-30 21:07:05 +00001483 return static_cast<SkCanvas::SaveFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001484}
1485
1486static inline SkCanvas::SaveFlags& operator|=(SkCanvas::SaveFlags& lhs,
1487 const SkCanvas::SaveFlags rhs) {
1488 lhs = lhs | rhs;
1489 return lhs;
1490}
1491
fmalitac3b589a2014-06-05 12:40:07 -07001492class SkCanvasClipVisitor {
1493public:
1494 virtual ~SkCanvasClipVisitor();
1495 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
1496 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
1497 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1498};
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001499
reed@android.com8a1c16f2008-12-17 15:59:43 +00001500#endif