blob: 611603715be3df8cc747ff17fe1255bbe2c71c44 [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"
msarette8597a42016-03-24 10:41:47 -070014#include "SkImage.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 "SkRegion.h"
reed4a8126e2014-09-22 07:29:03 -070018#include "SkSurfaceProps.h"
reed@android.com845fdac2009-06-23 03:01:32 +000019#include "SkXfermode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000020
bungemand3ebb482015-08-05 13:57:49 -070021class GrContext;
22class GrRenderTarget;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000023class SkBaseDevice;
reed6a070dc2014-11-11 19:36:09 -080024class SkCanvasClipVisitor;
bungemand3ebb482015-08-05 13:57:49 -070025class SkClipStack;
reedf70b5312016-03-04 16:36:20 -080026class SkData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000027class SkDraw;
reed3cb38402015-02-06 08:36:15 -080028class SkDrawable;
reed@android.com8a1c16f2008-12-17 15:59:43 +000029class SkDrawFilter;
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
brianosman898235c2016-04-06 07:38:23 -0700125 /**
126 * If the canvas is backed by pixels (cpu or gpu), this writes a copy of the SurfaceProps
127 * for the canvas to the location supplied by the caller, and returns true. Otherwise,
128 * return false and leave the supplied props unchanged.
129 */
130 bool getProps(SkSurfaceProps*) const;
131
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132 ///////////////////////////////////////////////////////////////////////////
133
reed@google.com210ce002011-11-01 14:24:23 +0000134 /**
bsalomone63ffef2016-02-05 07:17:34 -0800135 * Trigger the immediate execution of all pending draw operations. For the GPU
136 * backend this will resolve all rendering to the GPU surface backing the
137 * SkSurface that owns this canvas.
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000138 */
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 */
reede8f30622016-03-23 18:59:25 -0700196 sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps* = nullptr);
197#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
198 SkSurface* newSurface(const SkImageInfo& info, const SkSurfaceProps* props = NULL);
199#endif
bsalomon@google.come97f0852011-06-17 13:10:25 +0000200
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000201 /**
202 * Return the GPU context of the device that is associated with the canvas.
203 * For a canvas with non-GPU device, NULL is returned.
204 */
205 GrContext* getGrContext();
206
reed@google.com4b226022011-01-11 18:32:13 +0000207 ///////////////////////////////////////////////////////////////////////////
208
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000209 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000210 * If the canvas has writable pixels in its top layer (and is not recording to a picture
211 * or other non-raster target) and has direct access to its pixels (i.e. they are in
212 * local RAM) return the address of those pixels, and if not null,
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000213 * return the ImageInfo, rowBytes and origin. The returned address is only valid
reed@google.com9c135db2014-03-12 18:28:35 +0000214 * while the canvas object is in scope and unchanged. Any API calls made on
215 * canvas (or its parent surface if any) will invalidate the
216 * returned address (and associated information).
217 *
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000218 * On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
reed@google.com9c135db2014-03-12 18:28:35 +0000219 */
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000220 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
reed@google.com9c135db2014-03-12 18:28:35 +0000221
222 /**
223 * If the canvas has readable pixels in its base layer (and is not recording to a picture
224 * or other non-raster target) and has direct access to its pixels (i.e. they are in
reed6ceeebd2016-03-09 14:26:26 -0800225 * local RAM) return true, and if not null, return in the pixmap parameter information about
226 * the pixels. The pixmap's pixel address is only valid
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000227 * while the canvas object is in scope and unchanged. Any API calls made on
reed6ceeebd2016-03-09 14:26:26 -0800228 * canvas (or its parent surface if any) will invalidate the pixel address
229 * (and associated information).
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000230 *
reed6ceeebd2016-03-09 14:26:26 -0800231 * On failure, returns false and the pixmap parameter will be ignored.
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000232 */
reed6ceeebd2016-03-09 14:26:26 -0800233 bool peekPixels(SkPixmap*);
234
235#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000236 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
reed6ceeebd2016-03-09 14:26:26 -0800237#endif
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000238
reed@google.com4b226022011-01-11 18:32:13 +0000239 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000240 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
241 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
reedb184f7f2014-07-13 04:32:32 -0700242 * starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000243 *
reedb184f7f2014-07-13 04:32:32 -0700244 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000245 *
reedb184f7f2014-07-13 04:32:32 -0700246 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000247 *
reedb184f7f2014-07-13 04:32:32 -0700248 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
249 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
250 * corresponding src pixels, performing any colortype/alphatype transformations needed
251 * (in the case where the src and dst have different colortypes or alphatypes).
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000252 *
253 * This call can fail, returning false, for several reasons:
reedb184f7f2014-07-13 04:32:32 -0700254 * - If srcR does not intersect the base-layer bounds.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000255 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
256 * - If this canvas is not backed by pixels (e.g. picture or PDF)
257 */
reedb184f7f2014-07-13 04:32:32 -0700258 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
259 int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000260
261 /**
262 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
263 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
264 * it calls through to readPixels(info, ...) and returns its result.
265 */
reedb184f7f2014-07-13 04:32:32 -0700266 bool readPixels(SkBitmap* bitmap, int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000267
268 /**
269 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
270 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
271 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
272 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000273 */
274 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000275
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000276 /**
277 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
278 * ignoring the matrix and clip.
279 *
280 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
281 *
282 * target.setXYWH(x, y, info.width(), info.height());
283 *
284 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
285 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
286 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
287 * pixels, performing any colortype/alphatype transformations needed (in the case where the
288 * src and dst have different colortypes or alphatypes).
289 *
290 * This call can fail, returning false, for several reasons:
291 * - If the src colortype/alphatype cannot be converted to the canvas' types
292 * - If this canvas is not backed by pixels (e.g. picture or PDF)
293 */
294 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
295
296 /**
297 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
298 * is just wrapping a texture, returns false and does nothing.
299 */
300 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000301
reed@android.com8a1c16f2008-12-17 15:59:43 +0000302 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000303
reed@android.comdc3381f2010-02-11 16:05:15 +0000304 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000306 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
307 operate on this copy.
308 When the balancing call to restore() is made, the previous matrix, clip,
309 and drawFilter are restored.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000310
311 @return The value to pass to restoreToCount() to balance this save()
312 */
313 int save();
314
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315 /** This behaves the same as save(), but in addition it allocates an
316 offscreen bitmap. All drawing calls are directed there, and only when
317 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000318 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000319 @param bounds (may be null) This rect, if non-null, is used as a hint to
320 limit the size of the offscreen, and thus drawing may be
321 clipped to it, though that clipping is not guaranteed to
322 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000323 @param paint (may be null) This is copied, and is applied to the
324 offscreen when restore() is called
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000325 @return The value to pass to restoreToCount() to balance this save()
326 */
327 int saveLayer(const SkRect* bounds, const SkPaint* paint);
reed021f6312015-08-09 19:41:13 -0700328 int saveLayer(const SkRect& bounds, const SkPaint* paint) {
329 return this->saveLayer(&bounds, paint);
330 }
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000331
reed70ee31b2015-12-10 13:44:45 -0800332 /**
333 * Temporary name.
334 * Will allow any requests for LCD text to be respected, so the caller must be careful to
335 * only draw on top of opaque sections of the layer to get good results.
336 */
337 int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
338
reed@android.com8a1c16f2008-12-17 15:59:43 +0000339 /** This behaves the same as save(), but in addition it allocates an
340 offscreen bitmap. All drawing calls are directed there, and only when
341 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000342 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000343 @param bounds (may be null) This rect, if non-null, is used as a hint to
344 limit the size of the offscreen, and thus drawing may be
345 clipped to it, though that clipping is not guaranteed to
346 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000347 @param alpha This is applied to the offscreen when restore() is called.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000348 @return The value to pass to restoreToCount() to balance this save()
349 */
350 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
351
reed4960eee2015-12-18 07:09:18 -0800352 enum {
353 kIsOpaque_SaveLayerFlag = 1 << 0,
354 kPreserveLCDText_SaveLayerFlag = 1 << 1,
reedbada1882015-12-21 13:09:44 -0800355
356#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
357 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
358#endif
reed4960eee2015-12-18 07:09:18 -0800359 };
360 typedef uint32_t SaveLayerFlags;
361
362 struct SaveLayerRec {
reedbfd5f172016-01-07 11:28:08 -0800363 SaveLayerRec()
364 : fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
365 {}
reed4960eee2015-12-18 07:09:18 -0800366 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
367 : fBounds(bounds)
368 , fPaint(paint)
reedbfd5f172016-01-07 11:28:08 -0800369 , fBackdrop(nullptr)
370 , fSaveLayerFlags(saveLayerFlags)
371 {}
372 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
373 SaveLayerFlags saveLayerFlags)
374 : fBounds(bounds)
375 , fPaint(paint)
376 , fBackdrop(backdrop)
reed4960eee2015-12-18 07:09:18 -0800377 , fSaveLayerFlags(saveLayerFlags)
378 {}
379
reedbfd5f172016-01-07 11:28:08 -0800380 const SkRect* fBounds; // optional
381 const SkPaint* fPaint; // optional
382 const SkImageFilter* fBackdrop; // optional
383 SaveLayerFlags fSaveLayerFlags;
reed4960eee2015-12-18 07:09:18 -0800384 };
385
386 int saveLayer(const SaveLayerRec&);
387
reed@android.com8a1c16f2008-12-17 15:59:43 +0000388 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000389 modifications to the matrix/clip/drawFilter state since the last save
390 call.
391 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000392 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000393 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000394
395 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000396 This will equal # save() calls - # restore() calls + 1. The save count on
397 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000398 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000399 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000400
401 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000402 count reached saveCount. It is an error for saveCount to be greater than
403 getSaveCount(). To pop all the way back to the initial matrix/clip context
404 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000405 @param saveCount The number of save() levels to restore from
406 */
407 void restoreToCount(int saveCount);
408
409 /** Preconcat the current matrix with the specified translation
410 @param dx The distance to translate in X
411 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000412 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000413 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414
415 /** Preconcat the current matrix with the specified scale.
416 @param sx The amount to scale in X
417 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000418 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000419 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000420
421 /** Preconcat the current matrix with the specified rotation.
422 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000424 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425
426 /** Preconcat the current matrix with the specified skew.
427 @param sx The amount to skew in X
428 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000429 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000430 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000431
432 /** Preconcat the current matrix with the specified matrix.
433 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000434 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000435 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000436
reed@android.com8a1c16f2008-12-17 15:59:43 +0000437 /** Replace the current matrix with a copy of the specified matrix.
438 @param matrix The matrix that will be copied into the current matrix.
439 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000440 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000441
reed@android.com8a1c16f2008-12-17 15:59:43 +0000442 /** Helper for setMatrix(identity). Sets the current matrix to identity.
443 */
444 void resetMatrix();
445
reed@google.com4ed0fb72012-12-12 20:48:18 +0000446 /**
447 * Modify the current clip with the specified rectangle.
448 * @param rect The rect to combine with the current clip
449 * @param op The region op to apply to the current clip
450 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000451 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000452 void clipRect(const SkRect& rect,
453 SkRegion::Op op = SkRegion::kIntersect_Op,
454 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000455
reed@google.com4ed0fb72012-12-12 20:48:18 +0000456 /**
457 * Modify the current clip with the specified SkRRect.
458 * @param rrect The rrect 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 clipRRect(const SkRRect& rrect,
463 SkRegion::Op op = SkRegion::kIntersect_Op,
464 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000465
466 /**
467 * Modify the current clip with the specified path.
468 * @param path The path 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 clipPath(const SkPath& path,
473 SkRegion::Op op = SkRegion::kIntersect_Op,
474 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000475
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000476 /** EXPERIMENTAL -- only used for testing
477 Set to false to force clips to be hard, even if doAntiAlias=true is
478 passed to clipRect or clipPath.
479 */
480 void setAllowSoftClip(bool allow) {
481 fAllowSoftClip = allow;
482 }
483
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000484 /** EXPERIMENTAL -- only used for testing
485 Set to simplify clip stack using path ops.
486 */
487 void setAllowSimplifyClip(bool allow) {
488 fAllowSimplifyClip = allow;
489 }
490
reed@android.com8a1c16f2008-12-17 15:59:43 +0000491 /** Modify the current clip with the specified region. Note that unlike
492 clipRect() and clipPath() which transform their arguments by the current
493 matrix, clipRegion() assumes its argument is already in device
494 coordinates, and so no transformation is performed.
495 @param deviceRgn The region to apply to the current clip
496 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000497 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000498 void clipRegion(const SkRegion& deviceRgn,
499 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000500
501 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
502 specified region. This does not intersect or in any other way account
503 for the existing clip region.
504 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000505 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000506 void setClipRegion(const SkRegion& deviceRgn) {
507 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000508 }
509
reed@android.com8a1c16f2008-12-17 15:59:43 +0000510 /** Return true if the specified rectangle, after being transformed by the
511 current matrix, would lie completely outside of the current clip. Call
512 this to check if an area you intend to draw into is clipped out (and
513 therefore you can skip making the draw calls).
514 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000515 @return true if the rect (transformed by the canvas' matrix) does not
516 intersect with the canvas' clip
517 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000518 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000519
520 /** Return true if the specified path, 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). Note, for speed it may
524 return false even if the path itself might not intersect the clip
525 (i.e. the bounds of the path intersects, but the path does not).
526 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000527 @return true if the path (transformed by the canvas' matrix) does not
528 intersect with the canvas' clip
529 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000530 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000531
532 /** Return true if the horizontal band specified by top and bottom is
533 completely clipped out. This is a conservative calculation, meaning
534 that it is possible that if the method returns false, the band may still
535 in fact be clipped out, but the converse is not true. If this method
536 returns true, then the band is guaranteed to be clipped out.
537 @param top The top of the horizontal band to compare with the clip
538 @param bottom The bottom of the horizontal and to compare with the clip
539 @return true if the horizontal band is completely clipped out (i.e. does
540 not intersect the current clip)
541 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000542 bool quickRejectY(SkScalar top, SkScalar bottom) const {
reed@google.comc0784db2013-12-13 21:16:12 +0000543 SkASSERT(top <= bottom);
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000544
545#ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT
546 // TODO: add a hasPerspective method similar to getLocalClipBounds. This
547 // would cache the SkMatrix::hasPerspective result. Alternatively, have
548 // the MC stack just set a hasPerspective boolean as it is updated.
549 if (this->getTotalMatrix().hasPerspective()) {
skia.committer@gmail.coma3b53272014-02-15 03:02:15 +0000550 // TODO: consider implementing some half-plane test between the
commit-bot@chromium.org9836bc32014-02-14 19:52:18 +0000551 // two Y planes and the device-bounds (i.e., project the top and
552 // bottom Y planes and then determine if the clip bounds is completely
553 // outside either one).
554 return false;
555 }
556#endif
557
reed@google.comc0784db2013-12-13 21:16:12 +0000558 const SkRect& clipR = this->getLocalClipBounds();
djsollen@google.com92d2a292012-02-27 16:17:59 +0000559 // In the case where the clip is empty and we are provided with a
560 // negative top and positive bottom parameter then this test will return
561 // false even though it will be clipped. We have chosen to exclude that
562 // check as it is rare and would result double the comparisons.
reed@google.comc0784db2013-12-13 21:16:12 +0000563 return top >= clipR.fBottom || bottom <= clipR.fTop;
djsollen@google.com92d2a292012-02-27 16:17:59 +0000564 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000565
566 /** Return the bounds of the current clip (in local coordinates) in the
567 bounds parameter, and return true if it is non-empty. This can be useful
568 in a way similar to quickReject, in that it tells you that drawing
569 outside of these bounds will be clipped out.
570 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000571 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000572
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000573 /** Return the bounds of the current clip, in device coordinates; returns
574 true if non-empty. Maybe faster than getting the clip explicitly and
575 then taking its bounds.
576 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000577 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000578
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000579
reed@android.com8a1c16f2008-12-17 15:59:43 +0000580 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000581 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000582 @param a the alpha component (0..255) of the color to fill the canvas
583 @param r the red component (0..255) of the color to fill the canvas
584 @param g the green component (0..255) of the color to fill the canvas
585 @param b the blue component (0..255) of the color to fill the canvas
586 @param mode the mode to apply the color in (defaults to SrcOver)
587 */
588 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000589 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000590
591 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000592 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000593 @param color the color to draw with
594 @param mode the mode to apply the color in (defaults to SrcOver)
595 */
reed8eddfb52014-12-04 07:50:14 -0800596 void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000597
reedf4e0d9e2014-12-05 20:49:03 -0800598 /**
599 * Helper method for drawing a color in SRC mode, completely replacing all the pixels
600 * in the current clip with this color.
601 */
602 void clear(SkColor color) {
reed8eddfb52014-12-04 07:50:14 -0800603 this->drawColor(color, SkXfermode::kSrc_Mode);
604 }
reed@google.com2a981812011-04-14 18:59:28 +0000605
606 /**
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000607 * This makes the contents of the canvas undefined. Subsequent calls that
608 * require reading the canvas contents will produce undefined results. Examples
609 * include blending and readPixels. The actual implementation is backend-
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800610 * dependent and one legal implementation is to do nothing. This method
611 * ignores the current clip.
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000612 *
613 * This function should only be called if the caller intends to subsequently
614 * draw to the canvas. The canvas may do real work at discard() time in order
615 * to optimize performance on subsequent draws. Thus, if you call this and then
616 * never draw to the canvas subsequently you may pay a perfomance penalty.
617 */
618 void discard() { this->onDiscard(); }
619
620 /**
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800621 * Fill the entire canvas (restricted to the current clip) with the
reed@google.com2a981812011-04-14 18:59:28 +0000622 * specified paint.
623 * @param paint The paint used to fill the canvas
624 */
reed0846f1b2015-01-09 14:17:40 -0800625 void drawPaint(const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000626
627 enum PointMode {
628 /** drawPoints draws each point separately */
629 kPoints_PointMode,
630 /** drawPoints draws each pair of points as a line segment */
631 kLines_PointMode,
632 /** drawPoints draws the array of points as a polygon */
633 kPolygon_PointMode
634 };
635
636 /** Draw a series of points, interpreted based on the PointMode mode. For
637 all modes, the count parameter is interpreted as the total number of
638 points. For kLine mode, count/2 line segments are drawn.
639 For kPoint mode, each point is drawn centered at its coordinate, and its
640 size is specified by the paint's stroke-width. It draws as a square,
641 unless the paint's cap-type is round, in which the points are drawn as
642 circles.
643 For kLine mode, each pair of points is drawn as a line segment,
644 respecting the paint's settings for cap/join/width.
645 For kPolygon mode, the entire array is drawn as a series of connected
646 line segments.
647 Note that, while similar, kLine and kPolygon modes draw slightly
648 differently than the equivalent path built with a series of moveto,
649 lineto calls, in that the path will draw all of its contours at once,
650 with no interactions if contours intersect each other (think XOR
651 xfermode). drawPoints always draws each element one at a time.
652 @param mode PointMode specifying how to draw the array of points.
653 @param count The number of points in the array
654 @param pts Array of points to draw
655 @param paint The paint used to draw the points
656 */
reed0846f1b2015-01-09 14:17:40 -0800657 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658
659 /** Helper method for drawing a single point. See drawPoints() for a more
660 details.
661 */
662 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000663
reed@android.com8a1c16f2008-12-17 15:59:43 +0000664 /** Draws a single pixel in the specified color.
665 @param x The X coordinate of which pixel to draw
666 @param y The Y coordiante of which pixel to draw
667 @param color The color to draw
668 */
669 void drawPoint(SkScalar x, SkScalar y, SkColor color);
670
671 /** Draw a line segment with the specified start and stop x,y coordinates,
672 using the specified paint. NOTE: since a line is always "framed", the
673 paint's Style is ignored.
674 @param x0 The x-coordinate of the start point of the line
675 @param y0 The y-coordinate of the start point of the line
676 @param x1 The x-coordinate of the end point of the line
677 @param y1 The y-coordinate of the end point of the line
678 @param paint The paint used to draw the line
679 */
680 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
681 const SkPaint& paint);
682
683 /** Draw the specified rectangle using the specified paint. The rectangle
684 will be filled or stroked based on the Style in the paint.
685 @param rect The rect to be drawn
686 @param paint The paint used to draw the rect
687 */
reed0846f1b2015-01-09 14:17:40 -0800688 void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000689
690 /** Draw the specified rectangle using the specified paint. The rectangle
691 will be filled or framed based on the Style in the paint.
692 @param rect The rect to be drawn
693 @param paint The paint used to draw the rect
694 */
reed@google.com87001ed2014-02-17 16:28:05 +0000695 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000696 SkRect r;
697 r.set(rect); // promotes the ints to scalars
698 this->drawRect(r, paint);
699 }
reed@google.com4b226022011-01-11 18:32:13 +0000700
reed@android.com8a1c16f2008-12-17 15:59:43 +0000701 /** Draw the specified rectangle using the specified paint. The rectangle
702 will be filled or framed based on the Style in the paint.
703 @param left The left side of the rectangle to be drawn
704 @param top The top side of the rectangle to be drawn
705 @param right The right side of the rectangle to be drawn
706 @param bottom The bottom side of the rectangle to be drawn
707 @param paint The paint used to draw the rect
708 */
709 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
710 SkScalar bottom, const SkPaint& paint);
711
712 /** Draw the specified oval using the specified paint. The oval will be
713 filled or framed based on the Style in the paint.
714 @param oval The rectangle bounds of the oval to be drawn
715 @param paint The paint used to draw the oval
716 */
reed0846f1b2015-01-09 14:17:40 -0800717 void drawOval(const SkRect& oval, const SkPaint&);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000718
719 /**
720 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
721 * based on the Style in the paint.
722 *
723 * @param rrect The round-rect to draw
724 * @param paint The paint used to draw the round-rect
725 */
reed0846f1b2015-01-09 14:17:40 -0800726 void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000727
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000728 /**
729 * Draw the annulus formed by the outer and inner rrects. The results
730 * are undefined if the outer does not contain the inner.
731 */
732 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
733
reed@android.com8a1c16f2008-12-17 15:59:43 +0000734 /** Draw the specified circle using the specified paint. If radius is <= 0,
735 then nothing will be drawn. The circle will be filled
736 or framed based on the Style in the paint.
737 @param cx The x-coordinate of the center of the cirle to be drawn
738 @param cy The y-coordinate of the center of the cirle to be drawn
739 @param radius The radius of the cirle to be drawn
740 @param paint The paint used to draw the circle
741 */
742 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
743 const SkPaint& paint);
744
745 /** Draw the specified arc, which will be scaled to fit inside the
746 specified oval. If the sweep angle is >= 360, then the oval is drawn
747 completely. Note that this differs slightly from SkPath::arcTo, which
748 treats the sweep angle mod 360.
749 @param oval The bounds of oval used to define the shape of the arc
750 @param startAngle Starting angle (in degrees) where the arc begins
751 @param sweepAngle Sweep angle (in degrees) measured clockwise
752 @param useCenter true means include the center of the oval. For filling
753 this will draw a wedge. False means just use the arc.
754 @param paint The paint used to draw the arc
755 */
756 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
757 bool useCenter, const SkPaint& paint);
758
759 /** Draw the specified round-rect using the specified paint. The round-rect
760 will be filled or framed based on the Style in the paint.
761 @param rect The rectangular bounds of the roundRect to be drawn
762 @param rx The x-radius of the oval used to round the corners
763 @param ry The y-radius of the oval used to round the corners
764 @param paint The paint used to draw the roundRect
765 */
766 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
767 const SkPaint& paint);
768
769 /** Draw the specified path using the specified paint. The path will be
770 filled or framed based on the Style in the paint.
771 @param path The path to be drawn
772 @param paint The paint used to draw the path
773 */
reed0846f1b2015-01-09 14:17:40 -0800774 void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000775
piotaixrd52893c2014-09-25 14:39:40 -0700776 /** Draw the specified image, with its top/left corner at (x,y), using the
777 specified paint, transformed by the current matrix.
778
779 @param image The image to be drawn
780 @param left The position of the left side of the image being drawn
781 @param top The position of the top side of the image being drawn
782 @param paint The paint used to draw the image, or NULL
783 */
reed0846f1b2015-01-09 14:17:40 -0800784 void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
reedf8053da2016-03-17 08:14:57 -0700785 void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
786 const SkPaint* paint = NULL) {
787 this->drawImage(image.get(), left, top, paint);
788 }
piotaixrb5fae932014-09-24 13:03:30 -0700789
reeda5517e22015-07-14 10:54:12 -0700790 /**
791 * Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
792 * trading off speed for exactness.
793 *
794 * When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
795 * the pixels in the image. If there is a src-rect specified, it is intended to restrict the
796 * pixels that will be read. However, for performance reasons, some implementations may slow
797 * down if they cannot read 1-pixel past the src-rect boundary at times.
798 *
799 * This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
800 * If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
801 * must be strictly respected, the caller should pass kStrict.
802 */
803 enum SrcRectConstraint {
804 /**
805 * If kStrict is specified, the implementation must respect the src-rect
806 * (if specified) strictly, and will never sample outside of those bounds during sampling
807 * even when filtering. This may be slower than kFast.
808 */
809 kStrict_SrcRectConstraint,
810
811 /**
812 * If kFast is specified, the implementation may sample outside of the src-rect
bsalomon19e82e32015-10-23 09:27:42 -0700813 * (if specified) by half the width of filter. This allows greater flexibility
reeda5517e22015-07-14 10:54:12 -0700814 * to the implementation and can make the draw much faster.
815 */
816 kFast_SrcRectConstraint,
817 };
818
819 /** Draw the specified image, scaling and translating so that it fills the specified
820 * dst rect. If the src rect is non-null, only that subset of the image is transformed
821 * and drawn.
822 *
823 * @param image The image to be drawn
824 * @param src Optional: specify the subset of the image to be drawn
825 * @param dst The destination rectangle where the scaled/translated
826 * image will be drawn
827 * @param paint The paint used to draw the image, or NULL
828 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
829 */
reede47829b2015-08-06 10:02:53 -0700830 void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
831 const SkPaint* paint,
832 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
833 // variant that takes src SkIRect
834 void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
835 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
836 // variant that assumes src == image-bounds
reede47829b2015-08-06 10:02:53 -0700837 void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
838 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700839
reedf8053da2016-03-17 08:14:57 -0700840 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
841 const SkPaint* paint,
842 SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
843 this->drawImageRect(image.get(), src, dst, paint, constraint);
844 }
845 void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
846 const SkPaint* paint, SrcRectConstraint cons = kStrict_SrcRectConstraint) {
847 this->drawImageRect(image.get(), isrc, dst, paint, cons);
848 }
849 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
850 SrcRectConstraint cons = kStrict_SrcRectConstraint) {
851 this->drawImageRect(image.get(), dst, paint, cons);
852 }
853
reed4c21dc52015-06-25 12:32:03 -0700854 /**
855 * Draw the image stretched differentially to fit into dst.
856 * center is a rect within the image, and logically divides the image
857 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
858 * image is the "center", then the center-rect should be [2, 2, 3, 3].
859 *
860 * If the dst is >= the image size, then...
861 * - The 4 corners are not stretched at all.
862 * - The sides are stretched in only one axis.
863 * - The center is stretched in both axes.
864 * Else, for each axis where dst < image,
865 * - The corners shrink proportionally
866 * - The sides (along the shrink axis) and center are not drawn
867 */
868 void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
reedf8053da2016-03-17 08:14:57 -0700869 const SkPaint* paint = nullptr);
870 void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
871 const SkPaint* paint = nullptr) {
872 this->drawImageNine(image.get(), center, dst, paint);
873 }
reed4c21dc52015-06-25 12:32:03 -0700874
reed@android.com8a1c16f2008-12-17 15:59:43 +0000875 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
876 specified paint, transformed by the current matrix. Note: if the paint
877 contains a maskfilter that generates a mask which extends beyond the
878 bitmap's original width/height, then the bitmap will be drawn as if it
879 were in a Shader with CLAMP mode. Thus the color outside of the original
880 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000881
882 If a shader is present on the paint it will be ignored, except in the
reed@google.comf20fc242014-03-26 13:44:58 +0000883 case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000884 generated by the shader.
885
reed@android.com8a1c16f2008-12-17 15:59:43 +0000886 @param bitmap The bitmap to be drawn
887 @param left The position of the left side of the bitmap being drawn
888 @param top The position of the top side of the bitmap being drawn
889 @param paint The paint used to draw the bitmap, or NULL
890 */
reed0846f1b2015-01-09 14:17:40 -0800891 void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
892 const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000893
reeda5517e22015-07-14 10:54:12 -0700894 /** Draw the specified bitmap, scaling and translating so that it fills the specified
895 * dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
896 * and drawn.
897 *
898 * @param bitmap The bitmap to be drawn
899 * @param src Optional: specify the subset of the bitmap to be drawn
900 * @param dst The destination rectangle where the scaled/translated
901 * bitmap will be drawn
902 * @param paint The paint used to draw the bitmap, or NULL
903 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
904 */
reede47829b2015-08-06 10:02:53 -0700905 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
reed84984ef2015-07-17 07:09:43 -0700906 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700907 // variant where src is SkIRect
reed84984ef2015-07-17 07:09:43 -0700908 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
909 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700910 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
bsalomon19e82e32015-10-23 09:27:42 -0700911 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700912
reed@google.comf0b5e112011-09-07 11:57:34 +0000913 /**
914 * Draw the bitmap stretched differentially to fit into dst.
915 * center is a rect within the bitmap, and logically divides the bitmap
916 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
917 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
918 *
919 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000920 * - The 4 corners are not stretched at all.
921 * - The sides are stretched in only one axis.
922 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000923 * Else, for each axis where dst < bitmap,
924 * - The corners shrink proportionally
925 * - The sides (along the shrink axis) and center are not drawn
926 */
reed0846f1b2015-01-09 14:17:40 -0800927 void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
928 const SkPaint* paint = NULL);
reed@google.comf0b5e112011-09-07 11:57:34 +0000929
reed@android.com8a1c16f2008-12-17 15:59:43 +0000930 /** Draw the text, with origin at (x,y), using the specified paint.
931 The origin is interpreted based on the Align setting in the paint.
932 @param text The text to be drawn
933 @param byteLength The number of bytes to read from the text parameter
934 @param x The x-coordinate of the origin of the text being drawn
935 @param y The y-coordinate of the origin of the text being drawn
936 @param paint The paint used for the text (e.g. color, size, style)
937 */
reedf7430cc2014-12-21 11:38:35 -0800938 void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
939 const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000940
941 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +0000942 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000943 @param text The text to be drawn
944 @param byteLength The number of bytes to read from the text parameter
945 @param pos Array of positions, used to position each character
946 @param paint The paint used for the text (e.g. color, size, style)
947 */
reedf7430cc2014-12-21 11:38:35 -0800948 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
949 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000950
reed@android.com8a1c16f2008-12-17 15:59:43 +0000951 /** Draw the text, with each character/glyph origin specified by the x
952 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +0000953 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000954 @param text The text to be drawn
955 @param byteLength The number of bytes to read from the text parameter
956 @param xpos Array of x-positions, used to position each character
957 @param constY The shared Y coordinate for all of the positions
958 @param paint The paint used for the text (e.g. color, size, style)
959 */
reedf7430cc2014-12-21 11:38:35 -0800960 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
961 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000962
reed@android.com8a1c16f2008-12-17 15:59:43 +0000963 /** Draw the text, with origin at (x,y), using the specified paint, along
964 the specified path. The paint's Align setting determins where along the
965 path to start the text.
966 @param text The text to be drawn
967 @param byteLength The number of bytes to read from the text parameter
968 @param path The path the text should follow for its baseline
969 @param hOffset The distance along the path to add to the text's
970 starting position
971 @param vOffset The distance above(-) or below(+) the path to
972 position the text
973 @param paint The paint used for the text
974 */
reedf7430cc2014-12-21 11:38:35 -0800975 void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
reed@android.com8a1c16f2008-12-17 15:59:43 +0000976 SkScalar vOffset, const SkPaint& paint);
977
978 /** Draw the text, with origin at (x,y), using the specified paint, along
979 the specified path. The paint's Align setting determins where along the
980 path to start the text.
981 @param text The text to be drawn
982 @param byteLength The number of bytes to read from the text parameter
983 @param path The path the text should follow for its baseline
984 @param matrix (may be null) Applied to the text before it is
985 mapped onto the path
986 @param paint The paint used for the text
987 */
reedf7430cc2014-12-21 11:38:35 -0800988 void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
989 const SkMatrix* matrix, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000990
fmalita00d5c2c2014-08-21 08:53:26 -0700991 /** Draw the text blob, offset by (x,y), using the specified paint.
992 @param blob The text blob to be drawn
993 @param x The x-offset of the text being drawn
994 @param y The y-offset of the text being drawn
995 @param paint The paint used for the text (e.g. color, size, style)
996 */
997 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
998
reed@android.com8a1c16f2008-12-17 15:59:43 +0000999 /** Draw the picture into this canvas. This method effective brackets the
1000 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +00001001 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001002 @param picture The recorded drawing commands to playback into this
1003 canvas.
1004 */
reed1c2c4412015-04-30 13:09:24 -07001005 void drawPicture(const SkPicture* picture) {
1006 this->drawPicture(picture, NULL, NULL);
1007 }
reedca2622b2016-03-18 07:25:55 -07001008 void drawPicture(const sk_sp<SkPicture>& picture) {
reedf8053da2016-03-17 08:14:57 -07001009 this->drawPicture(picture.get());
1010 }
robertphillips9b14f262014-06-04 05:40:44 -07001011
reedd5fa1a42014-08-09 11:08:05 -07001012 /**
1013 * Draw the picture into this canvas.
1014 *
1015 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1016 * logically equivalent to
1017 * save/concat/drawPicture/restore
1018 *
1019 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1020 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1021 * This is logically equivalent to
1022 * saveLayer(paint)/drawPicture/restore
1023 */
1024 void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
reedca2622b2016-03-18 07:25:55 -07001025 void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) {
reedf8053da2016-03-17 08:14:57 -07001026 this->drawPicture(picture.get(), matrix, paint);
1027 }
reedd5fa1a42014-08-09 11:08:05 -07001028
reed@android.com8a1c16f2008-12-17 15:59:43 +00001029 enum VertexMode {
1030 kTriangles_VertexMode,
1031 kTriangleStrip_VertexMode,
1032 kTriangleFan_VertexMode
1033 };
reed@google.com4b226022011-01-11 18:32:13 +00001034
reed@android.com8a1c16f2008-12-17 15:59:43 +00001035 /** Draw the array of vertices, interpreted as triangles (based on mode).
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001036
1037 If both textures and vertex-colors are NULL, it strokes hairlines with
1038 the paint's color. This behavior is a useful debugging mode to visualize
1039 the mesh.
1040
reed@android.com8a1c16f2008-12-17 15:59:43 +00001041 @param vmode How to interpret the array of vertices
1042 @param vertexCount The number of points in the vertices array (and
1043 corresponding texs and colors arrays if non-null)
1044 @param vertices Array of vertices for the mesh
1045 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +00001046 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001047 @param colors May be null. If not null, specifies a color for each
1048 vertex, to be interpolated across the triangle.
1049 @param xmode Used if both texs and colors are present. In this
1050 case the colors are combined with the texture using mode,
1051 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +00001052 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001053 @param indices If not null, array of indices to reference into the
1054 vertex (texs, colors) array.
1055 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001056 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001057 */
reed0846f1b2015-01-09 14:17:40 -08001058 void drawVertices(VertexMode vmode, int vertexCount,
1059 const SkPoint vertices[], const SkPoint texs[],
1060 const SkColor colors[], SkXfermode* xmode,
1061 const uint16_t indices[], int indexCount,
1062 const SkPaint& paint);
reedcfb6bdf2016-03-29 11:32:50 -07001063 void drawVertices(VertexMode vmode, int vertexCount,
1064 const SkPoint vertices[], const SkPoint texs[],
mtklein92d48832016-04-01 04:55:47 -07001065 const SkColor colors[], const sk_sp<SkXfermode>& xmode,
reedcfb6bdf2016-03-29 11:32:50 -07001066 const uint16_t indices[], int indexCount,
1067 const SkPaint& paint) {
1068 this->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode.get(),
1069 indices, indexCount, paint);
1070 }
mtklein6cfa73a2014-08-13 13:33:49 -07001071
dandovb3c9d1c2014-08-12 08:34:29 -07001072 /**
1073 Draw a cubic coons patch
mtklein6cfa73a2014-08-13 13:33:49 -07001074
dandovb3c9d1c2014-08-12 08:34:29 -07001075 @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1076 starting at the top left corner.
1077 @param colors specifies the colors for the corners which will be bilerp across the patch,
1078 their order is clockwise starting at the top left corner.
mtklein6cfa73a2014-08-13 13:33:49 -07001079 @param texCoords specifies the texture coordinates that will be bilerp across the patch,
dandovb3c9d1c2014-08-12 08:34:29 -07001080 their order is the same as the colors.
mtklein6cfa73a2014-08-13 13:33:49 -07001081 @param xmode specifies how are the colors and the textures combined if both of them are
dandovb3c9d1c2014-08-12 08:34:29 -07001082 present.
dandov963137b2014-08-07 07:49:53 -07001083 @param paint Specifies the shader/texture if present.
1084 */
dandovb3c9d1c2014-08-12 08:34:29 -07001085 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1086 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reedcfb6bdf2016-03-29 11:32:50 -07001087 void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
1088 const sk_sp<SkXfermode>& xmode, const SkPaint& paint) {
1089 this->drawPatch(cubics, colors, texCoords, xmode.get(), paint);
1090 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001091
reed3cb38402015-02-06 08:36:15 -08001092 /**
reed71c3c762015-06-24 10:29:17 -07001093 * Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
1094 * coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
1095 * into a quad.
1096 *
1097 * xform maps [0, 0, tex.width, tex.height] -> quad
1098 *
1099 * The color array is optional. When specified, each color modulates the pixels in its
1100 * corresponding quad (via the specified SkXfermode::Mode).
1101 *
1102 * The cullRect is optional. When specified, it must be a conservative bounds of all of the
1103 * resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
1104 * intersect the current clip.
1105 *
1106 * The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
1107 * and xfermode are used to affect each of the quads.
1108 */
1109 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1110 const SkColor colors[], int count, SkXfermode::Mode, const SkRect* cullRect,
1111 const SkPaint* paint);
1112
1113 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
1114 const SkRect* cullRect, const SkPaint* paint) {
1115 this->drawAtlas(atlas, xform, tex, NULL, count, SkXfermode::kDst_Mode, cullRect, paint);
1116 }
1117
reedf8053da2016-03-17 08:14:57 -07001118 void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1119 const SkColor colors[], int count, SkXfermode::Mode mode, const SkRect* cull,
1120 const SkPaint* paint) {
1121 this->drawAtlas(atlas.get(), xform, tex, colors, count, mode, cull, paint);
1122 }
1123 void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1124 int count, const SkRect* cullRect, const SkPaint* paint) {
1125 this->drawAtlas(atlas.get(), xform, tex, nullptr, count, SkXfermode::kDst_Mode,
1126 cullRect, paint);
1127 }
1128
reed71c3c762015-06-24 10:29:17 -07001129 /**
reed3cb38402015-02-06 08:36:15 -08001130 * Draw the contents of this drawable into the canvas. If the canvas is async
1131 * (e.g. it is recording into a picture) then the drawable will be referenced instead,
1132 * to have its draw() method called when the picture is finalized.
1133 *
1134 * If the intent is to force the contents of the drawable into this canvas immediately,
1135 * then drawable->draw(canvas) may be called.
1136 */
reeda8db7282015-07-07 10:22:31 -07001137 void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL);
1138 void drawDrawable(SkDrawable*, SkScalar x, SkScalar y);
reed6a070dc2014-11-11 19:36:09 -08001139
reedf70b5312016-03-04 16:36:20 -08001140 /**
1141 * Send an "annotation" to the canvas. The annotation is a key/value pair, where the key is
1142 * a null-terminated utf8 string, and the value is a blob of data stored in an SkData
1143 * (which may be null). The annotation is associated with the specified rectangle.
1144 *
1145 * The caller still retains its ownership of the data (if any).
1146 *
1147 * Note: on may canvas types, this information is ignored, but some canvases (e.g. recording
1148 * a picture or drawing to a PDF document) will pass on this information.
1149 */
1150 void drawAnnotation(const SkRect&, const char key[], SkData* value);
mtklein0fba3b92016-04-01 04:55:51 -07001151 void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
1152 this->drawAnnotation(rect, key, value.get());
1153 }
reedf70b5312016-03-04 16:36:20 -08001154
reed@android.com8a1c16f2008-12-17 15:59:43 +00001155 //////////////////////////////////////////////////////////////////////////
fmalita77650002016-01-21 18:47:11 -08001156#ifdef SK_INTERNAL
fmalita53d9f1c2016-01-25 06:23:54 -08001157#ifndef SK_SUPPORT_LEGACY_DRAWFILTER
1158 #define SK_SUPPORT_LEGACY_DRAWFILTER
fmalita77650002016-01-21 18:47:11 -08001159#endif
1160#endif
reed@google.com4b226022011-01-11 18:32:13 +00001161
fmalita53d9f1c2016-01-25 06:23:54 -08001162#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
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 */
fmalita77650002016-01-21 18:47:11 -08001167 SK_ATTR_EXTERNALLY_DEPRECATED("getDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001168 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001169
reed@android.com8a1c16f2008-12-17 15:59:43 +00001170 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1171 As a convenience, the parameter is returned. If an existing filter
1172 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001173 refcnt is incremented. The filter is saved/restored, just like the
1174 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001175 @param filter the new filter (or NULL)
1176 @return the new filter
1177 */
fmalita77650002016-01-21 18:47:11 -08001178 SK_ATTR_EXTERNALLY_DEPRECATED("setDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001179 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
fmalita77650002016-01-21 18:47:11 -08001180#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001181 //////////////////////////////////////////////////////////////////////////
1182
reed@google.com754de5f2014-02-24 19:38:20 +00001183 /**
1184 * Return true if the current clip is empty (i.e. nothing will draw).
1185 * Note: this is not always a free call, so it should not be used
1186 * more often than necessary. However, once the canvas has computed this
1187 * result, subsequent calls will be cheap (until the clip state changes,
1188 * which can happen on any clip..() or restore() call.
1189 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001190 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001191
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001192 /**
1193 * Returns true if the current clip is just a (non-empty) rectangle.
1194 * Returns false if the clip is empty, or if it is complex.
1195 */
1196 virtual bool isClipRect() const;
1197
reed@android.com8a1c16f2008-12-17 15:59:43 +00001198 /** Return the current matrix on the canvas.
1199 This does not account for the translate in any of the devices.
1200 @return The current matrix on the canvas.
1201 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001202 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001203
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001204 /** Return the clip stack. The clip stack stores all the individual
1205 * clips organized by the save/restore frame in which they were
1206 * added.
1207 * @return the current clip stack ("list" of individual clip elements)
1208 */
1209 const SkClipStack* getClipStack() const {
reed687fa1c2015-04-07 08:00:56 -07001210 return fClipStack;
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001211 }
1212
fmalitac3b589a2014-06-05 12:40:07 -07001213 typedef SkCanvasClipVisitor ClipVisitor;
reed@google.com90c07ea2012-04-13 13:50:27 +00001214 /**
1215 * Replays the clip operations, back to front, that have been applied to
1216 * the canvas, calling the appropriate method on the visitor for each
1217 * clip. All clips have already been transformed into device space.
1218 */
1219 void replayClips(ClipVisitor*) const;
1220
reed@android.com8a1c16f2008-12-17 15:59:43 +00001221 ///////////////////////////////////////////////////////////////////////////
1222
robertphillips36736a22016-04-23 08:26:43 -07001223 // don't call
1224 GrRenderTarget* internal_private_accessTopLayerRenderTarget();
1225
1226 // don't call
1227 static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1228 static bool Internal_Private_GetIgnoreSaveLayerBounds();
1229 static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1230 static bool Internal_Private_GetTreatSpriteAsBitmap();
1231
1232 // TEMP helpers until we switch virtual over to const& for src-rect
1233 void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1234 const SkPaint* paint,
1235 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1236 void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1237 const SkPaint* paint,
1238 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1239
robertphillipsda2cd8b2016-04-21 11:05:32 -07001240protected:
reed@android.com8a1c16f2008-12-17 15:59:43 +00001241 /** After calling saveLayer(), there can be any number of devices that make
1242 up the top-most drawing area. LayerIter can be used to iterate through
1243 those devices. Note that the iterator is only valid until the next API
1244 call made on the canvas. Ownership of all pointers in the iterator stays
1245 with the canvas, so none of them should be modified or deleted.
1246 */
robertphillips36736a22016-04-23 08:26:43 -07001247 class LayerIter /*: SkNoncopyable*/ {
reed@android.com8a1c16f2008-12-17 15:59:43 +00001248 public:
1249 /** Initialize iterator with canvas, and set values for 1st device */
1250 LayerIter(SkCanvas*, bool skipEmptyClips);
1251 ~LayerIter();
reed@google.com4b226022011-01-11 18:32:13 +00001252
reed@android.com8a1c16f2008-12-17 15:59:43 +00001253 /** Return true if the iterator is done */
1254 bool done() const { return fDone; }
1255 /** Cycle to the next device */
1256 void next();
reed@google.com4b226022011-01-11 18:32:13 +00001257
reed@android.com8a1c16f2008-12-17 15:59:43 +00001258 // These reflect the current device in the iterator
1259
robertphillips@google.com1f2f3382013-08-29 11:54:56 +00001260 SkBaseDevice* device() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001261 const SkMatrix& matrix() const;
1262 const SkRegion& clip() const;
1263 const SkPaint& paint() const;
1264 int x() const;
1265 int y() const;
reed@google.com4b226022011-01-11 18:32:13 +00001266
reed@android.com8a1c16f2008-12-17 15:59:43 +00001267 private:
1268 // used to embed the SkDrawIter object directly in our instance, w/o
1269 // having to expose that class def to the public. There is an assert
1270 // in our constructor to ensure that fStorage is large enough
1271 // (though needs to be a compile-time-assert!). We use intptr_t to work
1272 // safely with 32 and 64 bit machines (to ensure the storage is enough)
reed@android.comf2b98d62010-12-20 18:26:13 +00001273 intptr_t fStorage[32];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001274 class SkDrawIter* fImpl; // this points at fStorage
1275 SkPaint fDefaultPaint;
1276 bool fDone;
1277 };
1278
reed@google.com76f10a32014-02-05 15:32:21 +00001279 // default impl defers to getDevice()->newSurface(info)
reede8f30622016-03-23 18:59:25 -07001280 virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
reed@google.com76f10a32014-02-05 15:32:21 +00001281
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001282 // default impl defers to its device
reed884e97c2015-05-26 11:31:54 -07001283 virtual bool onPeekPixels(SkPixmap*);
1284 virtual bool onAccessTopLayerPixels(SkPixmap*);
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001285
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001286 // Subclass save/restore notifiers.
1287 // Overriders should call the corresponding INHERITED method up the inheritance chain.
reed4960eee2015-12-18 07:09:18 -08001288 // getSaveLayerStrategy()'s return value may suppress full layer allocation.
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001289 enum SaveLayerStrategy {
1290 kFullLayer_SaveLayerStrategy,
reed4960eee2015-12-18 07:09:18 -08001291 kNoLayer_SaveLayerStrategy,
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001292 };
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001293
fmalita6ca763f2014-06-17 13:52:18 -07001294 virtual void willSave() {}
reed4960eee2015-12-18 07:09:18 -08001295 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1296 virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) {
1297 return kFullLayer_SaveLayerStrategy;
1298 }
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001299 virtual void willRestore() {}
mtklein6cfa73a2014-08-13 13:33:49 -07001300 virtual void didRestore() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001301 virtual void didConcat(const SkMatrix&) {}
1302 virtual void didSetMatrix(const SkMatrix&) {}
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001303
reedf70b5312016-03-04 16:36:20 -08001304 virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001305 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1306
reed@google.come0d9ce82014-04-23 04:00:17 +00001307 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1308 SkScalar y, const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001309
reed@google.come0d9ce82014-04-23 04:00:17 +00001310 virtual void onDrawPosText(const void* text, size_t byteLength,
1311 const SkPoint pos[], const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001312
reed@google.come0d9ce82014-04-23 04:00:17 +00001313 virtual void onDrawPosTextH(const void* text, size_t byteLength,
1314 const SkScalar xpos[], SkScalar constY,
1315 const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001316
reed@google.come0d9ce82014-04-23 04:00:17 +00001317 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1318 const SkPath& path, const SkMatrix* matrix,
1319 const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001320
fmalita00d5c2c2014-08-21 08:53:26 -07001321 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1322 const SkPaint& paint);
1323
dandovb3c9d1c2014-08-12 08:34:29 -07001324 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
1325 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@google.come0d9ce82014-04-23 04:00:17 +00001326
reeda8db7282015-07-07 10:22:31 -07001327 virtual void onDrawDrawable(SkDrawable*, const SkMatrix*);
reed6a070dc2014-11-11 19:36:09 -08001328
reed41af9662015-01-05 07:49:08 -08001329 virtual void onDrawPaint(const SkPaint&);
1330 virtual void onDrawRect(const SkRect&, const SkPaint&);
1331 virtual void onDrawOval(const SkRect&, const SkPaint&);
1332 virtual void onDrawRRect(const SkRRect&, const SkPaint&);
1333 virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
1334 virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
1335 const SkPoint texs[], const SkColor colors[], SkXfermode*,
1336 const uint16_t indices[], int indexCount, const SkPaint&);
mtklein2766c002015-06-26 11:45:03 -07001337
reed71c3c762015-06-24 10:29:17 -07001338 virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
1339 int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001340 virtual void onDrawPath(const SkPath&, const SkPaint&);
1341 virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
reed562fe472015-07-28 07:35:14 -07001342 virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
1343 SrcRectConstraint);
reed4c21dc52015-06-25 12:32:03 -07001344 virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
1345 const SkPaint*);
1346
reed41af9662015-01-05 07:49:08 -08001347 virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
1348 virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
reed562fe472015-07-28 07:35:14 -07001349 SrcRectConstraint);
reed41af9662015-01-05 07:49:08 -08001350 virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
1351 const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001352
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001353 enum ClipEdgeStyle {
1354 kHard_ClipEdgeStyle,
1355 kSoft_ClipEdgeStyle
1356 };
1357
1358 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1359 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1360 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1361 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1362
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +00001363 virtual void onDiscard();
1364
reedd5fa1a42014-08-09 11:08:05 -07001365 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
robertphillips9b14f262014-06-04 05:40:44 -07001366
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001367 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001368 // returns this. Subclasses that encapsulate an indirect canvas may
1369 // need to overload this method. The impl must keep track of this, as it
1370 // is not released or deleted by the caller.
1371 virtual SkCanvas* canvasForDrawIter();
1372
junov@chromium.orga907ac32012-02-24 21:54:07 +00001373 // Clip rectangle bounds. Called internally by saveLayer.
1374 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001375 // If non-NULL, The imageFilter parameter will be used to expand the clip
1376 // and offscreen bounds for any margin required by the filter DAG.
reed4960eee2015-12-18 07:09:18 -08001377 bool clipRectBounds(const SkRect* bounds, SaveLayerFlags, SkIRect* intersection,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001378 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001379
reedc83a2972015-07-16 07:40:45 -07001380private:
reed4960eee2015-12-18 07:09:18 -08001381 static bool BoundsAffectsClip(SaveLayerFlags);
reedbada1882015-12-21 13:09:44 -08001382 static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
reed4960eee2015-12-18 07:09:18 -08001383
reedc83a2972015-07-16 07:40:45 -07001384 enum ShaderOverrideOpacity {
1385 kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
1386 kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
1387 kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
1388 };
1389
reed@google.com97af1a62012-08-28 12:19:02 +00001390 // notify our surface (if we have one) that we are about to draw, so it
1391 // can perform copy-on-write or invalidate any cached images
reedc83a2972015-07-16 07:40:45 -07001392 void predrawNotify(bool willOverwritesEntireSurface = false);
1393 void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
1394 void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
1395 this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
1396 : kNotOpaque_ShaderOverrideOpacity);
1397 }
reed@google.com97af1a62012-08-28 12:19:02 +00001398
reed@android.com8a1c16f2008-12-17 15:59:43 +00001399 class MCRec;
1400
reed687fa1c2015-04-07 08:00:56 -07001401 SkAutoTUnref<SkClipStack> fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001402 SkDeque fMCStack;
1403 // points to top of stack
1404 MCRec* fMCRec;
1405 // the first N recs that can fit here mean we won't call malloc
reedb679ca82015-04-07 04:40:48 -07001406 enum {
reeda499f902015-05-01 09:34:31 -07001407 kMCRecSize = 128, // most recent measurement
reed31b80a92015-11-16 13:22:24 -08001408 kMCRecCount = 32, // common depth for save/restores
reed8c30a812016-04-20 16:36:51 -07001409 kDeviceCMSize = 176, // most recent measurement
reedb679ca82015-04-07 04:40:48 -07001410 };
1411 intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
reeda499f902015-05-01 09:34:31 -07001412 intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001413
reed4a8126e2014-09-22 07:29:03 -07001414 const SkSurfaceProps fProps;
1415
reed2ff1fce2014-12-11 07:07:37 -08001416 int fSaveCount; // value returned by getSaveCount()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001417
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001418 SkMetaData* fMetaData;
1419
reed@google.com97af1a62012-08-28 12:19:02 +00001420 SkSurface_Base* fSurfaceBase;
1421 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1422 void setSurfaceBase(SkSurface_Base* sb) {
1423 fSurfaceBase = sb;
1424 }
1425 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001426 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001427
reed@android.com8a1c16f2008-12-17 15:59:43 +00001428 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1429 void updateDeviceCMCache();
1430
reed2ff1fce2014-12-11 07:07:37 -08001431 void doSave();
1432 void checkForDeferredSave();
reed8c30a812016-04-20 16:36:51 -07001433 void internalSetMatrix(const SkMatrix&);
reed2ff1fce2014-12-11 07:07:37 -08001434
robertphillipsda2cd8b2016-04-21 11:05:32 -07001435 friend class CanvasTestingAccess; // for testing
reed@google.com9c135db2014-03-12 18:28:35 +00001436 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001437 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001438 friend class SkLua; // needs top layer size and offset
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +00001439 friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
reed52d9ac62014-06-30 09:05:34 -07001440 friend class SkSurface_Raster; // needs getDevice()
reedd9544982014-09-09 18:46:22 -07001441 friend class SkRecorder; // InitFlags
1442 friend class SkNoSaveLayerCanvas; // InitFlags
fmalita2d97bc12014-11-20 10:44:58 -08001443 friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
reedc83a2972015-07-16 07:40:45 -07001444 friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
reed4960eee2015-12-18 07:09:18 -08001445 friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
piotaixrb5fae932014-09-24 13:03:30 -07001446
reedd9544982014-09-09 18:46:22 -07001447 enum InitFlags {
1448 kDefault_InitFlags = 0,
1449 kConservativeRasterClip_InitFlag = 1 << 0,
1450 };
reed78e27682014-11-19 08:04:34 -08001451 SkCanvas(const SkIRect& bounds, InitFlags);
robertphillipsfcf78292015-06-19 11:49:52 -07001452 SkCanvas(SkBaseDevice* device, InitFlags);
reedd9544982014-09-09 18:46:22 -07001453
mtkleinfeaadee2015-04-08 11:25:48 -07001454 void resetForNextPicture(const SkIRect& bounds);
1455
reed8f2e7912014-09-04 12:45:18 -07001456 // needs gettotalclip()
tfarinaa5414c42014-10-10 06:19:09 -07001457 friend class SkCanvasStateUtils;
piotaixrb5fae932014-09-24 13:03:30 -07001458
reed4a8126e2014-09-22 07:29:03 -07001459 // call this each time we attach ourselves to a device
1460 // - constructor
1461 // - internalSaveLayer
1462 void setupDevice(SkBaseDevice*);
1463
reedd9544982014-09-09 18:46:22 -07001464 SkBaseDevice* init(SkBaseDevice*, InitFlags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001465
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001466 /**
senorblancoafc7cce2016-02-02 18:44:15 -08001467 * 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 +00001468 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1469 */
senorblancoafc7cce2016-02-02 18:44:15 -08001470 SkIRect getTopLayerBounds() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001471
reed@google.com71121732012-09-18 15:14:33 +00001472 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001473 const SkRect& dst, const SkPaint* paint,
reeda5517e22015-07-14 10:54:12 -07001474 SrcRectConstraint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001475 void internalDrawPaint(const SkPaint& paint);
reed4960eee2015-12-18 07:09:18 -08001476 void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
reed61f501f2015-04-29 08:34:00 -07001477 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, bool isBitmapDevice);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001478
reed@android.com8a1c16f2008-12-17 15:59:43 +00001479 // shared by save() and saveLayer()
reed2ff1fce2014-12-11 07:07:37 -08001480 void internalSave();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001481 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001482 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1483 const SkRect& r, SkScalar textSize);
1484 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1485 const char text[], size_t byteLength,
1486 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001487
reedfa35f8e2014-09-04 12:14:36 -07001488 // only for canvasutils
1489 const SkRegion& internal_private_getTotalClip() const;
1490
reedc83a2972015-07-16 07:40:45 -07001491 /*
1492 * Returns true if drawing the specified rect (or all if it is null) with the specified
1493 * paint (or default if null) would overwrite the entire root device of the canvas
1494 * (i.e. the canvas' surface if it had one).
1495 */
1496 bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
1497
reed262a71b2015-12-05 13:07:27 -08001498 /**
1499 * Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
1500 */
1501 bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
reedc83a2972015-07-16 07:40:45 -07001502
reed@android.com8a1c16f2008-12-17 15:59:43 +00001503 /* These maintain a cache of the clip bounds in local coordinates,
1504 (converted to 2s-compliment if floats are slow).
1505 */
reed@google.comc0784db2013-12-13 21:16:12 +00001506 mutable SkRect fCachedLocalClipBounds;
1507 mutable bool fCachedLocalClipBoundsDirty;
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001508 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001509 bool fAllowSimplifyClip;
reed42b73eb2015-11-20 13:42:42 -08001510 const bool fConservativeRasterClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001511
reed@google.comc0784db2013-12-13 21:16:12 +00001512 const SkRect& getLocalClipBounds() const {
1513 if (fCachedLocalClipBoundsDirty) {
1514 if (!this->getClipBounds(&fCachedLocalClipBounds)) {
1515 fCachedLocalClipBounds.setEmpty();
1516 }
1517 fCachedLocalClipBoundsDirty = false;
reed@android.comba09de42010-02-05 20:46:05 +00001518 }
reed@google.comc0784db2013-12-13 21:16:12 +00001519 return fCachedLocalClipBounds;
reed@android.comba09de42010-02-05 20:46:05 +00001520 }
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001521
reed@google.com5c3d1472011-02-22 19:12:23 +00001522 class AutoValidateClip : ::SkNoncopyable {
1523 public:
1524 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1525 fCanvas->validateClip();
1526 }
1527 ~AutoValidateClip() { fCanvas->validateClip(); }
1528
1529 private:
1530 const SkCanvas* fCanvas;
1531 };
1532
1533#ifdef SK_DEBUG
1534 void validateClip() const;
1535#else
1536 void validateClip() const {}
1537#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001538
1539 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001540};
1541
1542/** Stack helper class to automatically call restoreToCount() on the canvas
1543 when this object goes out of scope. Use this to guarantee that the canvas
1544 is restored to a known state.
1545*/
1546class SkAutoCanvasRestore : SkNoncopyable {
1547public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001548 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1549 if (fCanvas) {
1550 fSaveCount = canvas->getSaveCount();
1551 if (doSave) {
1552 canvas->save();
1553 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001554 }
1555 }
1556 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001557 if (fCanvas) {
1558 fCanvas->restoreToCount(fSaveCount);
1559 }
1560 }
1561
1562 /**
1563 * Perform the restore now, instead of waiting for the destructor. Will
1564 * only do this once.
1565 */
1566 void restore() {
1567 if (fCanvas) {
1568 fCanvas->restoreToCount(fSaveCount);
1569 fCanvas = NULL;
1570 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001571 }
1572
1573private:
1574 SkCanvas* fCanvas;
1575 int fSaveCount;
1576};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001577#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001578
fmalitac3b589a2014-06-05 12:40:07 -07001579class SkCanvasClipVisitor {
1580public:
1581 virtual ~SkCanvasClipVisitor();
1582 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
1583 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
1584 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1585};
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001586
reed@android.com8a1c16f2008-12-17 15:59:43 +00001587#endif