blob: 1b4571a09c9c65b9b3fdcfde71431636a1d39736 [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"
14#include "SkPaint.h"
15#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000016#include "SkRegion.h"
reed4a8126e2014-09-22 07:29:03 -070017#include "SkSurfaceProps.h"
reed@android.com845fdac2009-06-23 03:01:32 +000018#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000019
bungemand3ebb482015-08-05 13:57:49 -070020class GrContext;
21class GrRenderTarget;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000022class SkBaseDevice;
reed6a070dc2014-11-11 19:36:09 -080023class SkCanvasClipVisitor;
bungemand3ebb482015-08-05 13:57:49 -070024class SkClipStack;
reedf70b5312016-03-04 16:36:20 -080025class SkData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000026class SkDraw;
reed3cb38402015-02-06 08:36:15 -080027class SkDrawable;
reed@android.com8a1c16f2008-12-17 15:59:43 +000028class SkDrawFilter;
piotaixrb5fae932014-09-24 13:03:30 -070029class SkImage;
bungemand3ebb482015-08-05 13:57:49 -070030class SkImageFilter;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000031class SkMetaData;
bungemand3ebb482015-08-05 13:57:49 -070032class SkPath;
reed@android.com8a1c16f2008-12-17 15:59:43 +000033class SkPicture;
bungemand3ebb482015-08-05 13:57:49 -070034class SkPixmap;
reed@google.com4ed0fb72012-12-12 20:48:18 +000035class SkRRect;
reed71c3c762015-06-24 10:29:17 -070036struct SkRSXform;
reed@google.com76f10a32014-02-05 15:32:21 +000037class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000038class SkSurface_Base;
fmalita00d5c2c2014-08-21 08:53:26 -070039class SkTextBlob;
reedfa35f8e2014-09-04 12:14:36 -070040
reed@android.com8a1c16f2008-12-17 15:59:43 +000041/** \class SkCanvas
42
43 A Canvas encapsulates all of the state about drawing into a device (bitmap).
44 This includes a reference to the device itself, and a stack of matrix/clip
45 values. For any given draw call (e.g. drawRect), the geometry of the object
46 being drawn is transformed by the concatenation of all the matrices in the
47 stack. The transformed geometry is clipped by the intersection of all of
48 the clips in the stack.
49
50 While the Canvas holds the state of the drawing device, the state (style)
51 of the object being drawn is held by the Paint, which is provided as a
52 parameter to each of the draw() methods. The Paint holds attributes such as
53 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
54 etc.
55*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000056class SK_API SkCanvas : public SkRefCnt {
reedbada1882015-12-21 13:09:44 -080057 enum PrivateSaveLayerFlags {
caryclark952538e2016-02-26 05:01:42 -080058 kDontClipToLayer_PrivateSaveLayerFlag = 1U << 31,
reedbada1882015-12-21 13:09:44 -080059 };
60
reed@android.com8a1c16f2008-12-17 15:59:43 +000061public:
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000062 /**
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000063 * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
64 * specified pixels. To access the pixels after drawing to them, the caller should call
65 * flush() or call peekPixels(...).
66 *
67 * On failure, return NULL. This can fail for several reasons:
68 * 1. invalid ImageInfo (e.g. negative dimensions)
69 * 2. unsupported ImageInfo for a canvas
70 * - kUnknown_SkColorType, kIndex_8_SkColorType
reed44977482015-02-27 10:23:00 -080071 * - kUnknown_SkAlphaType
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000072 * - this list is not complete, so others may also be unsupported
73 *
74 * Note: it is valid to request a supported ImageInfo, but with zero
75 * dimensions.
76 */
77 static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t);
78
79 static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
80 return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
81 }
82
83 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000084 * Creates an empty canvas with no backing device/pixels, and zero
85 * dimensions.
86 */
reed@google.comcde92112011-07-06 20:00:52 +000087 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000088
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000089 /**
90 * Creates a canvas of the specified dimensions, but explicitly not backed
91 * by any device/pixels. Typically this use used by subclasses who handle
92 * the draw calls in some other way.
93 */
reed96a857e2015-01-25 10:33:58 -080094 SkCanvas(int width, int height, const SkSurfaceProps* = NULL);
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000095
reed@google.com6dc74552011-07-21 18:00:46 +000096 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +000097
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000098 @param device Specifies a device for the canvas to draw into.
99 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000100 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000101
reed@google.com44699382013-10-31 17:28:30 +0000102 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103 @param bitmap Specifies a bitmap for the canvas to draw into. Its
104 structure are copied to the canvas.
105 */
106 explicit SkCanvas(const SkBitmap& bitmap);
fmalita3d91aad2015-02-02 05:25:04 -0800107
108 /** Construct a canvas with the specified bitmap to draw into.
109 @param bitmap Specifies a bitmap for the canvas to draw into. Its
110 structure are copied to the canvas.
111 @param props New canvas surface properties.
112 */
113 SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
114
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115 virtual ~SkCanvas();
116
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000117 SkMetaData& getMetaData();
118
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000119 /**
120 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
121 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
122 */
123 SkImageInfo imageInfo() const;
124
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 ///////////////////////////////////////////////////////////////////////////
126
reed@google.com210ce002011-11-01 14:24:23 +0000127 /**
bsalomone63ffef2016-02-05 07:17:34 -0800128 * Trigger the immediate execution of all pending draw operations. For the GPU
129 * backend this will resolve all rendering to the GPU surface backing the
130 * SkSurface that owns this canvas.
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000131 */
132 void flush();
133
134 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000135 * Gets the size of the base or root layer in global canvas coordinates. The
136 * origin of the base layer is always (0,0). The current drawable area may be
137 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000138 */
tomhudson68260fa2015-03-23 07:22:40 -0700139 virtual SkISize getBaseLayerSize() const;
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000140
141 /**
142 * DEPRECATED: call getBaseLayerSize
143 */
144 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000145
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000146 /**
147 * DEPRECATED.
148 * Return the canvas' device object, which may be null. The device holds
149 * the bitmap of the pixels that the canvas draws into. The reference count
150 * of the returned device is not changed by this call.
151 */
reed52d9ac62014-06-30 09:05:34 -0700152#ifndef SK_SUPPORT_LEGACY_GETDEVICE
153protected: // Can we make this private?
154#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000155 SkBaseDevice* getDevice() const;
reed52d9ac62014-06-30 09:05:34 -0700156public:
reed41e010c2015-06-09 12:16:53 -0700157 SkBaseDevice* getDevice_just_for_deprecated_compatibility_testing() const {
158 return this->getDevice();
159 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160
reed@google.com9266fed2011-03-30 00:18:03 +0000161 /**
162 * saveLayer() can create another device (which is later drawn onto
163 * the previous device). getTopDevice() returns the top-most device current
164 * installed. Note that this can change on other calls like save/restore,
165 * so do not access this device after subsequent canvas calls.
166 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000167 *
168 * @param updateMatrixClip If this is true, then before the device is
169 * returned, we ensure that its has been notified about the current
170 * matrix and clip. Note: this happens automatically when the device
171 * is drawn to, but is optional here, as there is a small perf hit
172 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000173 */
reed@google.com9c135db2014-03-12 18:28:35 +0000174#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
175private:
176#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000177 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000178public:
reed@google.com9266fed2011-03-30 00:18:03 +0000179
reed@google.com76f10a32014-02-05 15:32:21 +0000180 /**
181 * Create a new surface matching the specified info, one that attempts to
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000182 * be maximally compatible when used with this canvas. If there is no matching Surface type,
183 * NULL is returned.
reed4a8126e2014-09-22 07:29:03 -0700184 *
185 * If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
186 * inherits the properties of the surface that owns this canvas. If this canvas has no parent
187 * surface, then the new surface is created with default properties.
reed@google.com76f10a32014-02-05 15:32:21 +0000188 */
reed4a8126e2014-09-22 07:29:03 -0700189 SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps* = NULL);
bsalomon@google.come97f0852011-06-17 13:10:25 +0000190
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000191 /**
192 * Return the GPU context of the device that is associated with the canvas.
193 * For a canvas with non-GPU device, NULL is returned.
194 */
195 GrContext* getGrContext();
196
reed@google.com4b226022011-01-11 18:32:13 +0000197 ///////////////////////////////////////////////////////////////////////////
198
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000199 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000200 * If the canvas has writable pixels in its top layer (and is not recording to a picture
201 * or other non-raster target) and has direct access to its pixels (i.e. they are in
202 * local RAM) return the address of those pixels, and if not null,
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000203 * return the ImageInfo, rowBytes and origin. The returned address is only valid
reed@google.com9c135db2014-03-12 18:28:35 +0000204 * while the canvas object is in scope and unchanged. Any API calls made on
205 * canvas (or its parent surface if any) will invalidate the
206 * returned address (and associated information).
207 *
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000208 * On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
reed@google.com9c135db2014-03-12 18:28:35 +0000209 */
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000210 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
reed@google.com9c135db2014-03-12 18:28:35 +0000211
212 /**
213 * If the canvas has readable pixels in its base layer (and is not recording to a picture
214 * 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 +0000215 * local RAM) return the const-address of those pixels, and if not null,
216 * return the ImageInfo and rowBytes. The returned address is only valid
217 * while the canvas object is in scope and unchanged. Any API calls made on
218 * canvas (or its parent surface if any) will invalidate the
219 * returned address (and associated information).
220 *
221 * On failure, returns NULL and the info and rowBytes parameters are
222 * ignored.
223 */
224 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
225
reed@google.com4b226022011-01-11 18:32:13 +0000226 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000227 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
228 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
reedb184f7f2014-07-13 04:32:32 -0700229 * starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000230 *
reedb184f7f2014-07-13 04:32:32 -0700231 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000232 *
reedb184f7f2014-07-13 04:32:32 -0700233 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000234 *
reedb184f7f2014-07-13 04:32:32 -0700235 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
236 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
237 * corresponding src pixels, performing any colortype/alphatype transformations needed
238 * (in the case where the src and dst have different colortypes or alphatypes).
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000239 *
240 * This call can fail, returning false, for several reasons:
reedb184f7f2014-07-13 04:32:32 -0700241 * - If srcR does not intersect the base-layer bounds.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000242 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
243 * - If this canvas is not backed by pixels (e.g. picture or PDF)
244 */
reedb184f7f2014-07-13 04:32:32 -0700245 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
246 int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000247
248 /**
249 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
250 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
251 * it calls through to readPixels(info, ...) and returns its result.
252 */
reedb184f7f2014-07-13 04:32:32 -0700253 bool readPixels(SkBitmap* bitmap, int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000254
255 /**
256 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
257 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
258 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
259 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000260 */
261 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000262
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000263 /**
264 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
265 * ignoring the matrix and clip.
266 *
267 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
268 *
269 * target.setXYWH(x, y, info.width(), info.height());
270 *
271 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
272 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
273 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
274 * pixels, performing any colortype/alphatype transformations needed (in the case where the
275 * src and dst have different colortypes or alphatypes).
276 *
277 * This call can fail, returning false, for several reasons:
278 * - If the src colortype/alphatype cannot be converted to the canvas' types
279 * - If this canvas is not backed by pixels (e.g. picture or PDF)
280 */
281 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
282
283 /**
284 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
285 * is just wrapping a texture, returns false and does nothing.
286 */
287 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000288
reed@android.com8a1c16f2008-12-17 15:59:43 +0000289 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000290
reed@android.comdc3381f2010-02-11 16:05:15 +0000291 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000293 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
294 operate on this copy.
295 When the balancing call to restore() is made, the previous matrix, clip,
296 and drawFilter are restored.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000297
298 @return The value to pass to restoreToCount() to balance this save()
299 */
300 int save();
301
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302 /** This behaves the same as save(), but in addition it allocates an
303 offscreen bitmap. All drawing calls are directed there, and only when
304 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000305 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000306 @param bounds (may be null) This rect, if non-null, is used as a hint to
307 limit the size of the offscreen, and thus drawing may be
308 clipped to it, though that clipping is not guaranteed to
309 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000310 @param paint (may be null) This is copied, and is applied to the
311 offscreen when restore() is called
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000312 @return The value to pass to restoreToCount() to balance this save()
313 */
314 int saveLayer(const SkRect* bounds, const SkPaint* paint);
reed021f6312015-08-09 19:41:13 -0700315 int saveLayer(const SkRect& bounds, const SkPaint* paint) {
316 return this->saveLayer(&bounds, paint);
317 }
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000318
reed70ee31b2015-12-10 13:44:45 -0800319 /**
320 * Temporary name.
321 * Will allow any requests for LCD text to be respected, so the caller must be careful to
322 * only draw on top of opaque sections of the layer to get good results.
323 */
324 int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
325
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 /** This behaves the same as save(), but in addition it allocates an
327 offscreen bitmap. All drawing calls are directed there, and only when
328 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000329 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000330 @param bounds (may be null) This rect, if non-null, is used as a hint to
331 limit the size of the offscreen, and thus drawing may be
332 clipped to it, though that clipping is not guaranteed to
333 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000334 @param alpha This is applied to the offscreen when restore() is called.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000335 @return The value to pass to restoreToCount() to balance this save()
336 */
337 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
338
reed4960eee2015-12-18 07:09:18 -0800339 enum {
340 kIsOpaque_SaveLayerFlag = 1 << 0,
341 kPreserveLCDText_SaveLayerFlag = 1 << 1,
reedbada1882015-12-21 13:09:44 -0800342
343#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
344 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
345#endif
reed4960eee2015-12-18 07:09:18 -0800346 };
347 typedef uint32_t SaveLayerFlags;
348
349 struct SaveLayerRec {
reedbfd5f172016-01-07 11:28:08 -0800350 SaveLayerRec()
351 : fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
352 {}
reed4960eee2015-12-18 07:09:18 -0800353 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
354 : fBounds(bounds)
355 , fPaint(paint)
reedbfd5f172016-01-07 11:28:08 -0800356 , fBackdrop(nullptr)
357 , fSaveLayerFlags(saveLayerFlags)
358 {}
359 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
360 SaveLayerFlags saveLayerFlags)
361 : fBounds(bounds)
362 , fPaint(paint)
363 , fBackdrop(backdrop)
reed4960eee2015-12-18 07:09:18 -0800364 , fSaveLayerFlags(saveLayerFlags)
365 {}
366
reedbfd5f172016-01-07 11:28:08 -0800367 const SkRect* fBounds; // optional
368 const SkPaint* fPaint; // optional
369 const SkImageFilter* fBackdrop; // optional
370 SaveLayerFlags fSaveLayerFlags;
reed4960eee2015-12-18 07:09:18 -0800371 };
372
373 int saveLayer(const SaveLayerRec&);
374
reed@android.com8a1c16f2008-12-17 15:59:43 +0000375 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000376 modifications to the matrix/clip/drawFilter state since the last save
377 call.
378 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000379 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000380 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000381
382 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000383 This will equal # save() calls - # restore() calls + 1. The save count on
384 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000385 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000386 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000387
388 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000389 count reached saveCount. It is an error for saveCount to be greater than
390 getSaveCount(). To pop all the way back to the initial matrix/clip context
391 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 @param saveCount The number of save() levels to restore from
393 */
394 void restoreToCount(int saveCount);
395
396 /** Preconcat the current matrix with the specified translation
397 @param dx The distance to translate in X
398 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000399 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000400 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401
402 /** Preconcat the current matrix with the specified scale.
403 @param sx The amount to scale in X
404 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000406 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000407
408 /** Preconcat the current matrix with the specified rotation.
409 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000410 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000411 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000412
413 /** Preconcat the current matrix with the specified skew.
414 @param sx The amount to skew in X
415 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000416 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000417 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418
419 /** Preconcat the current matrix with the specified matrix.
420 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000422 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000423
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424 /** Replace the current matrix with a copy of the specified matrix.
425 @param matrix The matrix that will be copied into the current matrix.
426 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000427 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000428
reed@android.com8a1c16f2008-12-17 15:59:43 +0000429 /** Helper for setMatrix(identity). Sets the current matrix to identity.
430 */
431 void resetMatrix();
432
reed@google.com4ed0fb72012-12-12 20:48:18 +0000433 /**
434 * Modify the current clip with the specified rectangle.
435 * @param rect The rect to combine with the current clip
436 * @param op The region op to apply to the current clip
437 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000438 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000439 void clipRect(const SkRect& rect,
440 SkRegion::Op op = SkRegion::kIntersect_Op,
441 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000442
reed@google.com4ed0fb72012-12-12 20:48:18 +0000443 /**
444 * Modify the current clip with the specified SkRRect.
445 * @param rrect The rrect to combine with the current clip
446 * @param op The region op to apply to the current clip
447 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000448 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000449 void clipRRect(const SkRRect& rrect,
450 SkRegion::Op op = SkRegion::kIntersect_Op,
451 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000452
453 /**
454 * Modify the current clip with the specified path.
455 * @param path The path to combine with the current clip
456 * @param op The region op to apply to the current clip
457 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000458 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000459 void clipPath(const SkPath& path,
460 SkRegion::Op op = SkRegion::kIntersect_Op,
461 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000462
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000463 /** EXPERIMENTAL -- only used for testing
464 Set to false to force clips to be hard, even if doAntiAlias=true is
465 passed to clipRect or clipPath.
466 */
467 void setAllowSoftClip(bool allow) {
468 fAllowSoftClip = allow;
469 }
470
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000471 /** EXPERIMENTAL -- only used for testing
472 Set to simplify clip stack using path ops.
473 */
474 void setAllowSimplifyClip(bool allow) {
475 fAllowSimplifyClip = allow;
476 }
477
reed@android.com8a1c16f2008-12-17 15:59:43 +0000478 /** Modify the current clip with the specified region. Note that unlike
479 clipRect() and clipPath() which transform their arguments by the current
480 matrix, clipRegion() assumes its argument is already in device
481 coordinates, and so no transformation is performed.
482 @param deviceRgn The region to apply to the current clip
483 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000484 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000485 void clipRegion(const SkRegion& deviceRgn,
486 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487
488 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
489 specified region. This does not intersect or in any other way account
490 for the existing clip region.
491 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000492 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000493 void setClipRegion(const SkRegion& deviceRgn) {
494 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000495 }
496
reed@android.com8a1c16f2008-12-17 15:59:43 +0000497 /** Return true if the specified rectangle, after being transformed by the
498 current matrix, would lie completely outside of the current clip. Call
499 this to check if an area you intend to draw into is clipped out (and
500 therefore you can skip making the draw calls).
501 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000502 @return true if the rect (transformed by the canvas' matrix) does not
503 intersect with the canvas' clip
504 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000505 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000506
507 /** Return true if the specified path, after being transformed by the
508 current matrix, would lie completely outside of the current clip. Call
509 this to check if an area you intend to draw into is clipped out (and
510 therefore you can skip making the draw calls). Note, for speed it may
511 return false even if the path itself might not intersect the clip
512 (i.e. the bounds of the path intersects, but the path does not).
513 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000514 @return true if the path (transformed by the canvas' matrix) does not
515 intersect with the canvas' clip
516 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000517 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000518
519 /** Return true if the horizontal band specified by top and bottom is
520 completely clipped out. This is a conservative calculation, meaning
521 that it is possible that if the method returns false, the band may still
522 in fact be clipped out, but the converse is not true. If this method
523 returns true, then the band is guaranteed to be clipped out.
524 @param top The top of the horizontal band to compare with the clip
525 @param bottom The bottom of the horizontal and to compare with the clip
526 @return true if the horizontal band is completely clipped out (i.e. does
527 not intersect the current clip)
528 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000529 bool quickRejectY(SkScalar top, SkScalar bottom) const {
reed@google.comc0784db2013-12-13 21:16:12 +0000530 SkASSERT(top <= bottom);
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000531
532#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
533 // TODO: add a hasPerspective method similar to getLocalClipBounds. This
534 // would cache the SkMatrix::hasPerspective result. Alternatively, have
535 // the MC stack just set a hasPerspective boolean as it is updated.
536 if (this->getTotalMatrix().hasPerspective()) {
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000537 // TODO: consider implementing some half-plane test between the
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000538 // two Y planes and the device-bounds (i.e., project the top and
539 // bottom Y planes and then determine if the clip bounds is completely
540 // outside either one).
541 return false;
542 }
543#endif
544
reed@google.comc0784db2013-12-13 21:16:12 +0000545 const SkRect& clipR = this->getLocalClipBounds();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000546 // In the case where the clip is empty and we are provided with a
547 // negative top and positive bottom parameter then this test will return
548 // false even though it will be clipped. We have chosen to exclude that
549 // check as it is rare and would result double the comparisons.
reed@google.comc0784db2013-12-13 21:16:12 +0000550 return top >= clipR.fBottom || bottom <= clipR.fTop;
djsollen@google.com92d2a292012-02-27 16:17:59 +0000551 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000552
553 /** Return the bounds of the current clip (in local coordinates) in the
554 bounds parameter, and return true if it is non-empty. This can be useful
555 in a way similar to quickReject, in that it tells you that drawing
556 outside of these bounds will be clipped out.
557 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000558 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000559
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000560 /** Return the bounds of the current clip, in device coordinates; returns
561 true if non-empty. Maybe faster than getting the clip explicitly and
562 then taking its bounds.
563 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000564 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000565
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000566
reed@android.com8a1c16f2008-12-17 15:59:43 +0000567 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000568 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000569 @param a the alpha component (0..255) of the color to fill the canvas
570 @param r the red component (0..255) of the color to fill the canvas
571 @param g the green component (0..255) of the color to fill the canvas
572 @param b the blue component (0..255) of the color to fill the canvas
573 @param mode the mode to apply the color in (defaults to SrcOver)
574 */
575 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000576 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000577
578 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000579 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000580 @param color the color to draw with
581 @param mode the mode to apply the color in (defaults to SrcOver)
582 */
reed8eddfb52014-12-04 07:50:14 -0800583 void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000584
reedf4e0d9e2014-12-05 20:49:03 -0800585 /**
586 * Helper method for drawing a color in SRC mode, completely replacing all the pixels
587 * in the current clip with this color.
588 */
589 void clear(SkColor color) {
reed8eddfb52014-12-04 07:50:14 -0800590 this->drawColor(color, SkXfermode::kSrc_Mode);
591 }
reed@google.com2a981812011-04-14 18:59:28 +0000592
593 /**
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000594 * This makes the contents of the canvas undefined. Subsequent calls that
595 * require reading the canvas contents will produce undefined results. Examples
596 * include blending and readPixels. The actual implementation is backend-
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800597 * dependent and one legal implementation is to do nothing. This method
598 * ignores the current clip.
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000599 *
600 * This function should only be called if the caller intends to subsequently
601 * draw to the canvas. The canvas may do real work at discard() time in order
602 * to optimize performance on subsequent draws. Thus, if you call this and then
603 * never draw to the canvas subsequently you may pay a perfomance penalty.
604 */
605 void discard() { this->onDiscard(); }
606
607 /**
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800608 * Fill the entire canvas (restricted to the current clip) with the
reed@google.com2a981812011-04-14 18:59:28 +0000609 * specified paint.
610 * @param paint The paint used to fill the canvas
611 */
reed0846f1b2015-01-09 14:17:40 -0800612 void drawPaint(const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000613
614 enum PointMode {
615 /** drawPoints draws each point separately */
616 kPoints_PointMode,
617 /** drawPoints draws each pair of points as a line segment */
618 kLines_PointMode,
619 /** drawPoints draws the array of points as a polygon */
620 kPolygon_PointMode
621 };
622
623 /** Draw a series of points, interpreted based on the PointMode mode. For
624 all modes, the count parameter is interpreted as the total number of
625 points. For kLine mode, count/2 line segments are drawn.
626 For kPoint mode, each point is drawn centered at its coordinate, and its
627 size is specified by the paint's stroke-width. It draws as a square,
628 unless the paint's cap-type is round, in which the points are drawn as
629 circles.
630 For kLine mode, each pair of points is drawn as a line segment,
631 respecting the paint's settings for cap/join/width.
632 For kPolygon mode, the entire array is drawn as a series of connected
633 line segments.
634 Note that, while similar, kLine and kPolygon modes draw slightly
635 differently than the equivalent path built with a series of moveto,
636 lineto calls, in that the path will draw all of its contours at once,
637 with no interactions if contours intersect each other (think XOR
638 xfermode). drawPoints always draws each element one at a time.
639 @param mode PointMode specifying how to draw the array of points.
640 @param count The number of points in the array
641 @param pts Array of points to draw
642 @param paint The paint used to draw the points
643 */
reed0846f1b2015-01-09 14:17:40 -0800644 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000645
646 /** Helper method for drawing a single point. See drawPoints() for a more
647 details.
648 */
649 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000650
reed@android.com8a1c16f2008-12-17 15:59:43 +0000651 /** Draws a single pixel in the specified color.
652 @param x The X coordinate of which pixel to draw
653 @param y The Y coordiante of which pixel to draw
654 @param color The color to draw
655 */
656 void drawPoint(SkScalar x, SkScalar y, SkColor color);
657
658 /** Draw a line segment with the specified start and stop x,y coordinates,
659 using the specified paint. NOTE: since a line is always "framed", the
660 paint's Style is ignored.
661 @param x0 The x-coordinate of the start point of the line
662 @param y0 The y-coordinate of the start point of the line
663 @param x1 The x-coordinate of the end point of the line
664 @param y1 The y-coordinate of the end point of the line
665 @param paint The paint used to draw the line
666 */
667 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
668 const SkPaint& paint);
669
670 /** Draw the specified rectangle using the specified paint. The rectangle
671 will be filled or stroked based on the Style in the paint.
672 @param rect The rect to be drawn
673 @param paint The paint used to draw the rect
674 */
reed0846f1b2015-01-09 14:17:40 -0800675 void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000676
677 /** Draw the specified rectangle using the specified paint. The rectangle
678 will be filled or framed based on the Style in the paint.
679 @param rect The rect to be drawn
680 @param paint The paint used to draw the rect
681 */
reed@google.com87001ed2014-02-17 16:28:05 +0000682 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000683 SkRect r;
684 r.set(rect); // promotes the ints to scalars
685 this->drawRect(r, paint);
686 }
reed@google.com4b226022011-01-11 18:32:13 +0000687
reed@android.com8a1c16f2008-12-17 15:59:43 +0000688 /** Draw the specified rectangle using the specified paint. The rectangle
689 will be filled or framed based on the Style in the paint.
690 @param left The left side of the rectangle to be drawn
691 @param top The top side of the rectangle to be drawn
692 @param right The right side of the rectangle to be drawn
693 @param bottom The bottom side of the rectangle to be drawn
694 @param paint The paint used to draw the rect
695 */
696 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
697 SkScalar bottom, const SkPaint& paint);
698
699 /** Draw the specified oval using the specified paint. The oval will be
700 filled or framed based on the Style in the paint.
701 @param oval The rectangle bounds of the oval to be drawn
702 @param paint The paint used to draw the oval
703 */
reed0846f1b2015-01-09 14:17:40 -0800704 void drawOval(const SkRect& oval, const SkPaint&);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000705
706 /**
707 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
708 * based on the Style in the paint.
709 *
710 * @param rrect The round-rect to draw
711 * @param paint The paint used to draw the round-rect
712 */
reed0846f1b2015-01-09 14:17:40 -0800713 void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000714
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000715 /**
716 * Draw the annulus formed by the outer and inner rrects. The results
717 * are undefined if the outer does not contain the inner.
718 */
719 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
720
reed@android.com8a1c16f2008-12-17 15:59:43 +0000721 /** Draw the specified circle using the specified paint. If radius is <= 0,
722 then nothing will be drawn. The circle will be filled
723 or framed based on the Style in the paint.
724 @param cx The x-coordinate of the center of the cirle to be drawn
725 @param cy The y-coordinate of the center of the cirle to be drawn
726 @param radius The radius of the cirle to be drawn
727 @param paint The paint used to draw the circle
728 */
729 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
730 const SkPaint& paint);
731
732 /** Draw the specified arc, which will be scaled to fit inside the
733 specified oval. If the sweep angle is >= 360, then the oval is drawn
734 completely. Note that this differs slightly from SkPath::arcTo, which
735 treats the sweep angle mod 360.
736 @param oval The bounds of oval used to define the shape of the arc
737 @param startAngle Starting angle (in degrees) where the arc begins
738 @param sweepAngle Sweep angle (in degrees) measured clockwise
739 @param useCenter true means include the center of the oval. For filling
740 this will draw a wedge. False means just use the arc.
741 @param paint The paint used to draw the arc
742 */
743 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
744 bool useCenter, const SkPaint& paint);
745
746 /** Draw the specified round-rect using the specified paint. The round-rect
747 will be filled or framed based on the Style in the paint.
748 @param rect The rectangular bounds of the roundRect to be drawn
749 @param rx The x-radius of the oval used to round the corners
750 @param ry The y-radius of the oval used to round the corners
751 @param paint The paint used to draw the roundRect
752 */
753 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
754 const SkPaint& paint);
755
756 /** Draw the specified path using the specified paint. The path will be
757 filled or framed based on the Style in the paint.
758 @param path The path to be drawn
759 @param paint The paint used to draw the path
760 */
reed0846f1b2015-01-09 14:17:40 -0800761 void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000762
piotaixrd52893c2014-09-25 14:39:40 -0700763 /** Draw the specified image, with its top/left corner at (x,y), using the
764 specified paint, transformed by the current matrix.
765
766 @param image The image to be drawn
767 @param left The position of the left side of the image being drawn
768 @param top The position of the top side of the image being drawn
769 @param paint The paint used to draw the image, or NULL
770 */
reed0846f1b2015-01-09 14:17:40 -0800771 void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
piotaixrb5fae932014-09-24 13:03:30 -0700772
reeda5517e22015-07-14 10:54:12 -0700773 /**
774 * Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
775 * trading off speed for exactness.
776 *
777 * When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
778 * the pixels in the image. If there is a src-rect specified, it is intended to restrict the
779 * pixels that will be read. However, for performance reasons, some implementations may slow
780 * down if they cannot read 1-pixel past the src-rect boundary at times.
781 *
782 * This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
783 * If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
784 * must be strictly respected, the caller should pass kStrict.
785 */
786 enum SrcRectConstraint {
787 /**
788 * If kStrict is specified, the implementation must respect the src-rect
789 * (if specified) strictly, and will never sample outside of those bounds during sampling
790 * even when filtering. This may be slower than kFast.
791 */
792 kStrict_SrcRectConstraint,
793
794 /**
795 * If kFast is specified, the implementation may sample outside of the src-rect
bsalomon19e82e32015-10-23 09:27:42 -0700796 * (if specified) by half the width of filter. This allows greater flexibility
reeda5517e22015-07-14 10:54:12 -0700797 * to the implementation and can make the draw much faster.
798 */
799 kFast_SrcRectConstraint,
800 };
801
802 /** Draw the specified image, scaling and translating so that it fills the specified
803 * dst rect. If the src rect is non-null, only that subset of the image is transformed
804 * and drawn.
805 *
806 * @param image The image to be drawn
807 * @param src Optional: specify the subset of the image to be drawn
808 * @param dst The destination rectangle where the scaled/translated
809 * image will be drawn
810 * @param paint The paint used to draw the image, or NULL
811 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
812 */
reede47829b2015-08-06 10:02:53 -0700813 void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
814 const SkPaint* paint,
815 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
816 // variant that takes src SkIRect
817 void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
818 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
819 // variant that assumes src == image-bounds
reede47829b2015-08-06 10:02:53 -0700820 void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
821 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700822
reed4c21dc52015-06-25 12:32:03 -0700823 /**
824 * Draw the image stretched differentially to fit into dst.
825 * center is a rect within the image, and logically divides the image
826 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
827 * image is the "center", then the center-rect should be [2, 2, 3, 3].
828 *
829 * If the dst is >= the image size, then...
830 * - The 4 corners are not stretched at all.
831 * - The sides are stretched in only one axis.
832 * - The center is stretched in both axes.
833 * Else, for each axis where dst < image,
834 * - The corners shrink proportionally
835 * - The sides (along the shrink axis) and center are not drawn
836 */
837 void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
838 const SkPaint* paint = NULL);
839
reed@android.com8a1c16f2008-12-17 15:59:43 +0000840 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
841 specified paint, transformed by the current matrix. Note: if the paint
842 contains a maskfilter that generates a mask which extends beyond the
843 bitmap's original width/height, then the bitmap will be drawn as if it
844 were in a Shader with CLAMP mode. Thus the color outside of the original
845 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000846
847 If a shader is present on the paint it will be ignored, except in the
reed@google.comf20fc242014-03-26 13:44:58 +0000848 case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000849 generated by the shader.
850
reed@android.com8a1c16f2008-12-17 15:59:43 +0000851 @param bitmap The bitmap to be drawn
852 @param left The position of the left side of the bitmap being drawn
853 @param top The position of the top side of the bitmap being drawn
854 @param paint The paint used to draw the bitmap, or NULL
855 */
reed0846f1b2015-01-09 14:17:40 -0800856 void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
857 const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000858
reeda5517e22015-07-14 10:54:12 -0700859 /** Draw the specified bitmap, scaling and translating so that it fills the specified
860 * dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
861 * and drawn.
862 *
863 * @param bitmap The bitmap to be drawn
864 * @param src Optional: specify the subset of the bitmap to be drawn
865 * @param dst The destination rectangle where the scaled/translated
866 * bitmap will be drawn
867 * @param paint The paint used to draw the bitmap, or NULL
868 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
869 */
reede47829b2015-08-06 10:02:53 -0700870 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
reed84984ef2015-07-17 07:09:43 -0700871 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700872 // variant where src is SkIRect
reed84984ef2015-07-17 07:09:43 -0700873 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
874 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700875 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
bsalomon19e82e32015-10-23 09:27:42 -0700876 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700877
reed@google.comf0b5e112011-09-07 11:57:34 +0000878 /**
879 * Draw the bitmap stretched differentially to fit into dst.
880 * center is a rect within the bitmap, and logically divides the bitmap
881 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
882 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
883 *
884 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000885 * - The 4 corners are not stretched at all.
886 * - The sides are stretched in only one axis.
887 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000888 * Else, for each axis where dst < bitmap,
889 * - The corners shrink proportionally
890 * - The sides (along the shrink axis) and center are not drawn
891 */
reed0846f1b2015-01-09 14:17:40 -0800892 void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
893 const SkPaint* paint = NULL);
reed@google.comf0b5e112011-09-07 11:57:34 +0000894
reed@android.com8a1c16f2008-12-17 15:59:43 +0000895 /** Draw the text, with origin at (x,y), using the specified paint.
896 The origin is interpreted based on the Align setting in the paint.
897 @param text The text to be drawn
898 @param byteLength The number of bytes to read from the text parameter
899 @param x The x-coordinate of the origin of the text being drawn
900 @param y The y-coordinate of the origin of the text being drawn
901 @param paint The paint used for the text (e.g. color, size, style)
902 */
reedf7430cc2014-12-21 11:38:35 -0800903 void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
904 const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000905
906 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000907 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000908 @param text The text to be drawn
909 @param byteLength The number of bytes to read from the text parameter
910 @param pos Array of positions, used to position each character
911 @param paint The paint used for the text (e.g. color, size, style)
912 */
reedf7430cc2014-12-21 11:38:35 -0800913 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
914 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000915
reed@android.com8a1c16f2008-12-17 15:59:43 +0000916 /** Draw the text, with each character/glyph origin specified by the x
917 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000918 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000919 @param text The text to be drawn
920 @param byteLength The number of bytes to read from the text parameter
921 @param xpos Array of x-positions, used to position each character
922 @param constY The shared Y coordinate for all of the positions
923 @param paint The paint used for the text (e.g. color, size, style)
924 */
reedf7430cc2014-12-21 11:38:35 -0800925 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
926 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000927
reed@android.com8a1c16f2008-12-17 15:59:43 +0000928 /** Draw the text, with origin at (x,y), using the specified paint, along
929 the specified path. The paint's Align setting determins where along the
930 path to start the text.
931 @param text The text to be drawn
932 @param byteLength The number of bytes to read from the text parameter
933 @param path The path the text should follow for its baseline
934 @param hOffset The distance along the path to add to the text's
935 starting position
936 @param vOffset The distance above(-) or below(+) the path to
937 position the text
938 @param paint The paint used for the text
939 */
reedf7430cc2014-12-21 11:38:35 -0800940 void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000941 SkScalar vOffset, const SkPaint& paint);
942
943 /** Draw the text, with origin at (x,y), using the specified paint, along
944 the specified path. The paint's Align setting determins where along the
945 path to start the text.
946 @param text The text to be drawn
947 @param byteLength The number of bytes to read from the text parameter
948 @param path The path the text should follow for its baseline
949 @param matrix (may be null) Applied to the text before it is
950 mapped onto the path
951 @param paint The paint used for the text
952 */
reedf7430cc2014-12-21 11:38:35 -0800953 void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
954 const SkMatrix* matrix, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000955
fmalita00d5c2c2014-08-21 08:53:26 -0700956 /** Draw the text blob, offset by (x,y), using the specified paint.
957 @param blob The text blob to be drawn
958 @param x The x-offset of the text being drawn
959 @param y The y-offset of the text being drawn
960 @param paint The paint used for the text (e.g. color, size, style)
961 */
962 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
963
reed@android.com8a1c16f2008-12-17 15:59:43 +0000964 /** Draw the picture into this canvas. This method effective brackets the
965 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +0000966 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000967 @param picture The recorded drawing commands to playback into this
968 canvas.
969 */
reed1c2c4412015-04-30 13:09:24 -0700970 void drawPicture(const SkPicture* picture) {
971 this->drawPicture(picture, NULL, NULL);
972 }
robertphillips9b14f262014-06-04 05:40:44 -0700973
reedd5fa1a42014-08-09 11:08:05 -0700974 /**
975 * Draw the picture into this canvas.
976 *
977 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
978 * logically equivalent to
979 * save/concat/drawPicture/restore
980 *
981 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
982 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
983 * This is logically equivalent to
984 * saveLayer(paint)/drawPicture/restore
985 */
986 void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
987
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988 enum VertexMode {
989 kTriangles_VertexMode,
990 kTriangleStrip_VertexMode,
991 kTriangleFan_VertexMode
992 };
reed@google.com4b226022011-01-11 18:32:13 +0000993
reed@android.com8a1c16f2008-12-17 15:59:43 +0000994 /** Draw the array of vertices, interpreted as triangles (based on mode).
commit-bot@chromium.org559a8832014-05-30 10:08:22 +0000995
996 If both textures and vertex-colors are NULL, it strokes hairlines with
997 the paint's color. This behavior is a useful debugging mode to visualize
998 the mesh.
999
reed@android.com8a1c16f2008-12-17 15:59:43 +00001000 @param vmode How to interpret the array of vertices
1001 @param vertexCount The number of points in the vertices array (and
1002 corresponding texs and colors arrays if non-null)
1003 @param vertices Array of vertices for the mesh
1004 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +00001005 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001006 @param colors May be null. If not null, specifies a color for each
1007 vertex, to be interpolated across the triangle.
1008 @param xmode Used if both texs and colors are present. In this
1009 case the colors are combined with the texture using mode,
1010 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +00001011 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001012 @param indices If not null, array of indices to reference into the
1013 vertex (texs, colors) array.
1014 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001015 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001016 */
reed0846f1b2015-01-09 14:17:40 -08001017 void drawVertices(VertexMode vmode, int vertexCount,
1018 const SkPoint vertices[], const SkPoint texs[],
1019 const SkColor colors[], SkXfermode* xmode,
1020 const uint16_t indices[], int indexCount,
1021 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001022
dandovb3c9d1c2014-08-12 08:34:29 -07001023 /**
1024 Draw a cubic coons patch
mtklein6cfa73a2014-08-13 13:33:49 -07001025
dandovb3c9d1c2014-08-12 08:34:29 -07001026 @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1027 starting at the top left corner.
1028 @param colors specifies the colors for the corners which will be bilerp across the patch,
1029 their order is clockwise starting at the top left corner.
mtklein6cfa73a2014-08-13 13:33:49 -07001030 @param texCoords specifies the texture coordinates that will be bilerp across the patch,
dandovb3c9d1c2014-08-12 08:34:29 -07001031 their order is the same as the colors.
mtklein6cfa73a2014-08-13 13:33:49 -07001032 @param xmode specifies how are the colors and the textures combined if both of them are
dandovb3c9d1c2014-08-12 08:34:29 -07001033 present.
dandov963137b2014-08-07 07:49:53 -07001034 @param paint Specifies the shader/texture if present.
1035 */
dandovb3c9d1c2014-08-12 08:34:29 -07001036 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1037 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001038
reed3cb38402015-02-06 08:36:15 -08001039 /**
reed71c3c762015-06-24 10:29:17 -07001040 * Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
1041 * coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
1042 * into a quad.
1043 *
1044 * xform maps [0, 0, tex.width, tex.height] -> quad
1045 *
1046 * The color array is optional. When specified, each color modulates the pixels in its
1047 * corresponding quad (via the specified SkXfermode::Mode).
1048 *
1049 * The cullRect is optional. When specified, it must be a conservative bounds of all of the
1050 * resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
1051 * intersect the current clip.
1052 *
1053 * The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
1054 * and xfermode are used to affect each of the quads.
1055 */
1056 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1057 const SkColor colors[], int count, SkXfermode::Mode, const SkRect* cullRect,
1058 const SkPaint* paint);
1059
1060 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
1061 const SkRect* cullRect, const SkPaint* paint) {
1062 this->drawAtlas(atlas, xform, tex, NULL, count, SkXfermode::kDst_Mode, cullRect, paint);
1063 }
1064
1065 /**
reed3cb38402015-02-06 08:36:15 -08001066 * Draw the contents of this drawable into the canvas. If the canvas is async
1067 * (e.g. it is recording into a picture) then the drawable will be referenced instead,
1068 * to have its draw() method called when the picture is finalized.
1069 *
1070 * If the intent is to force the contents of the drawable into this canvas immediately,
1071 * then drawable->draw(canvas) may be called.
1072 */
reeda8db7282015-07-07 10:22:31 -07001073 void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL);
1074 void drawDrawable(SkDrawable*, SkScalar x, SkScalar y);
reed6a070dc2014-11-11 19:36:09 -08001075
reedf70b5312016-03-04 16:36:20 -08001076 /**
1077 * Send an "annotation" to the canvas. The annotation is a key/value pair, where the key is
1078 * a null-terminated utf8 string, and the value is a blob of data stored in an SkData
1079 * (which may be null). The annotation is associated with the specified rectangle.
1080 *
1081 * The caller still retains its ownership of the data (if any).
1082 *
1083 * Note: on may canvas types, this information is ignored, but some canvases (e.g. recording
1084 * a picture or drawing to a PDF document) will pass on this information.
1085 */
1086 void drawAnnotation(const SkRect&, const char key[], SkData* value);
1087
reed@android.com8a1c16f2008-12-17 15:59:43 +00001088 //////////////////////////////////////////////////////////////////////////
fmalita77650002016-01-21 18:47:11 -08001089#ifdef SK_INTERNAL
fmalita53d9f1c2016-01-25 06:23:54 -08001090#ifndef SK_SUPPORT_LEGACY_DRAWFILTER
1091 #define SK_SUPPORT_LEGACY_DRAWFILTER
fmalita77650002016-01-21 18:47:11 -08001092#endif
1093#endif
reed@google.com4b226022011-01-11 18:32:13 +00001094
fmalita53d9f1c2016-01-25 06:23:54 -08001095#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
reed@android.com8a1c16f2008-12-17 15:59:43 +00001096 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001097 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001098 @return the canvas' filter (or NULL).
1099 */
fmalita77650002016-01-21 18:47:11 -08001100 SK_ATTR_EXTERNALLY_DEPRECATED("getDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001101 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001102
reed@android.com8a1c16f2008-12-17 15:59:43 +00001103 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1104 As a convenience, the parameter is returned. If an existing filter
1105 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001106 refcnt is incremented. The filter is saved/restored, just like the
1107 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001108 @param filter the new filter (or NULL)
1109 @return the new filter
1110 */
fmalita77650002016-01-21 18:47:11 -08001111 SK_ATTR_EXTERNALLY_DEPRECATED("setDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001112 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
fmalita77650002016-01-21 18:47:11 -08001113#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001114 //////////////////////////////////////////////////////////////////////////
1115
reed@google.com754de5f2014-02-24 19:38:20 +00001116 /**
1117 * Return true if the current clip is empty (i.e. nothing will draw).
1118 * Note: this is not always a free call, so it should not be used
1119 * more often than necessary. However, once the canvas has computed this
1120 * result, subsequent calls will be cheap (until the clip state changes,
1121 * which can happen on any clip..() or restore() call.
1122 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001123 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001124
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001125 /**
1126 * Returns true if the current clip is just a (non-empty) rectangle.
1127 * Returns false if the clip is empty, or if it is complex.
1128 */
1129 virtual bool isClipRect() const;
1130
reed@android.com8a1c16f2008-12-17 15:59:43 +00001131 /** Return the current matrix on the canvas.
1132 This does not account for the translate in any of the devices.
1133 @return The current matrix on the canvas.
1134 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001135 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001136
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001137 /** Return the clip stack. The clip stack stores all the individual
1138 * clips organized by the save/restore frame in which they were
1139 * added.
1140 * @return the current clip stack ("list" of individual clip elements)
1141 */
1142 const SkClipStack* getClipStack() const {
reed687fa1c2015-04-07 08:00:56 -07001143 return fClipStack;
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001144 }
1145
fmalitac3b589a2014-06-05 12:40:07 -07001146 typedef SkCanvasClipVisitor ClipVisitor;
reed@google.com90c07ea2012-04-13 13:50:27 +00001147 /**
1148 * Replays the clip operations, back to front, that have been applied to
1149 * the canvas, calling the appropriate method on the visitor for each
1150 * clip. All clips have already been transformed into device space.
1151 */
1152 void replayClips(ClipVisitor*) const;
1153
reed@android.com8a1c16f2008-12-17 15:59:43 +00001154 ///////////////////////////////////////////////////////////////////////////
1155
1156 /** After calling saveLayer(), there can be any number of devices that make
1157 up the top-most drawing area. LayerIter can be used to iterate through
1158 those devices. Note that the iterator is only valid until the next API
1159 call made on the canvas. Ownership of all pointers in the iterator stays
1160 with the canvas, so none of them should be modified or deleted.
1161 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +00001162 class SK_API LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001163 public:
1164 /** Initialize iterator with canvas, and set values for 1st device */
1165 LayerIter(SkCanvas*, bool skipEmptyClips);
1166 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +00001167
reed@android.com8a1c16f2008-12-17 15:59:43 +00001168 /** Return true if the iterator is done */
1169 bool done() const { return fDone; }
1170 /** Cycle to the next device */
1171 void next();
reed@google.com4b226022011-01-11 18:32:13 +00001172
reed@android.com8a1c16f2008-12-17 15:59:43 +00001173 // These reflect the current device in the iterator
1174
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001175 SkBaseDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001176 const SkMatrix& matrix() const;
1177 const SkRegion& clip() const;
1178 const SkPaint& paint() const;
1179 int x() const;
1180 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001181
reed@android.com8a1c16f2008-12-17 15:59:43 +00001182 private:
1183 // used to embed the SkDrawIter object directly in our instance, w/o
1184 // having to expose that class def to the public. There is an assert
1185 // in our constructor to ensure that fStorage is large enough
1186 // (though needs to be a compile-time-assert!). We use intptr_t to work
1187 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001188 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001189 class SkDrawIter* fImpl; // this points at fStorage
1190 SkPaint fDefaultPaint;
1191 bool fDone;
1192 };
1193
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001194 // don't call
reed@google.com9c135db2014-03-12 18:28:35 +00001195 GrRenderTarget* internal_private_accessTopLayerRenderTarget();
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001196
reedd990e2f2014-12-22 11:58:30 -08001197 // don't call
1198 static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1199 static bool Internal_Private_GetIgnoreSaveLayerBounds();
reed0acf1b42014-12-22 16:12:38 -08001200 static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1201 static bool Internal_Private_GetTreatSpriteAsBitmap();
reedd990e2f2014-12-22 11:58:30 -08001202
reede47829b2015-08-06 10:02:53 -07001203 // TEMP helpers until we switch virtual over to const& for src-rect
1204 void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1205 const SkPaint* paint,
1206 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1207 void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1208 const SkPaint* paint,
1209 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1210
reed@android.com8a1c16f2008-12-17 15:59:43 +00001211protected:
reed@google.com76f10a32014-02-05 15:32:21 +00001212 // default impl defers to getDevice()->newSurface(info)
reed4a8126e2014-09-22 07:29:03 -07001213 virtual SkSurface* onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
reed@google.com76f10a32014-02-05 15:32:21 +00001214
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001215 // default impl defers to its device
reed884e97c2015-05-26 11:31:54 -07001216 virtual bool onPeekPixels(SkPixmap*);
1217 virtual bool onAccessTopLayerPixels(SkPixmap*);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001218
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001219 // Subclass save/restore notifiers.
1220 // Overriders should call the corresponding INHERITED method up the inheritance chain.
reed4960eee2015-12-18 07:09:18 -08001221 // getSaveLayerStrategy()'s return value may suppress full layer allocation.
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001222 enum SaveLayerStrategy {
1223 kFullLayer_SaveLayerStrategy,
reed4960eee2015-12-18 07:09:18 -08001224 kNoLayer_SaveLayerStrategy,
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001225 };
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001226
fmalita6ca763f2014-06-17 13:52:18 -07001227 virtual void willSave() {}
reed4960eee2015-12-18 07:09:18 -08001228 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1229 virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) {
1230 return kFullLayer_SaveLayerStrategy;
1231 }
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001232 virtual void willRestore() {}
mtklein6cfa73a2014-08-13 13:33:49 -07001233 virtual void didRestore() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001234 virtual void didConcat(const SkMatrix&) {}
1235 virtual void didSetMatrix(const SkMatrix&) {}
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001236
reedf70b5312016-03-04 16:36:20 -08001237 virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001238 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1239
reed@google.come0d9ce82014-04-23 04:00:17 +00001240 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1241 SkScalar y, const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001242
reed@google.come0d9ce82014-04-23 04:00:17 +00001243 virtual void onDrawPosText(const void* text, size_t byteLength,
1244 const SkPoint pos[], const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001245
reed@google.come0d9ce82014-04-23 04:00:17 +00001246 virtual void onDrawPosTextH(const void* text, size_t byteLength,
1247 const SkScalar xpos[], SkScalar constY,
1248 const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001249
reed@google.come0d9ce82014-04-23 04:00:17 +00001250 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1251 const SkPath& path, const SkMatrix* matrix,
1252 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001253
fmalita00d5c2c2014-08-21 08:53:26 -07001254 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1255 const SkPaint& paint);
1256
dandovb3c9d1c2014-08-12 08:34:29 -07001257 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
1258 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@google.come0d9ce82014-04-23 04:00:17 +00001259
reeda8db7282015-07-07 10:22:31 -07001260 virtual void onDrawDrawable(SkDrawable*, const SkMatrix*);
reed6a070dc2014-11-11 19:36:09 -08001261
reed41af9662015-01-05 07:49:08 -08001262 virtual void onDrawPaint(const SkPaint&);
1263 virtual void onDrawRect(const SkRect&, const SkPaint&);
1264 virtual void onDrawOval(const SkRect&, const SkPaint&);
1265 virtual void onDrawRRect(const SkRRect&, const SkPaint&);
1266 virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
1267 virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
1268 const SkPoint texs[], const SkColor colors[], SkXfermode*,
1269 const uint16_t indices[], int indexCount, const SkPaint&);
mtklein2766c002015-06-26 11:45:03 -07001270
reed71c3c762015-06-24 10:29:17 -07001271 virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
1272 int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001273 virtual void onDrawPath(const SkPath&, const SkPaint&);
1274 virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
reed562fe472015-07-28 07:35:14 -07001275 virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
1276 SrcRectConstraint);
reed4c21dc52015-06-25 12:32:03 -07001277 virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
1278 const SkPaint*);
1279
reed41af9662015-01-05 07:49:08 -08001280 virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
1281 virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
reed562fe472015-07-28 07:35:14 -07001282 SrcRectConstraint);
reed41af9662015-01-05 07:49:08 -08001283 virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
1284 const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001285
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001286 enum ClipEdgeStyle {
1287 kHard_ClipEdgeStyle,
1288 kSoft_ClipEdgeStyle
1289 };
1290
1291 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1292 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1293 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1294 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1295
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +00001296 virtual void onDiscard();
1297
reedd5fa1a42014-08-09 11:08:05 -07001298 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
robertphillips9b14f262014-06-04 05:40:44 -07001299
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001300 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001301 // returns this. Subclasses that encapsulate an indirect canvas may
1302 // need to overload this method. The impl must keep track of this, as it
1303 // is not released or deleted by the caller.
1304 virtual SkCanvas* canvasForDrawIter();
1305
junov@chromium.orga907ac32012-02-24 21:54:07 +00001306 // Clip rectangle bounds. Called internally by saveLayer.
1307 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001308 // If non-NULL, The imageFilter parameter will be used to expand the clip
1309 // and offscreen bounds for any margin required by the filter DAG.
reed4960eee2015-12-18 07:09:18 -08001310 bool clipRectBounds(const SkRect* bounds, SaveLayerFlags, SkIRect* intersection,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001311 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001312
reedc83a2972015-07-16 07:40:45 -07001313private:
reed4960eee2015-12-18 07:09:18 -08001314 static bool BoundsAffectsClip(SaveLayerFlags);
reedbada1882015-12-21 13:09:44 -08001315 static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
reed4960eee2015-12-18 07:09:18 -08001316
reedc83a2972015-07-16 07:40:45 -07001317 enum ShaderOverrideOpacity {
1318 kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
1319 kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
1320 kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
1321 };
1322
reed@google.com97af1a62012-08-28 12:19:02 +00001323 // notify our surface (if we have one) that we are about to draw, so it
1324 // can perform copy-on-write or invalidate any cached images
reedc83a2972015-07-16 07:40:45 -07001325 void predrawNotify(bool willOverwritesEntireSurface = false);
1326 void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
1327 void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
1328 this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
1329 : kNotOpaque_ShaderOverrideOpacity);
1330 }
reed@google.com97af1a62012-08-28 12:19:02 +00001331
reed@android.com8a1c16f2008-12-17 15:59:43 +00001332 class MCRec;
1333
reed687fa1c2015-04-07 08:00:56 -07001334 SkAutoTUnref<SkClipStack> fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001335 SkDeque fMCStack;
1336 // points to top of stack
1337 MCRec* fMCRec;
1338 // the first N recs that can fit here mean we won't call malloc
reedb679ca82015-04-07 04:40:48 -07001339 enum {
reeda499f902015-05-01 09:34:31 -07001340 kMCRecSize = 128, // most recent measurement
reed31b80a92015-11-16 13:22:24 -08001341 kMCRecCount = 32, // common depth for save/restores
reed86a17e72015-05-14 12:25:22 -07001342 kDeviceCMSize = 136, // most recent measurement
reedb679ca82015-04-07 04:40:48 -07001343 };
1344 intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
reeda499f902015-05-01 09:34:31 -07001345 intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001346
reed4a8126e2014-09-22 07:29:03 -07001347 const SkSurfaceProps fProps;
1348
reed2ff1fce2014-12-11 07:07:37 -08001349 int fSaveCount; // value returned by getSaveCount()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001350
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001351 SkMetaData* fMetaData;
1352
reed@google.com97af1a62012-08-28 12:19:02 +00001353 SkSurface_Base* fSurfaceBase;
1354 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1355 void setSurfaceBase(SkSurface_Base* sb) {
1356 fSurfaceBase = sb;
1357 }
1358 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001359 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001360
reed@android.com8a1c16f2008-12-17 15:59:43 +00001361 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1362 void updateDeviceCMCache();
1363
reed2ff1fce2014-12-11 07:07:37 -08001364 void doSave();
1365 void checkForDeferredSave();
1366
reed@google.com9c135db2014-03-12 18:28:35 +00001367 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001368 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001369 friend class SkLua; // needs top layer size and offset
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +00001370 friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
reed52d9ac62014-06-30 09:05:34 -07001371 friend class SkSurface_Raster; // needs getDevice()
reedd9544982014-09-09 18:46:22 -07001372 friend class SkRecorder; // InitFlags
1373 friend class SkNoSaveLayerCanvas; // InitFlags
fmalita2d97bc12014-11-20 10:44:58 -08001374 friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
reedc83a2972015-07-16 07:40:45 -07001375 friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
reed4960eee2015-12-18 07:09:18 -08001376 friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
piotaixrb5fae932014-09-24 13:03:30 -07001377
reedd9544982014-09-09 18:46:22 -07001378 enum InitFlags {
1379 kDefault_InitFlags = 0,
1380 kConservativeRasterClip_InitFlag = 1 << 0,
1381 };
reed78e27682014-11-19 08:04:34 -08001382 SkCanvas(const SkIRect& bounds, InitFlags);
robertphillipsfcf78292015-06-19 11:49:52 -07001383 SkCanvas(SkBaseDevice* device, InitFlags);
reedd9544982014-09-09 18:46:22 -07001384
mtkleinfeaadee2015-04-08 11:25:48 -07001385 void resetForNextPicture(const SkIRect& bounds);
1386
reed8f2e7912014-09-04 12:45:18 -07001387 // needs gettotalclip()
tfarinaa5414c42014-10-10 06:19:09 -07001388 friend class SkCanvasStateUtils;
piotaixrb5fae932014-09-24 13:03:30 -07001389
reed4a8126e2014-09-22 07:29:03 -07001390 // call this each time we attach ourselves to a device
1391 // - constructor
1392 // - internalSaveLayer
1393 void setupDevice(SkBaseDevice*);
1394
reedd9544982014-09-09 18:46:22 -07001395 SkBaseDevice* init(SkBaseDevice*, InitFlags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001396
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001397 /**
senorblancoafc7cce2016-02-02 18:44:15 -08001398 * Gets the bounds of the top level layer in global canvas coordinates. We don't want this
bsalomon@google.com4ebe3822014-02-26 20:22:32 +00001399 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1400 */
senorblancoafc7cce2016-02-02 18:44:15 -08001401 SkIRect getTopLayerBounds() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001402
reed@google.com71121732012-09-18 15:14:33 +00001403 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001404 const SkRect& dst, const SkPaint* paint,
reeda5517e22015-07-14 10:54:12 -07001405 SrcRectConstraint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001406 void internalDrawPaint(const SkPaint& paint);
reed4960eee2015-12-18 07:09:18 -08001407 void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
reed61f501f2015-04-29 08:34:00 -07001408 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001409
reed@android.com8a1c16f2008-12-17 15:59:43 +00001410 // shared by save() and saveLayer()
reed2ff1fce2014-12-11 07:07:37 -08001411 void internalSave();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001412 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001413 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1414 const SkRect& r, SkScalar textSize);
1415 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1416 const char text[], size_t byteLength,
1417 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001418
reedfa35f8e2014-09-04 12:14:36 -07001419 // only for canvasutils
1420 const SkRegion& internal_private_getTotalClip() const;
1421
reedc83a2972015-07-16 07:40:45 -07001422 /*
1423 * Returns true if drawing the specified rect (or all if it is null) with the specified
1424 * paint (or default if null) would overwrite the entire root device of the canvas
1425 * (i.e. the canvas' surface if it had one).
1426 */
1427 bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
1428
reed262a71b2015-12-05 13:07:27 -08001429 /**
1430 * Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
1431 */
1432 bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
reedc83a2972015-07-16 07:40:45 -07001433
reed@android.com8a1c16f2008-12-17 15:59:43 +00001434 /* These maintain a cache of the clip bounds in local coordinates,
1435 (converted to 2s-compliment if floats are slow).
1436 */
reed@google.comc0784db2013-12-13 21:16:12 +00001437 mutable SkRect fCachedLocalClipBounds;
1438 mutable bool fCachedLocalClipBoundsDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001439 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001440 bool fAllowSimplifyClip;
reed42b73eb2015-11-20 13:42:42 -08001441 const bool fConservativeRasterClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001442
reed@google.comc0784db2013-12-13 21:16:12 +00001443 const SkRect& getLocalClipBounds() const {
1444 if (fCachedLocalClipBoundsDirty) {
1445 if (!this->getClipBounds(&fCachedLocalClipBounds)) {
1446 fCachedLocalClipBounds.setEmpty();
1447 }
1448 fCachedLocalClipBoundsDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001449 }
reed@google.comc0784db2013-12-13 21:16:12 +00001450 return fCachedLocalClipBounds;
reed@android.comba09de42010-02-05 20:46:05 +00001451 }
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001452
reed@google.com5c3d1472011-02-22 19:12:23 +00001453 class AutoValidateClip : ::SkNoncopyable {
1454 public:
1455 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1456 fCanvas->validateClip();
1457 }
1458 ~AutoValidateClip() { fCanvas->validateClip(); }
1459
1460 private:
1461 const SkCanvas* fCanvas;
1462 };
1463
1464#ifdef SK_DEBUG
1465 void validateClip() const;
1466#else
1467 void validateClip() const {}
1468#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001469
1470 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001471};
1472
1473/** Stack helper class to automatically call restoreToCount() on the canvas
1474 when this object goes out of scope. Use this to guarantee that the canvas
1475 is restored to a known state.
1476*/
1477class SkAutoCanvasRestore : SkNoncopyable {
1478public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001479 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1480 if (fCanvas) {
1481 fSaveCount = canvas->getSaveCount();
1482 if (doSave) {
1483 canvas->save();
1484 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001485 }
1486 }
1487 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001488 if (fCanvas) {
1489 fCanvas->restoreToCount(fSaveCount);
1490 }
1491 }
1492
1493 /**
1494 * Perform the restore now, instead of waiting for the destructor. Will
1495 * only do this once.
1496 */
1497 void restore() {
1498 if (fCanvas) {
1499 fCanvas->restoreToCount(fSaveCount);
1500 fCanvas = NULL;
1501 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001502 }
1503
1504private:
1505 SkCanvas* fCanvas;
1506 int fSaveCount;
1507};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001508#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001509
fmalitac3b589a2014-06-05 12:40:07 -07001510class SkCanvasClipVisitor {
1511public:
1512 virtual ~SkCanvasClipVisitor();
1513 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
1514 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
1515 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1516};
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001517
reed@android.com8a1c16f2008-12-17 15:59:43 +00001518#endif