blob: 299ef45d28aa410e190ed29a720b7a12060fbe76 [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;
reed71c3c762015-06-24 10:29:17 -070031struct SkRSXform;
reed@google.com76f10a32014-02-05 15:32:21 +000032class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000033class SkSurface_Base;
fmalita00d5c2c2014-08-21 08:53:26 -070034class SkTextBlob;
commit-bot@chromium.org644629c2013-11-21 06:21:58 +000035class GrContext;
reed@google.com9c135db2014-03-12 18:28:35 +000036class GrRenderTarget;
reed@android.com8a1c16f2008-12-17 15:59:43 +000037
reed84984ef2015-07-17 07:09:43 -070038//#define SK_SUPPORT_LEGACY_DRAWBITMAPRECTFLAGS_TYPE
reeda5517e22015-07-14 10:54:12 -070039
reedfa35f8e2014-09-04 12:14:36 -070040class SkCanvasState;
41
reeda5517e22015-07-14 10:54:12 -070042#ifdef SK_SUPPORT_LEGACY_ONDRAWIMAGERECT
43 #define SK_VIRTUAL_CONSTRAINT_TYPE SkCanvas::DrawBitmapRectFlags
44 #define SRC_RECT_CONSTRAINT_PARAM(param)
45 #define SRC_RECT_CONSTRAINT_ARG(arg)
46 #define SRC_RECT_CONSTRAINT_LOCAL_DEFAULT(var) SkCanvas::SrcRectConstraint var = SkCanvas::kStrict_SrcRectConstraint;
47#else
48 #define SK_VIRTUAL_CONSTRAINT_TYPE SkCanvas::SrcRectConstraint
49 #define SRC_RECT_CONSTRAINT_PARAM(param) , SrcRectConstraint param
50 #define SRC_RECT_CONSTRAINT_ARG(arg) , arg
51 #define SRC_RECT_CONSTRAINT_LOCAL_DEFAULT(var)
52#endif
53
reed@android.com8a1c16f2008-12-17 15:59:43 +000054/** \class SkCanvas
55
56 A Canvas encapsulates all of the state about drawing into a device (bitmap).
57 This includes a reference to the device itself, and a stack of matrix/clip
58 values. For any given draw call (e.g. drawRect), the geometry of the object
59 being drawn is transformed by the concatenation of all the matrices in the
60 stack. The transformed geometry is clipped by the intersection of all of
61 the clips in the stack.
62
63 While the Canvas holds the state of the drawing device, the state (style)
64 of the object being drawn is held by the Paint, which is provided as a
65 parameter to each of the draw() methods. The Paint holds attributes such as
66 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
67 etc.
68*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000069class SK_API SkCanvas : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000070public:
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000071 /**
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000072 * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
73 * specified pixels. To access the pixels after drawing to them, the caller should call
74 * flush() or call peekPixels(...).
75 *
76 * On failure, return NULL. This can fail for several reasons:
77 * 1. invalid ImageInfo (e.g. negative dimensions)
78 * 2. unsupported ImageInfo for a canvas
79 * - kUnknown_SkColorType, kIndex_8_SkColorType
reed44977482015-02-27 10:23:00 -080080 * - kUnknown_SkAlphaType
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000081 * - this list is not complete, so others may also be unsupported
82 *
83 * Note: it is valid to request a supported ImageInfo, but with zero
84 * dimensions.
85 */
86 static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t);
87
88 static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
89 return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
90 }
91
92 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000093 * Creates an empty canvas with no backing device/pixels, and zero
94 * dimensions.
95 */
reed@google.comcde92112011-07-06 20:00:52 +000096 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000097
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000098 /**
99 * Creates a canvas of the specified dimensions, but explicitly not backed
100 * by any device/pixels. Typically this use used by subclasses who handle
101 * the draw calls in some other way.
102 */
reed96a857e2015-01-25 10:33:58 -0800103 SkCanvas(int width, int height, const SkSurfaceProps* = NULL);
commit-bot@chromium.orge2543102014-01-31 19:42:58 +0000104
reed@google.com6dc74552011-07-21 18:00:46 +0000105 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000106
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000107 @param device Specifies a device for the canvas to draw into.
108 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000109 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000110
reed@google.com44699382013-10-31 17:28:30 +0000111 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112 @param bitmap Specifies a bitmap for the canvas to draw into. Its
113 structure are copied to the canvas.
114 */
115 explicit SkCanvas(const SkBitmap& bitmap);
fmalita3d91aad2015-02-02 05:25:04 -0800116
117 /** Construct a canvas with the specified bitmap to draw into.
118 @param bitmap Specifies a bitmap for the canvas to draw into. Its
119 structure are copied to the canvas.
120 @param props New canvas surface properties.
121 */
122 SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
123
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124 virtual ~SkCanvas();
125
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000126 SkMetaData& getMetaData();
127
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000128 /**
129 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
130 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
131 */
132 SkImageInfo imageInfo() const;
133
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 ///////////////////////////////////////////////////////////////////////////
135
reed@google.com210ce002011-11-01 14:24:23 +0000136 /**
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000137 * Trigger the immediate execution of all pending draw operations.
138 */
139 void flush();
140
141 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000142 * Gets the size of the base or root layer in global canvas coordinates. The
143 * origin of the base layer is always (0,0). The current drawable area may be
144 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000145 */
tomhudson68260fa2015-03-23 07:22:40 -0700146 virtual SkISize getBaseLayerSize() const;
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000147
148 /**
149 * DEPRECATED: call getBaseLayerSize
150 */
151 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000152
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000153 /**
154 * DEPRECATED.
155 * Return the canvas' device object, which may be null. The device holds
156 * the bitmap of the pixels that the canvas draws into. The reference count
157 * of the returned device is not changed by this call.
158 */
reed52d9ac62014-06-30 09:05:34 -0700159#ifndef SK_SUPPORT_LEGACY_GETDEVICE
160protected: // Can we make this private?
161#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000162 SkBaseDevice* getDevice() const;
reed52d9ac62014-06-30 09:05:34 -0700163public:
reed41e010c2015-06-09 12:16:53 -0700164 SkBaseDevice* getDevice_just_for_deprecated_compatibility_testing() const {
165 return this->getDevice();
166 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167
reed@google.com9266fed2011-03-30 00:18:03 +0000168 /**
169 * saveLayer() can create another device (which is later drawn onto
170 * the previous device). getTopDevice() returns the top-most device current
171 * installed. Note that this can change on other calls like save/restore,
172 * so do not access this device after subsequent canvas calls.
173 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000174 *
175 * @param updateMatrixClip If this is true, then before the device is
176 * returned, we ensure that its has been notified about the current
177 * matrix and clip. Note: this happens automatically when the device
178 * is drawn to, but is optional here, as there is a small perf hit
179 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000180 */
reed@google.com9c135db2014-03-12 18:28:35 +0000181#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
182private:
183#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000184 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000185public:
reed@google.com9266fed2011-03-30 00:18:03 +0000186
reed@google.com76f10a32014-02-05 15:32:21 +0000187 /**
188 * Create a new surface matching the specified info, one that attempts to
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000189 * be maximally compatible when used with this canvas. If there is no matching Surface type,
190 * NULL is returned.
reed4a8126e2014-09-22 07:29:03 -0700191 *
192 * If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
193 * inherits the properties of the surface that owns this canvas. If this canvas has no parent
194 * surface, then the new surface is created with default properties.
reed@google.com76f10a32014-02-05 15:32:21 +0000195 */
reed4a8126e2014-09-22 07:29:03 -0700196 SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps* = NULL);
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,
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000210 * return the ImageInfo, rowBytes and origin. The returned address is only valid
reed@google.com9c135db2014-03-12 18:28:35 +0000211 * 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 *
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000215 * On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
reed@google.com9c135db2014-03-12 18:28:35 +0000216 */
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000217 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
reed@google.com9c135db2014-03-12 18:28:35 +0000218
219 /**
220 * If the canvas has readable pixels in its base layer (and is not recording to a picture
221 * 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 +0000222 * local RAM) return the const-address of those pixels, and if not null,
223 * return the ImageInfo and rowBytes. The returned address is only valid
224 * while the canvas object is in scope and unchanged. Any API calls made on
225 * canvas (or its parent surface if any) will invalidate the
226 * returned address (and associated information).
227 *
228 * On failure, returns NULL and the info and rowBytes parameters are
229 * ignored.
230 */
231 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
232
reed@google.com4b226022011-01-11 18:32:13 +0000233 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000234 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
235 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
reedb184f7f2014-07-13 04:32:32 -0700236 * starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000237 *
reedb184f7f2014-07-13 04:32:32 -0700238 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000239 *
reedb184f7f2014-07-13 04:32:32 -0700240 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000241 *
reedb184f7f2014-07-13 04:32:32 -0700242 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
243 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
244 * corresponding src pixels, performing any colortype/alphatype transformations needed
245 * (in the case where the src and dst have different colortypes or alphatypes).
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000246 *
247 * This call can fail, returning false, for several reasons:
reedb184f7f2014-07-13 04:32:32 -0700248 * - If srcR does not intersect the base-layer bounds.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000249 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
250 * - If this canvas is not backed by pixels (e.g. picture or PDF)
251 */
reedb184f7f2014-07-13 04:32:32 -0700252 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
253 int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000254
255 /**
256 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
257 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
258 * it calls through to readPixels(info, ...) and returns its result.
259 */
reedb184f7f2014-07-13 04:32:32 -0700260 bool readPixels(SkBitmap* bitmap, int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000261
262 /**
263 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
264 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
265 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
266 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000267 */
268 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000269
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000270 /**
271 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
272 * ignoring the matrix and clip.
273 *
274 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
275 *
276 * target.setXYWH(x, y, info.width(), info.height());
277 *
278 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
279 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
280 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
281 * pixels, performing any colortype/alphatype transformations needed (in the case where the
282 * src and dst have different colortypes or alphatypes).
283 *
284 * This call can fail, returning false, for several reasons:
285 * - If the src colortype/alphatype cannot be converted to the canvas' types
286 * - If this canvas is not backed by pixels (e.g. picture or PDF)
287 */
288 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
289
290 /**
291 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
292 * is just wrapping a texture, returns false and does nothing.
293 */
294 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000295
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000297
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 enum SaveFlags {
299 /** save the matrix state, restoring it on restore() */
Florin Malita5f6102d2014-06-30 10:13:28 -0400300 // [deprecated] kMatrix_SaveFlag = 0x01,
fmalita696d3612014-07-01 11:55:41 -0700301 kMatrix_SaveFlag = 0x01,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302 /** save the clip state, restoring it on restore() */
Florin Malita5f6102d2014-06-30 10:13:28 -0400303 // [deprecated] kClip_SaveFlag = 0x02,
fmalita696d3612014-07-01 11:55:41 -0700304 kClip_SaveFlag = 0x02,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 /** the layer needs to support per-pixel alpha */
306 kHasAlphaLayer_SaveFlag = 0x04,
307 /** the layer needs to support 8-bits per color component */
308 kFullColorLayer_SaveFlag = 0x08,
reed@google.comb93ba452014-03-10 19:47:58 +0000309 /**
310 * the layer should clip against the bounds argument
311 *
312 * if SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG is undefined, this is treated as always on.
313 */
reed@android.com8a1c16f2008-12-17 15:59:43 +0000314 kClipToLayer_SaveFlag = 0x10,
315
316 // helper masks for common choices
Florin Malita5f6102d2014-06-30 10:13:28 -0400317 // [deprecated] kMatrixClip_SaveFlag = 0x03,
fmalita696d3612014-07-01 11:55:41 -0700318 kMatrixClip_SaveFlag = 0x03,
reed@google.comb93ba452014-03-10 19:47:58 +0000319#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
reed@android.com8a1c16f2008-12-17 15:59:43 +0000320 kARGB_NoClipLayer_SaveFlag = 0x0F,
reed@google.comb93ba452014-03-10 19:47:58 +0000321#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000322 kARGB_ClipLayer_SaveFlag = 0x1F
323 };
324
reed@android.comdc3381f2010-02-11 16:05:15 +0000325 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000327 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
328 operate on this copy.
329 When the balancing call to restore() is made, the previous matrix, clip,
330 and drawFilter are restored.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000331
332 @return The value to pass to restoreToCount() to balance this save()
333 */
334 int save();
335
reed@android.com8a1c16f2008-12-17 15:59:43 +0000336 /** This behaves the same as save(), but in addition it allocates an
337 offscreen bitmap. All drawing calls are directed there, and only when
338 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000339 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000340 @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().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344 @param paint (may be null) This is copied, and is applied to the
345 offscreen when restore() is called
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000346 @return The value to pass to restoreToCount() to balance this save()
347 */
348 int saveLayer(const SkRect* bounds, const SkPaint* paint);
349
350 /** DEPRECATED - use saveLayer(const SkRect*, const SkPaint*) instead.
351
352 This behaves the same as saveLayer(const SkRect*, const SkPaint*),
353 but it allows fine-grained control of which state bits to be saved
354 (and subsequently restored).
355
356 @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().
360 @param paint (may be null) This is copied, and is applied to the
361 offscreen when restore() is called
reed@android.com8a1c16f2008-12-17 15:59:43 +0000362 @param flags LayerFlags
363 @return The value to pass to restoreToCount() to balance this save()
364 */
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000365 SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
366 int saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000367
368 /** This behaves the same as save(), but in addition it allocates an
369 offscreen bitmap. All drawing calls are directed there, and only when
370 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000371 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000372 @param bounds (may be null) This rect, if non-null, is used as a hint to
373 limit the size of the offscreen, and thus drawing may be
374 clipped to it, though that clipping is not guaranteed to
375 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000376 @param alpha This is applied to the offscreen when restore() is called.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000377 @return The value to pass to restoreToCount() to balance this save()
378 */
379 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
380
381 /** DEPRECATED - use saveLayerAlpha(const SkRect*, U8CPU) instead.
382
383 This behaves the same as saveLayerAlpha(const SkRect*, U8CPU),
384 but it allows fine-grained control of which state bits to be saved
385 (and subsequently restored).
386
387 @param bounds (may be null) This rect, if non-null, is used as a hint to
388 limit the size of the offscreen, and thus drawing may be
389 clipped to it, though that clipping is not guaranteed to
390 happen. If exact clipping is desired, use clipRect().
391 @param alpha This is applied to the offscreen when restore() is called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 @param flags LayerFlags
393 @return The value to pass to restoreToCount() to balance this save()
394 */
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000395 SK_ATTR_EXTERNALLY_DEPRECATED("SaveFlags use is deprecated")
396 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, SaveFlags flags);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397
398 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000399 modifications to the matrix/clip/drawFilter state since the last save
400 call.
401 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000402 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000403 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000404
405 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000406 This will equal # save() calls - # restore() calls + 1. The save count on
407 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000409 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000410
411 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000412 count reached saveCount. It is an error for saveCount to be greater than
413 getSaveCount(). To pop all the way back to the initial matrix/clip context
414 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415 @param saveCount The number of save() levels to restore from
416 */
417 void restoreToCount(int saveCount);
418
419 /** Preconcat the current matrix with the specified translation
420 @param dx The distance to translate in X
421 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000422 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000423 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424
425 /** Preconcat the current matrix with the specified scale.
426 @param sx The amount to scale in X
427 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000429 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000430
431 /** Preconcat the current matrix with the specified rotation.
432 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000433 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000434 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000435
436 /** Preconcat the current matrix with the specified skew.
437 @param sx The amount to skew in X
438 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000439 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000440 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000441
442 /** Preconcat the current matrix with the specified matrix.
443 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000444 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000445 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000446
reed@android.com8a1c16f2008-12-17 15:59:43 +0000447 /** Replace the current matrix with a copy of the specified matrix.
448 @param matrix The matrix that will be copied into the current matrix.
449 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000450 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000451
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452 /** Helper for setMatrix(identity). Sets the current matrix to identity.
453 */
454 void resetMatrix();
455
reed@google.com4ed0fb72012-12-12 20:48:18 +0000456 /**
457 * Modify the current clip with the specified rectangle.
458 * @param rect The rect to combine with the current clip
459 * @param op The region op to apply to the current clip
460 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000461 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000462 void clipRect(const SkRect& rect,
463 SkRegion::Op op = SkRegion::kIntersect_Op,
464 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465
reed@google.com4ed0fb72012-12-12 20:48:18 +0000466 /**
467 * Modify the current clip with the specified SkRRect.
468 * @param rrect The rrect to combine with the current clip
469 * @param op The region op to apply to the current clip
470 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000471 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000472 void clipRRect(const SkRRect& rrect,
473 SkRegion::Op op = SkRegion::kIntersect_Op,
474 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000475
476 /**
477 * Modify the current clip with the specified path.
478 * @param path The path to combine with the current clip
479 * @param op The region op to apply to the current clip
480 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000481 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000482 void clipPath(const SkPath& path,
483 SkRegion::Op op = SkRegion::kIntersect_Op,
484 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000485
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000486 /** EXPERIMENTAL -- only used for testing
487 Set to false to force clips to be hard, even if doAntiAlias=true is
488 passed to clipRect or clipPath.
489 */
490 void setAllowSoftClip(bool allow) {
491 fAllowSoftClip = allow;
492 }
493
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000494 /** EXPERIMENTAL -- only used for testing
495 Set to simplify clip stack using path ops.
496 */
497 void setAllowSimplifyClip(bool allow) {
498 fAllowSimplifyClip = allow;
499 }
500
reed@android.com8a1c16f2008-12-17 15:59:43 +0000501 /** Modify the current clip with the specified region. Note that unlike
502 clipRect() and clipPath() which transform their arguments by the current
503 matrix, clipRegion() assumes its argument is already in device
504 coordinates, and so no transformation is performed.
505 @param deviceRgn The region to apply to the current clip
506 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000507 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000508 void clipRegion(const SkRegion& deviceRgn,
509 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000510
511 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
512 specified region. This does not intersect or in any other way account
513 for the existing clip region.
514 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000515 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000516 void setClipRegion(const SkRegion& deviceRgn) {
517 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000518 }
519
reed@android.com8a1c16f2008-12-17 15:59:43 +0000520 /** Return true if the specified rectangle, after being transformed by the
521 current matrix, would lie completely outside of the current clip. Call
522 this to check if an area you intend to draw into is clipped out (and
523 therefore you can skip making the draw calls).
524 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000525 @return true if the rect (transformed by the canvas' matrix) does not
526 intersect with the canvas' clip
527 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000528 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000529
530 /** Return true if the specified path, after being transformed by the
531 current matrix, would lie completely outside of the current clip. Call
532 this to check if an area you intend to draw into is clipped out (and
533 therefore you can skip making the draw calls). Note, for speed it may
534 return false even if the path itself might not intersect the clip
535 (i.e. the bounds of the path intersects, but the path does not).
536 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000537 @return true if the path (transformed by the canvas' matrix) does not
538 intersect with the canvas' clip
539 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000540 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000541
542 /** Return true if the horizontal band specified by top and bottom is
543 completely clipped out. This is a conservative calculation, meaning
544 that it is possible that if the method returns false, the band may still
545 in fact be clipped out, but the converse is not true. If this method
546 returns true, then the band is guaranteed to be clipped out.
547 @param top The top of the horizontal band to compare with the clip
548 @param bottom The bottom of the horizontal and to compare with the clip
549 @return true if the horizontal band is completely clipped out (i.e. does
550 not intersect the current clip)
551 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000552 bool quickRejectY(SkScalar top, SkScalar bottom) const {
reed@google.comc0784db2013-12-13 21:16:12 +0000553 SkASSERT(top <= bottom);
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000554
555#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
556 // TODO: add a hasPerspective method similar to getLocalClipBounds. This
557 // would cache the SkMatrix::hasPerspective result. Alternatively, have
558 // the MC stack just set a hasPerspective boolean as it is updated.
559 if (this->getTotalMatrix().hasPerspective()) {
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000560 // TODO: consider implementing some half-plane test between the
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000561 // two Y planes and the device-bounds (i.e., project the top and
562 // bottom Y planes and then determine if the clip bounds is completely
563 // outside either one).
564 return false;
565 }
566#endif
567
reed@google.comc0784db2013-12-13 21:16:12 +0000568 const SkRect& clipR = this->getLocalClipBounds();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000569 // In the case where the clip is empty and we are provided with a
570 // negative top and positive bottom parameter then this test will return
571 // false even though it will be clipped. We have chosen to exclude that
572 // check as it is rare and would result double the comparisons.
reed@google.comc0784db2013-12-13 21:16:12 +0000573 return top >= clipR.fBottom || bottom <= clipR.fTop;
djsollen@google.com92d2a292012-02-27 16:17:59 +0000574 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000575
576 /** Return the bounds of the current clip (in local coordinates) in the
577 bounds parameter, and return true if it is non-empty. This can be useful
578 in a way similar to quickReject, in that it tells you that drawing
579 outside of these bounds will be clipped out.
580 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000581 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000582
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000583 /** Return the bounds of the current clip, in device coordinates; returns
584 true if non-empty. Maybe faster than getting the clip explicitly and
585 then taking its bounds.
586 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000587 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000588
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000589
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000591 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000592 @param a the alpha component (0..255) of the color to fill the canvas
593 @param r the red component (0..255) of the color to fill the canvas
594 @param g the green component (0..255) of the color to fill the canvas
595 @param b the blue component (0..255) of the color to fill the canvas
596 @param mode the mode to apply the color in (defaults to SrcOver)
597 */
598 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000599 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000600
601 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000602 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000603 @param color the color to draw with
604 @param mode the mode to apply the color in (defaults to SrcOver)
605 */
reed8eddfb52014-12-04 07:50:14 -0800606 void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000607
reedf4e0d9e2014-12-05 20:49:03 -0800608 /**
609 * Helper method for drawing a color in SRC mode, completely replacing all the pixels
610 * in the current clip with this color.
611 */
612 void clear(SkColor color) {
reed8eddfb52014-12-04 07:50:14 -0800613 this->drawColor(color, SkXfermode::kSrc_Mode);
614 }
reed@google.com2a981812011-04-14 18:59:28 +0000615
616 /**
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000617 * This makes the contents of the canvas undefined. Subsequent calls that
618 * require reading the canvas contents will produce undefined results. Examples
619 * include blending and readPixels. The actual implementation is backend-
620 * dependent and one legal implementation is to do nothing. Like clear(), this
621 * ignores the clip.
622 *
623 * This function should only be called if the caller intends to subsequently
624 * draw to the canvas. The canvas may do real work at discard() time in order
625 * to optimize performance on subsequent draws. Thus, if you call this and then
626 * never draw to the canvas subsequently you may pay a perfomance penalty.
627 */
628 void discard() { this->onDiscard(); }
629
630 /**
reed@google.com2a981812011-04-14 18:59:28 +0000631 * Fill the entire canvas' bitmap (restricted to the current clip) with the
632 * specified paint.
633 * @param paint The paint used to fill the canvas
634 */
reed0846f1b2015-01-09 14:17:40 -0800635 void drawPaint(const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000636
637 enum PointMode {
638 /** drawPoints draws each point separately */
639 kPoints_PointMode,
640 /** drawPoints draws each pair of points as a line segment */
641 kLines_PointMode,
642 /** drawPoints draws the array of points as a polygon */
643 kPolygon_PointMode
644 };
645
646 /** Draw a series of points, interpreted based on the PointMode mode. For
647 all modes, the count parameter is interpreted as the total number of
648 points. For kLine mode, count/2 line segments are drawn.
649 For kPoint mode, each point is drawn centered at its coordinate, and its
650 size is specified by the paint's stroke-width. It draws as a square,
651 unless the paint's cap-type is round, in which the points are drawn as
652 circles.
653 For kLine mode, each pair of points is drawn as a line segment,
654 respecting the paint's settings for cap/join/width.
655 For kPolygon mode, the entire array is drawn as a series of connected
656 line segments.
657 Note that, while similar, kLine and kPolygon modes draw slightly
658 differently than the equivalent path built with a series of moveto,
659 lineto calls, in that the path will draw all of its contours at once,
660 with no interactions if contours intersect each other (think XOR
661 xfermode). drawPoints always draws each element one at a time.
662 @param mode PointMode specifying how to draw the array of points.
663 @param count The number of points in the array
664 @param pts Array of points to draw
665 @param paint The paint used to draw the points
666 */
reed0846f1b2015-01-09 14:17:40 -0800667 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000668
669 /** Helper method for drawing a single point. See drawPoints() for a more
670 details.
671 */
672 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000673
reed@android.com8a1c16f2008-12-17 15:59:43 +0000674 /** Draws a single pixel in the specified color.
675 @param x The X coordinate of which pixel to draw
676 @param y The Y coordiante of which pixel to draw
677 @param color The color to draw
678 */
679 void drawPoint(SkScalar x, SkScalar y, SkColor color);
680
681 /** Draw a line segment with the specified start and stop x,y coordinates,
682 using the specified paint. NOTE: since a line is always "framed", the
683 paint's Style is ignored.
684 @param x0 The x-coordinate of the start point of the line
685 @param y0 The y-coordinate of the start point of the line
686 @param x1 The x-coordinate of the end point of the line
687 @param y1 The y-coordinate of the end point of the line
688 @param paint The paint used to draw the line
689 */
690 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
691 const SkPaint& paint);
692
693 /** Draw the specified rectangle using the specified paint. The rectangle
694 will be filled or stroked based on the Style in the paint.
695 @param rect The rect to be drawn
696 @param paint The paint used to draw the rect
697 */
reed0846f1b2015-01-09 14:17:40 -0800698 void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000699
700 /** Draw the specified rectangle using the specified paint. The rectangle
701 will be filled or framed based on the Style in the paint.
702 @param rect The rect to be drawn
703 @param paint The paint used to draw the rect
704 */
reed@google.com87001ed2014-02-17 16:28:05 +0000705 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000706 SkRect r;
707 r.set(rect); // promotes the ints to scalars
708 this->drawRect(r, paint);
709 }
reed@google.com4b226022011-01-11 18:32:13 +0000710
reed@android.com8a1c16f2008-12-17 15:59:43 +0000711 /** Draw the specified rectangle using the specified paint. The rectangle
712 will be filled or framed based on the Style in the paint.
713 @param left The left side of the rectangle to be drawn
714 @param top The top side of the rectangle to be drawn
715 @param right The right side of the rectangle to be drawn
716 @param bottom The bottom side of the rectangle to be drawn
717 @param paint The paint used to draw the rect
718 */
719 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
720 SkScalar bottom, const SkPaint& paint);
721
722 /** Draw the specified oval using the specified paint. The oval will be
723 filled or framed based on the Style in the paint.
724 @param oval The rectangle bounds of the oval to be drawn
725 @param paint The paint used to draw the oval
726 */
reed0846f1b2015-01-09 14:17:40 -0800727 void drawOval(const SkRect& oval, const SkPaint&);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000728
729 /**
730 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
731 * based on the Style in the paint.
732 *
733 * @param rrect The round-rect to draw
734 * @param paint The paint used to draw the round-rect
735 */
reed0846f1b2015-01-09 14:17:40 -0800736 void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000737
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000738 /**
739 * Draw the annulus formed by the outer and inner rrects. The results
740 * are undefined if the outer does not contain the inner.
741 */
742 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
743
reed@android.com8a1c16f2008-12-17 15:59:43 +0000744 /** Draw the specified circle using the specified paint. If radius is <= 0,
745 then nothing will be drawn. The circle will be filled
746 or framed based on the Style in the paint.
747 @param cx The x-coordinate of the center of the cirle to be drawn
748 @param cy The y-coordinate of the center of the cirle to be drawn
749 @param radius The radius of the cirle to be drawn
750 @param paint The paint used to draw the circle
751 */
752 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
753 const SkPaint& paint);
754
755 /** Draw the specified arc, which will be scaled to fit inside the
756 specified oval. If the sweep angle is >= 360, then the oval is drawn
757 completely. Note that this differs slightly from SkPath::arcTo, which
758 treats the sweep angle mod 360.
759 @param oval The bounds of oval used to define the shape of the arc
760 @param startAngle Starting angle (in degrees) where the arc begins
761 @param sweepAngle Sweep angle (in degrees) measured clockwise
762 @param useCenter true means include the center of the oval. For filling
763 this will draw a wedge. False means just use the arc.
764 @param paint The paint used to draw the arc
765 */
766 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
767 bool useCenter, const SkPaint& paint);
768
769 /** Draw the specified round-rect using the specified paint. The round-rect
770 will be filled or framed based on the Style in the paint.
771 @param rect The rectangular bounds of the roundRect to be drawn
772 @param rx The x-radius of the oval used to round the corners
773 @param ry The y-radius of the oval used to round the corners
774 @param paint The paint used to draw the roundRect
775 */
776 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
777 const SkPaint& paint);
778
779 /** Draw the specified path using the specified paint. The path will be
780 filled or framed based on the Style in the paint.
781 @param path The path to be drawn
782 @param paint The paint used to draw the path
783 */
reed0846f1b2015-01-09 14:17:40 -0800784 void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000785
piotaixrd52893c2014-09-25 14:39:40 -0700786 /** Draw the specified image, with its top/left corner at (x,y), using the
787 specified paint, transformed by the current matrix.
788
789 @param image The image to be drawn
790 @param left The position of the left side of the image being drawn
791 @param top The position of the top side of the image being drawn
792 @param paint The paint used to draw the image, or NULL
793 */
reed0846f1b2015-01-09 14:17:40 -0800794 void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
piotaixrb5fae932014-09-24 13:03:30 -0700795
reeda5517e22015-07-14 10:54:12 -0700796 /**
797 * Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
798 * trading off speed for exactness.
799 *
800 * When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
801 * the pixels in the image. If there is a src-rect specified, it is intended to restrict the
802 * pixels that will be read. However, for performance reasons, some implementations may slow
803 * down if they cannot read 1-pixel past the src-rect boundary at times.
804 *
805 * This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
806 * If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
807 * must be strictly respected, the caller should pass kStrict.
808 */
809 enum SrcRectConstraint {
810 /**
811 * If kStrict is specified, the implementation must respect the src-rect
812 * (if specified) strictly, and will never sample outside of those bounds during sampling
813 * even when filtering. This may be slower than kFast.
814 */
815 kStrict_SrcRectConstraint,
816
817 /**
818 * If kFast is specified, the implementation may sample outside of the src-rect
819 * (if specified) by at most 1 pixel when filtering. This allows greater flexibility
820 * to the implementation and can make the draw much faster.
821 */
822 kFast_SrcRectConstraint,
823 };
824
825 /** Draw the specified image, scaling and translating so that it fills the specified
826 * dst rect. If the src rect is non-null, only that subset of the image is transformed
827 * and drawn.
828 *
829 * @param image The image to be drawn
830 * @param src Optional: specify the subset of the image to be drawn
831 * @param dst The destination rectangle where the scaled/translated
832 * image will be drawn
833 * @param paint The paint used to draw the image, or NULL
834 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
835 */
reed0846f1b2015-01-09 14:17:40 -0800836 void drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
reed84984ef2015-07-17 07:09:43 -0700837 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reeda5517e22015-07-14 10:54:12 -0700838
reed84984ef2015-07-17 07:09:43 -0700839 void drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst) {
840 this->drawImageRect(image, src, dst, NULL, kStrict_SrcRectConstraint);
reeda5517e22015-07-14 10:54:12 -0700841 }
842
843 void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint = NULL) {
844 // With no src-rect, the constraint value is ignored, so we just use the default.
845 this->drawImageRect(image, NULL, dst, paint, kStrict_SrcRectConstraint);
846 }
piotaixrb5fae932014-09-24 13:03:30 -0700847
reed84984ef2015-07-17 07:09:43 -0700848 void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
849 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
850
reed4c21dc52015-06-25 12:32:03 -0700851 /**
852 * Draw the image stretched differentially to fit into dst.
853 * center is a rect within the image, and logically divides the image
854 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
855 * image is the "center", then the center-rect should be [2, 2, 3, 3].
856 *
857 * If the dst is >= the image size, then...
858 * - The 4 corners are not stretched at all.
859 * - The sides are stretched in only one axis.
860 * - The center is stretched in both axes.
861 * Else, for each axis where dst < image,
862 * - The corners shrink proportionally
863 * - The sides (along the shrink axis) and center are not drawn
864 */
865 void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
866 const SkPaint* paint = NULL);
867
reed@android.com8a1c16f2008-12-17 15:59:43 +0000868 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
869 specified paint, transformed by the current matrix. Note: if the paint
870 contains a maskfilter that generates a mask which extends beyond the
871 bitmap's original width/height, then the bitmap will be drawn as if it
872 were in a Shader with CLAMP mode. Thus the color outside of the original
873 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000874
875 If a shader is present on the paint it will be ignored, except in the
reed@google.comf20fc242014-03-26 13:44:58 +0000876 case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000877 generated by the shader.
878
reed@android.com8a1c16f2008-12-17 15:59:43 +0000879 @param bitmap The bitmap to be drawn
880 @param left The position of the left side of the bitmap being drawn
881 @param top The position of the top side of the bitmap being drawn
882 @param paint The paint used to draw the bitmap, or NULL
883 */
reed0846f1b2015-01-09 14:17:40 -0800884 void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
885 const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000886
reeda5517e22015-07-14 10:54:12 -0700887 /** Draw the specified bitmap, scaling and translating so that it fills the specified
888 * dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
889 * and drawn.
890 *
891 * @param bitmap The bitmap to be drawn
892 * @param src Optional: specify the subset of the bitmap to be drawn
893 * @param dst The destination rectangle where the scaled/translated
894 * bitmap will be drawn
895 * @param paint The paint used to draw the bitmap, or NULL
896 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
897 */
reed84984ef2015-07-17 07:09:43 -0700898#ifdef SK_SUPPORT_LEGACY_DRAWBITMAPRECTFLAGS_TYPE
reeda5517e22015-07-14 10:54:12 -0700899 void drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
900 const SkPaint* paint, SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700901#else
902 void drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
903 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
904#endif
reeda5517e22015-07-14 10:54:12 -0700905
906 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint = NULL) {
907 this->drawBitmapRect(bitmap, NULL, dst, paint, kStrict_SrcRectConstraint);
908 }
909
reed84984ef2015-07-17 07:09:43 -0700910 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
911 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
912
913#ifdef SK_SUPPORT_LEGACY_DRAWBITMAPRECTFLAGS_TYPE
reeda5517e22015-07-14 10:54:12 -0700914 // IMPORTANT that thse be value-equal with SrcRectConstraint (during transition period)
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000915 enum DrawBitmapRectFlags {
robertphillips@google.com31acc112013-08-20 12:13:48 +0000916 kNone_DrawBitmapRectFlag = 0x0,
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000917 /**
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000918 * When filtering is enabled, allow the color samples outside of
skia.committer@gmail.com74758112013-08-17 07:01:54 +0000919 * the src rect (but still in the src bitmap) to bleed into the
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000920 * drawn portion
921 */
robertphillips@google.com31acc112013-08-20 12:13:48 +0000922 kBleed_DrawBitmapRectFlag = 0x1,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000923 };
924
reed@android.com8a1c16f2008-12-17 15:59:43 +0000925 /** Draw the specified bitmap, with the specified matrix applied (before the
926 canvas' matrix is applied).
927 @param bitmap The bitmap to be drawn
928 @param src Optional: specify the subset of the bitmap to be drawn
929 @param dst The destination rectangle where the scaled/translated
930 image will be drawn
931 @param paint The paint used to draw the bitmap, or NULL
932 */
reed0846f1b2015-01-09 14:17:40 -0800933 void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
934 const SkPaint* paint = NULL,
935 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000936
reed@google.com71121732012-09-18 15:14:33 +0000937 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000938 const SkRect& dst, const SkPaint* paint = NULL,
robertphillips@google.com31acc112013-08-20 12:13:48 +0000939 DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) {
reed@google.com71121732012-09-18 15:14:33 +0000940 SkRect realSrcStorage;
941 SkRect* realSrcPtr = NULL;
942 if (isrc) {
943 realSrcStorage.set(*isrc);
944 realSrcPtr = &realSrcStorage;
945 }
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +0000946 this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags);
reed@google.com71121732012-09-18 15:14:33 +0000947 }
reed84984ef2015-07-17 07:09:43 -0700948#endif
skia.committer@gmail.comc1ad0222012-09-19 02:01:47 +0000949
reed@google.comf0b5e112011-09-07 11:57:34 +0000950 /**
951 * Draw the bitmap stretched differentially to fit into dst.
952 * center is a rect within the bitmap, and logically divides the bitmap
953 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
954 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
955 *
956 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000957 * - The 4 corners are not stretched at all.
958 * - The sides are stretched in only one axis.
959 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000960 * Else, for each axis where dst < bitmap,
961 * - The corners shrink proportionally
962 * - The sides (along the shrink axis) and center are not drawn
963 */
reed0846f1b2015-01-09 14:17:40 -0800964 void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
965 const SkPaint* paint = NULL);
reed@google.comf0b5e112011-09-07 11:57:34 +0000966
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967 /** Draw the specified bitmap, with its top/left corner at (x,y),
968 NOT transformed by the current matrix. Note: if the paint
969 contains a maskfilter that generates a mask which extends beyond the
970 bitmap's original width/height, then the bitmap will be drawn as if it
971 were in a Shader with CLAMP mode. Thus the color outside of the original
972 width/height will be the edge color replicated.
973 @param bitmap The bitmap to be drawn
974 @param left The position of the left side of the bitmap being drawn
975 @param top The position of the top side of the bitmap being drawn
976 @param paint The paint used to draw the bitmap, or NULL
977 */
reed0846f1b2015-01-09 14:17:40 -0800978 void drawSprite(const SkBitmap& bitmap, int left, int top, const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000979
980 /** Draw the text, with origin at (x,y), using the specified paint.
981 The origin is interpreted based on the Align setting in the paint.
982 @param text The text to be drawn
983 @param byteLength The number of bytes to read from the text parameter
984 @param x The x-coordinate of the origin of the text being drawn
985 @param y The y-coordinate of the origin of the text being drawn
986 @param paint The paint used for the text (e.g. color, size, style)
987 */
reedf7430cc2014-12-21 11:38:35 -0800988 void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
989 const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990
991 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000992 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000993 @param text The text to be drawn
994 @param byteLength The number of bytes to read from the text parameter
995 @param pos Array of positions, used to position each character
996 @param paint The paint used for the text (e.g. color, size, style)
997 */
reedf7430cc2014-12-21 11:38:35 -0800998 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
999 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +00001000
reed@android.com8a1c16f2008-12-17 15:59:43 +00001001 /** Draw the text, with each character/glyph origin specified by the x
1002 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +00001003 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001004 @param text The text to be drawn
1005 @param byteLength The number of bytes to read from the text parameter
1006 @param xpos Array of x-positions, used to position each character
1007 @param constY The shared Y coordinate for all of the positions
1008 @param paint The paint used for the text (e.g. color, size, style)
1009 */
reedf7430cc2014-12-21 11:38:35 -08001010 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
1011 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +00001012
reed@android.com8a1c16f2008-12-17 15:59:43 +00001013 /** Draw the text, with origin at (x,y), using the specified paint, along
1014 the specified path. The paint's Align setting determins where along the
1015 path to start the text.
1016 @param text The text to be drawn
1017 @param byteLength The number of bytes to read from the text parameter
1018 @param path The path the text should follow for its baseline
1019 @param hOffset The distance along the path to add to the text's
1020 starting position
1021 @param vOffset The distance above(-) or below(+) the path to
1022 position the text
1023 @param paint The paint used for the text
1024 */
reedf7430cc2014-12-21 11:38:35 -08001025 void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
reed@android.com8a1c16f2008-12-17 15:59:43 +00001026 SkScalar vOffset, const SkPaint& paint);
1027
1028 /** Draw the text, with origin at (x,y), using the specified paint, along
1029 the specified path. The paint's Align setting determins where along the
1030 path to start the text.
1031 @param text The text to be drawn
1032 @param byteLength The number of bytes to read from the text parameter
1033 @param path The path the text should follow for its baseline
1034 @param matrix (may be null) Applied to the text before it is
1035 mapped onto the path
1036 @param paint The paint used for the text
1037 */
reedf7430cc2014-12-21 11:38:35 -08001038 void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
1039 const SkMatrix* matrix, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001040
fmalita00d5c2c2014-08-21 08:53:26 -07001041 /** Draw the text blob, offset by (x,y), using the specified paint.
1042 @param blob The text blob to be drawn
1043 @param x The x-offset of the text being drawn
1044 @param y The y-offset of the text being drawn
1045 @param paint The paint used for the text (e.g. color, size, style)
1046 */
1047 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
1048
reed@android.com8a1c16f2008-12-17 15:59:43 +00001049 /** Draw the picture into this canvas. This method effective brackets the
1050 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +00001051 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001052 @param picture The recorded drawing commands to playback into this
1053 canvas.
1054 */
reed1c2c4412015-04-30 13:09:24 -07001055 void drawPicture(const SkPicture* picture) {
1056 this->drawPicture(picture, NULL, NULL);
1057 }
robertphillips9b14f262014-06-04 05:40:44 -07001058
reedd5fa1a42014-08-09 11:08:05 -07001059 /**
1060 * Draw the picture into this canvas.
1061 *
1062 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1063 * logically equivalent to
1064 * save/concat/drawPicture/restore
1065 *
1066 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1067 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1068 * This is logically equivalent to
1069 * saveLayer(paint)/drawPicture/restore
1070 */
1071 void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
1072
reed@android.com8a1c16f2008-12-17 15:59:43 +00001073 enum VertexMode {
1074 kTriangles_VertexMode,
1075 kTriangleStrip_VertexMode,
1076 kTriangleFan_VertexMode
1077 };
reed@google.com4b226022011-01-11 18:32:13 +00001078
reed@android.com8a1c16f2008-12-17 15:59:43 +00001079 /** Draw the array of vertices, interpreted as triangles (based on mode).
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001080
1081 If both textures and vertex-colors are NULL, it strokes hairlines with
1082 the paint's color. This behavior is a useful debugging mode to visualize
1083 the mesh.
1084
reed@android.com8a1c16f2008-12-17 15:59:43 +00001085 @param vmode How to interpret the array of vertices
1086 @param vertexCount The number of points in the vertices array (and
1087 corresponding texs and colors arrays if non-null)
1088 @param vertices Array of vertices for the mesh
1089 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +00001090 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001091 @param colors May be null. If not null, specifies a color for each
1092 vertex, to be interpolated across the triangle.
1093 @param xmode Used if both texs and colors are present. In this
1094 case the colors are combined with the texture using mode,
1095 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +00001096 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001097 @param indices If not null, array of indices to reference into the
1098 vertex (texs, colors) array.
1099 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001100 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001101 */
reed0846f1b2015-01-09 14:17:40 -08001102 void drawVertices(VertexMode vmode, int vertexCount,
1103 const SkPoint vertices[], const SkPoint texs[],
1104 const SkColor colors[], SkXfermode* xmode,
1105 const uint16_t indices[], int indexCount,
1106 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001107
dandovb3c9d1c2014-08-12 08:34:29 -07001108 /**
1109 Draw a cubic coons patch
mtklein6cfa73a2014-08-13 13:33:49 -07001110
dandovb3c9d1c2014-08-12 08:34:29 -07001111 @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1112 starting at the top left corner.
1113 @param colors specifies the colors for the corners which will be bilerp across the patch,
1114 their order is clockwise starting at the top left corner.
mtklein6cfa73a2014-08-13 13:33:49 -07001115 @param texCoords specifies the texture coordinates that will be bilerp across the patch,
dandovb3c9d1c2014-08-12 08:34:29 -07001116 their order is the same as the colors.
mtklein6cfa73a2014-08-13 13:33:49 -07001117 @param xmode specifies how are the colors and the textures combined if both of them are
dandovb3c9d1c2014-08-12 08:34:29 -07001118 present.
dandov963137b2014-08-07 07:49:53 -07001119 @param paint Specifies the shader/texture if present.
1120 */
dandovb3c9d1c2014-08-12 08:34:29 -07001121 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1122 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001123
reed3cb38402015-02-06 08:36:15 -08001124 /**
reed71c3c762015-06-24 10:29:17 -07001125 * Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
1126 * coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
1127 * into a quad.
1128 *
1129 * xform maps [0, 0, tex.width, tex.height] -> quad
1130 *
1131 * The color array is optional. When specified, each color modulates the pixels in its
1132 * corresponding quad (via the specified SkXfermode::Mode).
1133 *
1134 * The cullRect is optional. When specified, it must be a conservative bounds of all of the
1135 * resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
1136 * intersect the current clip.
1137 *
1138 * The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
1139 * and xfermode are used to affect each of the quads.
1140 */
1141 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1142 const SkColor colors[], int count, SkXfermode::Mode, const SkRect* cullRect,
1143 const SkPaint* paint);
1144
1145 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
1146 const SkRect* cullRect, const SkPaint* paint) {
1147 this->drawAtlas(atlas, xform, tex, NULL, count, SkXfermode::kDst_Mode, cullRect, paint);
1148 }
1149
1150 /**
reed3cb38402015-02-06 08:36:15 -08001151 * Draw the contents of this drawable into the canvas. If the canvas is async
1152 * (e.g. it is recording into a picture) then the drawable will be referenced instead,
1153 * to have its draw() method called when the picture is finalized.
1154 *
1155 * If the intent is to force the contents of the drawable into this canvas immediately,
1156 * then drawable->draw(canvas) may be called.
1157 */
reeda8db7282015-07-07 10:22:31 -07001158 void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL);
1159 void drawDrawable(SkDrawable*, SkScalar x, SkScalar y);
reed6a070dc2014-11-11 19:36:09 -08001160
reed@android.com8a1c16f2008-12-17 15:59:43 +00001161 //////////////////////////////////////////////////////////////////////////
reed@google.com4b226022011-01-11 18:32:13 +00001162
reed@android.com8a1c16f2008-12-17 15:59:43 +00001163 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001164 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001165 @return the canvas' filter (or NULL).
1166 */
1167 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001168
reed@android.com8a1c16f2008-12-17 15:59:43 +00001169 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1170 As a convenience, the parameter is returned. If an existing filter
1171 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001172 refcnt is incremented. The filter is saved/restored, just like the
1173 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001174 @param filter the new filter (or NULL)
1175 @return the new filter
1176 */
1177 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
1178
1179 //////////////////////////////////////////////////////////////////////////
1180
reed@google.com754de5f2014-02-24 19:38:20 +00001181 /**
1182 * Return true if the current clip is empty (i.e. nothing will draw).
1183 * Note: this is not always a free call, so it should not be used
1184 * more often than necessary. However, once the canvas has computed this
1185 * result, subsequent calls will be cheap (until the clip state changes,
1186 * which can happen on any clip..() or restore() call.
1187 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001188 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001189
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001190 /**
1191 * Returns true if the current clip is just a (non-empty) rectangle.
1192 * Returns false if the clip is empty, or if it is complex.
1193 */
1194 virtual bool isClipRect() const;
1195
reed@android.com8a1c16f2008-12-17 15:59:43 +00001196 /** Return the current matrix on the canvas.
1197 This does not account for the translate in any of the devices.
1198 @return The current matrix on the canvas.
1199 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001200 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001201
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001202 /** Return the clip stack. The clip stack stores all the individual
1203 * clips organized by the save/restore frame in which they were
1204 * added.
1205 * @return the current clip stack ("list" of individual clip elements)
1206 */
1207 const SkClipStack* getClipStack() const {
reed687fa1c2015-04-07 08:00:56 -07001208 return fClipStack;
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001209 }
1210
fmalitac3b589a2014-06-05 12:40:07 -07001211 typedef SkCanvasClipVisitor ClipVisitor;
reed@google.com90c07ea2012-04-13 13:50:27 +00001212 /**
1213 * Replays the clip operations, back to front, that have been applied to
1214 * the canvas, calling the appropriate method on the visitor for each
1215 * clip. All clips have already been transformed into device space.
1216 */
1217 void replayClips(ClipVisitor*) const;
1218
reed@android.com8a1c16f2008-12-17 15:59:43 +00001219 ///////////////////////////////////////////////////////////////////////////
1220
1221 /** After calling saveLayer(), there can be any number of devices that make
1222 up the top-most drawing area. LayerIter can be used to iterate through
1223 those devices. Note that the iterator is only valid until the next API
1224 call made on the canvas. Ownership of all pointers in the iterator stays
1225 with the canvas, so none of them should be modified or deleted.
1226 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +00001227 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001228 public:
1229 /** Initialize iterator with canvas, and set values for 1st device */
1230 LayerIter(SkCanvas*, bool skipEmptyClips);
1231 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +00001232
reed@android.com8a1c16f2008-12-17 15:59:43 +00001233 /** Return true if the iterator is done */
1234 bool done() const { return fDone; }
1235 /** Cycle to the next device */
1236 void next();
reed@google.com4b226022011-01-11 18:32:13 +00001237
reed@android.com8a1c16f2008-12-17 15:59:43 +00001238 // These reflect the current device in the iterator
1239
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001240 SkBaseDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001241 const SkMatrix& matrix() const;
1242 const SkRegion& clip() const;
1243 const SkPaint& paint() const;
1244 int x() const;
1245 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001246
reed@android.com8a1c16f2008-12-17 15:59:43 +00001247 private:
1248 // used to embed the SkDrawIter object directly in our instance, w/o
1249 // having to expose that class def to the public. There is an assert
1250 // in our constructor to ensure that fStorage is large enough
1251 // (though needs to be a compile-time-assert!). We use intptr_t to work
1252 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001253 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001254 class SkDrawIter* fImpl; // this points at fStorage
1255 SkPaint fDefaultPaint;
1256 bool fDone;
1257 };
1258
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001259 // don't call
reed@google.com9c135db2014-03-12 18:28:35 +00001260 GrRenderTarget* internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001261
reedd990e2f2014-12-22 11:58:30 -08001262 // don't call
1263 static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1264 static bool Internal_Private_GetIgnoreSaveLayerBounds();
reed0acf1b42014-12-22 16:12:38 -08001265 static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1266 static bool Internal_Private_GetTreatSpriteAsBitmap();
reedd990e2f2014-12-22 11:58:30 -08001267
reed@android.com8a1c16f2008-12-17 15:59:43 +00001268protected:
reed@google.com76f10a32014-02-05 15:32:21 +00001269 // default impl defers to getDevice()->newSurface(info)
reed4a8126e2014-09-22 07:29:03 -07001270 virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
reed@google.com76f10a32014-02-05 15:32:21 +00001271
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001272 // default impl defers to its device
reed884e97c2015-05-26 11:31:54 -07001273 virtual bool onPeekPixels(SkPixmap*);
1274 virtual bool onAccessTopLayerPixels(SkPixmap*);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001275
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001276 // Subclass save/restore notifiers.
1277 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1278 // willSaveLayer()'s return value may suppress full layer allocation.
1279 enum SaveLayerStrategy {
1280 kFullLayer_SaveLayerStrategy,
1281 kNoLayer_SaveLayerStrategy
1282 };
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001283
fmalita6ca763f2014-06-17 13:52:18 -07001284 virtual void willSave() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001285 virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags) {
1286 return kFullLayer_SaveLayerStrategy;
1287 }
1288 virtual void willRestore() {}
mtklein6cfa73a2014-08-13 13:33:49 -07001289 virtual void didRestore() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001290 virtual void didConcat(const SkMatrix&) {}
1291 virtual void didSetMatrix(const SkMatrix&) {}
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001292
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001293 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1294
reed@google.come0d9ce82014-04-23 04:00:17 +00001295 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1296 SkScalar y, const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001297
reed@google.come0d9ce82014-04-23 04:00:17 +00001298 virtual void onDrawPosText(const void* text, size_t byteLength,
1299 const SkPoint pos[], const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001300
reed@google.come0d9ce82014-04-23 04:00:17 +00001301 virtual void onDrawPosTextH(const void* text, size_t byteLength,
1302 const SkScalar xpos[], SkScalar constY,
1303 const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001304
reed@google.come0d9ce82014-04-23 04:00:17 +00001305 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1306 const SkPath& path, const SkMatrix* matrix,
1307 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001308
fmalita00d5c2c2014-08-21 08:53:26 -07001309 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1310 const SkPaint& paint);
1311
dandovb3c9d1c2014-08-12 08:34:29 -07001312 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
1313 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@google.come0d9ce82014-04-23 04:00:17 +00001314
reeda8db7282015-07-07 10:22:31 -07001315 virtual void onDrawDrawable(SkDrawable*, const SkMatrix*);
reed6a070dc2014-11-11 19:36:09 -08001316
reed41af9662015-01-05 07:49:08 -08001317 virtual void onDrawPaint(const SkPaint&);
1318 virtual void onDrawRect(const SkRect&, const SkPaint&);
1319 virtual void onDrawOval(const SkRect&, const SkPaint&);
1320 virtual void onDrawRRect(const SkRRect&, const SkPaint&);
1321 virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
1322 virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
1323 const SkPoint texs[], const SkColor colors[], SkXfermode*,
1324 const uint16_t indices[], int indexCount, const SkPaint&);
mtklein2766c002015-06-26 11:45:03 -07001325
reed71c3c762015-06-24 10:29:17 -07001326 virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
1327 int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001328 virtual void onDrawPath(const SkPath&, const SkPaint&);
1329 virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
reeda5517e22015-07-14 10:54:12 -07001330 virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*
1331 SRC_RECT_CONSTRAINT_PARAM(constraint));
reed4c21dc52015-06-25 12:32:03 -07001332 virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
1333 const SkPaint*);
1334
reed41af9662015-01-05 07:49:08 -08001335 virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
1336 virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
reeda5517e22015-07-14 10:54:12 -07001337 SK_VIRTUAL_CONSTRAINT_TYPE);
reed41af9662015-01-05 07:49:08 -08001338 virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
1339 const SkPaint*);
1340 virtual void onDrawSprite(const SkBitmap&, int left, int top, const SkPaint*);
1341
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001342 enum ClipEdgeStyle {
1343 kHard_ClipEdgeStyle,
1344 kSoft_ClipEdgeStyle
1345 };
1346
1347 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1348 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1349 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1350 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1351
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +00001352 virtual void onDiscard();
1353
reedd5fa1a42014-08-09 11:08:05 -07001354 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
robertphillips9b14f262014-06-04 05:40:44 -07001355
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001356 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001357 // returns this. Subclasses that encapsulate an indirect canvas may
1358 // need to overload this method. The impl must keep track of this, as it
1359 // is not released or deleted by the caller.
1360 virtual SkCanvas* canvasForDrawIter();
1361
junov@chromium.orga907ac32012-02-24 21:54:07 +00001362 // Clip rectangle bounds. Called internally by saveLayer.
1363 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001364 // If non-NULL, The imageFilter parameter will be used to expand the clip
1365 // and offscreen bounds for any margin required by the filter DAG.
junov@chromium.orga907ac32012-02-24 21:54:07 +00001366 bool clipRectBounds(const SkRect* bounds, SaveFlags flags,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001367 SkIRect* intersection,
1368 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001369
reedc83a2972015-07-16 07:40:45 -07001370private:
1371 enum ShaderOverrideOpacity {
1372 kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
1373 kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
1374 kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
1375 };
1376
reed@google.com97af1a62012-08-28 12:19:02 +00001377 // notify our surface (if we have one) that we are about to draw, so it
1378 // can perform copy-on-write or invalidate any cached images
reedc83a2972015-07-16 07:40:45 -07001379 void predrawNotify(bool willOverwritesEntireSurface = false);
1380 void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
1381 void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
1382 this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
1383 : kNotOpaque_ShaderOverrideOpacity);
1384 }
reed@google.com97af1a62012-08-28 12:19:02 +00001385
reed@android.com8a1c16f2008-12-17 15:59:43 +00001386 class MCRec;
1387
reed687fa1c2015-04-07 08:00:56 -07001388 SkAutoTUnref<SkClipStack> fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001389 SkDeque fMCStack;
1390 // points to top of stack
1391 MCRec* fMCRec;
1392 // the first N recs that can fit here mean we won't call malloc
reedb679ca82015-04-07 04:40:48 -07001393 enum {
reeda499f902015-05-01 09:34:31 -07001394 kMCRecSize = 128, // most recent measurement
1395 kMCRecCount = 8, // common depth for save/restores
reed86a17e72015-05-14 12:25:22 -07001396 kDeviceCMSize = 136, // most recent measurement
reedb679ca82015-04-07 04:40:48 -07001397 };
1398 intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
reeda499f902015-05-01 09:34:31 -07001399 intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001400
reed4a8126e2014-09-22 07:29:03 -07001401 const SkSurfaceProps fProps;
1402
reed2ff1fce2014-12-11 07:07:37 -08001403 int fSaveCount; // value returned by getSaveCount()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001404
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001405 SkMetaData* fMetaData;
1406
reed@google.com97af1a62012-08-28 12:19:02 +00001407 SkSurface_Base* fSurfaceBase;
1408 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1409 void setSurfaceBase(SkSurface_Base* sb) {
1410 fSurfaceBase = sb;
1411 }
1412 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001413 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001414
reed@android.com8a1c16f2008-12-17 15:59:43 +00001415 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1416 void updateDeviceCMCache();
1417
reed2ff1fce2014-12-11 07:07:37 -08001418 void doSave();
1419 void checkForDeferredSave();
1420
reed@google.com9c135db2014-03-12 18:28:35 +00001421 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001422 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001423 friend class SkLua; // needs top layer size and offset
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +00001424 friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
reed@google.com9c135db2014-03-12 18:28:35 +00001425 friend class SkDeferredDevice; // needs getTopDevice()
reed52d9ac62014-06-30 09:05:34 -07001426 friend class SkSurface_Raster; // needs getDevice()
reedd9544982014-09-09 18:46:22 -07001427 friend class SkRecorder; // InitFlags
1428 friend class SkNoSaveLayerCanvas; // InitFlags
fmalita2d97bc12014-11-20 10:44:58 -08001429 friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
reedc83a2972015-07-16 07:40:45 -07001430 friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
piotaixrb5fae932014-09-24 13:03:30 -07001431
reedd9544982014-09-09 18:46:22 -07001432 enum InitFlags {
1433 kDefault_InitFlags = 0,
1434 kConservativeRasterClip_InitFlag = 1 << 0,
1435 };
reed78e27682014-11-19 08:04:34 -08001436 SkCanvas(const SkIRect& bounds, InitFlags);
robertphillipsfcf78292015-06-19 11:49:52 -07001437 SkCanvas(SkBaseDevice* device, InitFlags);
reedd9544982014-09-09 18:46:22 -07001438
mtkleinfeaadee2015-04-08 11:25:48 -07001439 void resetForNextPicture(const SkIRect& bounds);
1440
reed8f2e7912014-09-04 12:45:18 -07001441 // needs gettotalclip()
tfarinaa5414c42014-10-10 06:19:09 -07001442 friend class SkCanvasStateUtils;
piotaixrb5fae932014-09-24 13:03:30 -07001443
reed4a8126e2014-09-22 07:29:03 -07001444 // call this each time we attach ourselves to a device
1445 // - constructor
1446 // - internalSaveLayer
1447 void setupDevice(SkBaseDevice*);
1448
reedd9544982014-09-09 18:46:22 -07001449 SkBaseDevice* init(SkBaseDevice*, InitFlags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001450
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001451 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00001452 * Gets the size/origin of the top level layer in global canvas coordinates. We don't want this
1453 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1454 */
1455 SkISize getTopLayerSize() const;
1456 SkIPoint getTopLayerOrigin() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001457
reed@google.comf0b5e112011-09-07 11:57:34 +00001458 // internal methods are not virtual, so they can safely be called by other
1459 // canvas apis, without confusing subclasses (like SkPictureRecording)
robertphillips@google.com9bf380c2013-07-25 12:10:42 +00001460 void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint);
reed@google.com71121732012-09-18 15:14:33 +00001461 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001462 const SkRect& dst, const SkPaint* paint,
reeda5517e22015-07-14 10:54:12 -07001463 SrcRectConstraint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001464 void internalDrawPaint(const SkPaint& paint);
reed76033be2015-03-14 10:54:31 -07001465 void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy);
reed61f501f2015-04-29 08:34:00 -07001466 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001467
reed@android.com8a1c16f2008-12-17 15:59:43 +00001468 // shared by save() and saveLayer()
reed2ff1fce2014-12-11 07:07:37 -08001469 void internalSave();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001470 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001471 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1472 const SkRect& r, SkScalar textSize);
1473 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1474 const char text[], size_t byteLength,
1475 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001476
reedfa35f8e2014-09-04 12:14:36 -07001477 // only for canvasutils
1478 const SkRegion& internal_private_getTotalClip() const;
1479
reedc83a2972015-07-16 07:40:45 -07001480 /*
1481 * Returns true if drawing the specified rect (or all if it is null) with the specified
1482 * paint (or default if null) would overwrite the entire root device of the canvas
1483 * (i.e. the canvas' surface if it had one).
1484 */
1485 bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
1486
1487
reed@android.com8a1c16f2008-12-17 15:59:43 +00001488 /* These maintain a cache of the clip bounds in local coordinates,
1489 (converted to 2s-compliment if floats are slow).
1490 */
reed@google.comc0784db2013-12-13 21:16:12 +00001491 mutable SkRect fCachedLocalClipBounds;
1492 mutable bool fCachedLocalClipBoundsDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001493 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001494 bool fAllowSimplifyClip;
reedd9544982014-09-09 18:46:22 -07001495 bool fConservativeRasterClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001496
reed@google.comc0784db2013-12-13 21:16:12 +00001497 const SkRect& getLocalClipBounds() const {
1498 if (fCachedLocalClipBoundsDirty) {
1499 if (!this->getClipBounds(&fCachedLocalClipBounds)) {
1500 fCachedLocalClipBounds.setEmpty();
1501 }
1502 fCachedLocalClipBoundsDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001503 }
reed@google.comc0784db2013-12-13 21:16:12 +00001504 return fCachedLocalClipBounds;
reed@android.comba09de42010-02-05 20:46:05 +00001505 }
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001506
reed@google.com5c3d1472011-02-22 19:12:23 +00001507 class AutoValidateClip : ::SkNoncopyable {
1508 public:
1509 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1510 fCanvas->validateClip();
1511 }
1512 ~AutoValidateClip() { fCanvas->validateClip(); }
1513
1514 private:
1515 const SkCanvas* fCanvas;
1516 };
1517
1518#ifdef SK_DEBUG
1519 void validateClip() const;
1520#else
1521 void validateClip() const {}
1522#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001523
1524 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001525};
1526
1527/** Stack helper class to automatically call restoreToCount() on the canvas
1528 when this object goes out of scope. Use this to guarantee that the canvas
1529 is restored to a known state.
1530*/
1531class SkAutoCanvasRestore : SkNoncopyable {
1532public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001533 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1534 if (fCanvas) {
1535 fSaveCount = canvas->getSaveCount();
1536 if (doSave) {
1537 canvas->save();
1538 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001539 }
1540 }
1541 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001542 if (fCanvas) {
1543 fCanvas->restoreToCount(fSaveCount);
1544 }
1545 }
1546
1547 /**
1548 * Perform the restore now, instead of waiting for the destructor. Will
1549 * only do this once.
1550 */
1551 void restore() {
1552 if (fCanvas) {
1553 fCanvas->restoreToCount(fSaveCount);
1554 fCanvas = NULL;
1555 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001556 }
1557
1558private:
1559 SkCanvas* fCanvas;
1560 int fSaveCount;
1561};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001562#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001563
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001564/**
1565 * If the caller wants read-only access to the pixels in a canvas, it can just
1566 * call canvas->peekPixels(), since that is the fastest way to "peek" at the
1567 * pixels on a raster-backed canvas.
1568 *
1569 * If the canvas has pixels, but they are not readily available to the CPU
1570 * (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will
1571 * succeed (though be slower, since it will return a copy of the pixels).
1572 *
1573 * SkAutoROCanvasPixels encapsulates these two techniques, trying first to call
1574 * peekPixels() (for performance), but if that fails, calling readPixels() and
1575 * storing the copy locally.
1576 *
1577 * The caller must respect the restrictions associated with peekPixels(), since
1578 * that may have been called: The returned information is invalidated if...
1579 * - any API is called on the canvas (or its parent surface if present)
1580 * - the canvas goes out of scope
1581 */
1582class SkAutoROCanvasPixels : SkNoncopyable {
1583public:
1584 SkAutoROCanvasPixels(SkCanvas* canvas);
1585
1586 // returns NULL on failure
1587 const void* addr() const { return fAddr; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001588
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001589 // undefined if addr() == NULL
1590 size_t rowBytes() const { return fRowBytes; }
skia.committer@gmail.com02d6f542014-02-14 03:02:05 +00001591
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001592 // undefined if addr() == NULL
1593 const SkImageInfo& info() const { return fInfo; }
1594
1595 // helper that, if returns true, installs the pixels into the bitmap. Note
1596 // that the bitmap may reference the address returned by peekPixels(), so
1597 // the caller must respect the restrictions associated with peekPixels().
1598 bool asROBitmap(SkBitmap*) const;
1599
1600private:
1601 SkBitmap fBitmap; // used if peekPixels() fails
1602 const void* fAddr; // NULL on failure
1603 SkImageInfo fInfo;
1604 size_t fRowBytes;
1605};
1606
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001607static inline SkCanvas::SaveFlags operator|(const SkCanvas::SaveFlags lhs,
1608 const SkCanvas::SaveFlags rhs) {
commit-bot@chromium.org92a89162014-05-30 21:07:05 +00001609 return static_cast<SkCanvas::SaveFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001610}
1611
1612static inline SkCanvas::SaveFlags& operator|=(SkCanvas::SaveFlags& lhs,
1613 const SkCanvas::SaveFlags rhs) {
1614 lhs = lhs | rhs;
1615 return lhs;
1616}
1617
fmalitac3b589a2014-06-05 12:40:07 -07001618class SkCanvasClipVisitor {
1619public:
1620 virtual ~SkCanvasClipVisitor();
1621 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
1622 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
1623 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1624};
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001625
reed@android.com8a1c16f2008-12-17 15:59:43 +00001626#endif