blob: d28d0f18982292a0c4294cd032db3590ad4cad50 [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"
vjiaoblack95302da2016-07-21 10:25:54 -070020#include "SkLights.h"
vjiaoblacke6f5d562016-08-25 06:30:23 -070021#include "../private/SkShadowParams.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000022
bungemand3ebb482015-08-05 13:57:49 -070023class GrContext;
robertphillips175dd9b2016-04-28 14:32:04 -070024class GrDrawContext;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000025class SkBaseDevice;
reed6a070dc2014-11-11 19:36:09 -080026class SkCanvasClipVisitor;
bungemand3ebb482015-08-05 13:57:49 -070027class SkClipStack;
reedf70b5312016-03-04 16:36:20 -080028class SkData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000029class SkDraw;
reed3cb38402015-02-06 08:36:15 -080030class SkDrawable;
reed@android.com8a1c16f2008-12-17 15:59:43 +000031class SkDrawFilter;
bungemand3ebb482015-08-05 13:57:49 -070032class SkImageFilter;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000033class SkMetaData;
bungemand3ebb482015-08-05 13:57:49 -070034class SkPath;
reed@android.com8a1c16f2008-12-17 15:59:43 +000035class SkPicture;
bungemand3ebb482015-08-05 13:57:49 -070036class SkPixmap;
reed1e7f5e72016-04-27 07:49:17 -070037class SkRasterClip;
reed@google.com4ed0fb72012-12-12 20:48:18 +000038class SkRRect;
reed71c3c762015-06-24 10:29:17 -070039struct SkRSXform;
reed@google.com76f10a32014-02-05 15:32:21 +000040class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000041class SkSurface_Base;
fmalita00d5c2c2014-08-21 08:53:26 -070042class SkTextBlob;
reedfa35f8e2014-09-04 12:14:36 -070043
reed@android.com8a1c16f2008-12-17 15:59:43 +000044/** \class SkCanvas
45
46 A Canvas encapsulates all of the state about drawing into a device (bitmap).
47 This includes a reference to the device itself, and a stack of matrix/clip
48 values. For any given draw call (e.g. drawRect), the geometry of the object
49 being drawn is transformed by the concatenation of all the matrices in the
50 stack. The transformed geometry is clipped by the intersection of all of
51 the clips in the stack.
52
53 While the Canvas holds the state of the drawing device, the state (style)
54 of the object being drawn is held by the Paint, which is provided as a
55 parameter to each of the draw() methods. The Paint holds attributes such as
56 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
57 etc.
58*/
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000059class SK_API SkCanvas : public SkRefCnt {
reedbada1882015-12-21 13:09:44 -080060 enum PrivateSaveLayerFlags {
caryclark952538e2016-02-26 05:01:42 -080061 kDontClipToLayer_PrivateSaveLayerFlag = 1U << 31,
reedbada1882015-12-21 13:09:44 -080062 };
63
reed@android.com8a1c16f2008-12-17 15:59:43 +000064public:
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000065 /**
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000066 * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
67 * specified pixels. To access the pixels after drawing to them, the caller should call
68 * flush() or call peekPixels(...).
69 *
70 * On failure, return NULL. This can fail for several reasons:
71 * 1. invalid ImageInfo (e.g. negative dimensions)
72 * 2. unsupported ImageInfo for a canvas
73 * - kUnknown_SkColorType, kIndex_8_SkColorType
reed44977482015-02-27 10:23:00 -080074 * - kUnknown_SkAlphaType
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000075 * - this list is not complete, so others may also be unsupported
76 *
77 * Note: it is valid to request a supported ImageInfo, but with zero
78 * dimensions.
79 */
80 static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t);
81
82 static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
83 return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
84 }
85
86 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000087 * Creates an empty canvas with no backing device/pixels, and zero
88 * dimensions.
89 */
reed@google.comcde92112011-07-06 20:00:52 +000090 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +000091
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000092 /**
93 * Creates a canvas of the specified dimensions, but explicitly not backed
94 * by any device/pixels. Typically this use used by subclasses who handle
95 * the draw calls in some other way.
96 */
reed96a857e2015-01-25 10:33:58 -080097 SkCanvas(int width, int height, const SkSurfaceProps* = NULL);
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000098
reed@google.com6dc74552011-07-21 18:00:46 +000099 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000100
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000101 @param device Specifies a device for the canvas to draw into.
102 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000103 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000104
reed@google.com44699382013-10-31 17:28:30 +0000105 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106 @param bitmap Specifies a bitmap for the canvas to draw into. Its
107 structure are copied to the canvas.
108 */
109 explicit SkCanvas(const SkBitmap& bitmap);
fmalita3d91aad2015-02-02 05:25:04 -0800110
111 /** Construct a canvas with the specified bitmap to draw into.
112 @param bitmap Specifies a bitmap for the canvas to draw into. Its
113 structure are copied to the canvas.
114 @param props New canvas surface properties.
115 */
116 SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
117
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118 virtual ~SkCanvas();
119
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000120 SkMetaData& getMetaData();
121
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000122 /**
123 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
124 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
125 */
126 SkImageInfo imageInfo() const;
127
brianosman898235c2016-04-06 07:38:23 -0700128 /**
129 * If the canvas is backed by pixels (cpu or gpu), this writes a copy of the SurfaceProps
130 * for the canvas to the location supplied by the caller, and returns true. Otherwise,
131 * return false and leave the supplied props unchanged.
132 */
133 bool getProps(SkSurfaceProps*) const;
134
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135 ///////////////////////////////////////////////////////////////////////////
136
reed@google.com210ce002011-11-01 14:24:23 +0000137 /**
bsalomone63ffef2016-02-05 07:17:34 -0800138 * Trigger the immediate execution of all pending draw operations. For the GPU
139 * backend this will resolve all rendering to the GPU surface backing the
140 * SkSurface that owns this canvas.
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000141 */
142 void flush();
143
144 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000145 * Gets the size of the base or root layer in global canvas coordinates. The
146 * origin of the base layer is always (0,0). The current drawable area may be
147 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000148 */
tomhudson68260fa2015-03-23 07:22:40 -0700149 virtual SkISize getBaseLayerSize() const;
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000150
151 /**
152 * DEPRECATED: call getBaseLayerSize
153 */
154 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000155
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000156 /**
157 * DEPRECATED.
158 * Return the canvas' device object, which may be null. The device holds
159 * the bitmap of the pixels that the canvas draws into. The reference count
160 * of the returned device is not changed by this call.
161 */
reed52d9ac62014-06-30 09:05:34 -0700162#ifndef SK_SUPPORT_LEGACY_GETDEVICE
163protected: // Can we make this private?
164#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000165 SkBaseDevice* getDevice() const;
reed52d9ac62014-06-30 09:05:34 -0700166public:
reed41e010c2015-06-09 12:16:53 -0700167 SkBaseDevice* getDevice_just_for_deprecated_compatibility_testing() const {
168 return this->getDevice();
169 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170
reed@google.com9266fed2011-03-30 00:18:03 +0000171 /**
172 * saveLayer() can create another device (which is later drawn onto
173 * the previous device). getTopDevice() returns the top-most device current
174 * installed. Note that this can change on other calls like save/restore,
175 * so do not access this device after subsequent canvas calls.
176 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000177 *
178 * @param updateMatrixClip If this is true, then before the device is
179 * returned, we ensure that its has been notified about the current
180 * matrix and clip. Note: this happens automatically when the device
181 * is drawn to, but is optional here, as there is a small perf hit
182 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000183 */
reed@google.com9c135db2014-03-12 18:28:35 +0000184#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
185private:
186#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000187 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000188public:
reed@google.com9266fed2011-03-30 00:18:03 +0000189
reed@google.com76f10a32014-02-05 15:32:21 +0000190 /**
191 * Create a new surface matching the specified info, one that attempts to
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000192 * be maximally compatible when used with this canvas. If there is no matching Surface type,
193 * NULL is returned.
reed4a8126e2014-09-22 07:29:03 -0700194 *
195 * If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
196 * inherits the properties of the surface that owns this canvas. If this canvas has no parent
197 * surface, then the new surface is created with default properties.
reed@google.com76f10a32014-02-05 15:32:21 +0000198 */
reede8f30622016-03-23 18:59:25 -0700199 sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps* = nullptr);
200#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
201 SkSurface* newSurface(const SkImageInfo& info, const SkSurfaceProps* props = NULL);
202#endif
bsalomon@google.come97f0852011-06-17 13:10:25 +0000203
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000204 /**
205 * Return the GPU context of the device that is associated with the canvas.
206 * For a canvas with non-GPU device, NULL is returned.
207 */
208 GrContext* getGrContext();
209
reed@google.com4b226022011-01-11 18:32:13 +0000210 ///////////////////////////////////////////////////////////////////////////
211
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000212 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000213 * If the canvas has writable pixels in its top layer (and is not recording to a picture
214 * or other non-raster target) and has direct access to its pixels (i.e. they are in
215 * local RAM) return the address of those pixels, and if not null,
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000216 * return the ImageInfo, rowBytes and origin. The returned address is only valid
reed@google.com9c135db2014-03-12 18:28:35 +0000217 * while the canvas object is in scope and unchanged. Any API calls made on
218 * canvas (or its parent surface if any) will invalidate the
219 * returned address (and associated information).
220 *
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000221 * On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
reed@google.com9c135db2014-03-12 18:28:35 +0000222 */
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000223 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
reed@google.com9c135db2014-03-12 18:28:35 +0000224
225 /**
226 * If the canvas has readable pixels in its base layer (and is not recording to a picture
227 * or other non-raster target) and has direct access to its pixels (i.e. they are in
reed6ceeebd2016-03-09 14:26:26 -0800228 * local RAM) return true, and if not null, return in the pixmap parameter information about
229 * the pixels. The pixmap's pixel address is only valid
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000230 * while the canvas object is in scope and unchanged. Any API calls made on
reed6ceeebd2016-03-09 14:26:26 -0800231 * canvas (or its parent surface if any) will invalidate the pixel address
232 * (and associated information).
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000233 *
reed6ceeebd2016-03-09 14:26:26 -0800234 * On failure, returns false and the pixmap parameter will be ignored.
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000235 */
reed6ceeebd2016-03-09 14:26:26 -0800236 bool peekPixels(SkPixmap*);
237
238#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000239 const void* peekPixels(SkImageInfo* info, size_t* rowBytes);
reed6ceeebd2016-03-09 14:26:26 -0800240#endif
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000241
reed@google.com4b226022011-01-11 18:32:13 +0000242 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000243 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
244 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
reedb184f7f2014-07-13 04:32:32 -0700245 * starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000246 *
reedb184f7f2014-07-13 04:32:32 -0700247 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000248 *
reedb184f7f2014-07-13 04:32:32 -0700249 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000250 *
reedb184f7f2014-07-13 04:32:32 -0700251 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
252 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
253 * corresponding src pixels, performing any colortype/alphatype transformations needed
254 * (in the case where the src and dst have different colortypes or alphatypes).
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000255 *
256 * This call can fail, returning false, for several reasons:
reedb184f7f2014-07-13 04:32:32 -0700257 * - If srcR does not intersect the base-layer bounds.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000258 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
259 * - If this canvas is not backed by pixels (e.g. picture or PDF)
260 */
reedb184f7f2014-07-13 04:32:32 -0700261 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
262 int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000263
264 /**
265 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
266 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
267 * it calls through to readPixels(info, ...) and returns its result.
268 */
reedb184f7f2014-07-13 04:32:32 -0700269 bool readPixels(SkBitmap* bitmap, int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000270
271 /**
272 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
273 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
274 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
275 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000276 */
277 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000278
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000279 /**
280 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
281 * ignoring the matrix and clip.
282 *
283 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
284 *
285 * target.setXYWH(x, y, info.width(), info.height());
286 *
287 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
288 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
289 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
290 * pixels, performing any colortype/alphatype transformations needed (in the case where the
291 * src and dst have different colortypes or alphatypes).
292 *
293 * This call can fail, returning false, for several reasons:
294 * - If the src colortype/alphatype cannot be converted to the canvas' types
295 * - If this canvas is not backed by pixels (e.g. picture or PDF)
296 */
297 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
298
299 /**
300 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
301 * is just wrapping a texture, returns false and does nothing.
302 */
303 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000304
reed@android.com8a1c16f2008-12-17 15:59:43 +0000305 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000306
reed@android.comdc3381f2010-02-11 16:05:15 +0000307 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000308 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000309 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
310 operate on this copy.
311 When the balancing call to restore() is made, the previous matrix, clip,
312 and drawFilter are restored.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000313
314 @return The value to pass to restoreToCount() to balance this save()
315 */
316 int save();
317
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318 /** This behaves the same as save(), but in addition it allocates an
319 offscreen bitmap. All drawing calls are directed there, and only when
320 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000321 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000322 @param bounds (may be null) This rect, if non-null, is used as a hint to
323 limit the size of the offscreen, and thus drawing may be
324 clipped to it, though that clipping is not guaranteed to
325 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000326 @param paint (may be null) This is copied, and is applied to the
327 offscreen when restore() is called
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000328 @return The value to pass to restoreToCount() to balance this save()
329 */
330 int saveLayer(const SkRect* bounds, const SkPaint* paint);
reed021f6312015-08-09 19:41:13 -0700331 int saveLayer(const SkRect& bounds, const SkPaint* paint) {
332 return this->saveLayer(&bounds, paint);
333 }
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000334
reed70ee31b2015-12-10 13:44:45 -0800335 /**
336 * Temporary name.
337 * Will allow any requests for LCD text to be respected, so the caller must be careful to
338 * only draw on top of opaque sections of the layer to get good results.
339 */
340 int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
341
reed@android.com8a1c16f2008-12-17 15:59:43 +0000342 /** This behaves the same as save(), but in addition it allocates an
343 offscreen bitmap. All drawing calls are directed there, and only when
344 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000345 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000346 @param bounds (may be null) This rect, if non-null, is used as a hint to
347 limit the size of the offscreen, and thus drawing may be
348 clipped to it, though that clipping is not guaranteed to
349 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 @param alpha This is applied to the offscreen when restore() is called.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000351 @return The value to pass to restoreToCount() to balance this save()
352 */
353 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
354
reed4960eee2015-12-18 07:09:18 -0800355 enum {
356 kIsOpaque_SaveLayerFlag = 1 << 0,
357 kPreserveLCDText_SaveLayerFlag = 1 << 1,
reedbada1882015-12-21 13:09:44 -0800358
359#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
360 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
361#endif
reed4960eee2015-12-18 07:09:18 -0800362 };
363 typedef uint32_t SaveLayerFlags;
364
365 struct SaveLayerRec {
reedbfd5f172016-01-07 11:28:08 -0800366 SaveLayerRec()
367 : fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
368 {}
reed4960eee2015-12-18 07:09:18 -0800369 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
370 : fBounds(bounds)
371 , fPaint(paint)
reedbfd5f172016-01-07 11:28:08 -0800372 , fBackdrop(nullptr)
373 , fSaveLayerFlags(saveLayerFlags)
374 {}
375 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
376 SaveLayerFlags saveLayerFlags)
377 : fBounds(bounds)
378 , fPaint(paint)
379 , fBackdrop(backdrop)
reed4960eee2015-12-18 07:09:18 -0800380 , fSaveLayerFlags(saveLayerFlags)
381 {}
382
reedbfd5f172016-01-07 11:28:08 -0800383 const SkRect* fBounds; // optional
384 const SkPaint* fPaint; // optional
385 const SkImageFilter* fBackdrop; // optional
386 SaveLayerFlags fSaveLayerFlags;
reed4960eee2015-12-18 07:09:18 -0800387 };
388
389 int saveLayer(const SaveLayerRec&);
390
reed@android.com8a1c16f2008-12-17 15:59:43 +0000391 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000392 modifications to the matrix/clip/drawFilter state since the last save
393 call.
394 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000395 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000396 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000397
398 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000399 This will equal # save() calls - # restore() calls + 1. The save count on
400 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000401 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000402 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000403
404 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000405 count reached saveCount. It is an error for saveCount to be greater than
406 getSaveCount(). To pop all the way back to the initial matrix/clip context
407 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000408 @param saveCount The number of save() levels to restore from
409 */
410 void restoreToCount(int saveCount);
411
412 /** Preconcat the current matrix with the specified translation
413 @param dx The distance to translate in X
414 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000415 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000416 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000417
418 /** Preconcat the current matrix with the specified scale.
419 @param sx The amount to scale in X
420 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000421 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000422 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423
bungeman7438bfc2016-07-12 15:01:19 -0700424 /** Preconcat the current matrix with the specified rotation about the origin.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000425 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000426 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000427 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000428
bungeman7438bfc2016-07-12 15:01:19 -0700429 /** Preconcat the current matrix with the specified rotation about a given point.
430 @param degrees The amount to rotate, in degrees
431 @param px The x coordinate of the point to rotate about.
432 @param py The y coordinate of the point to rotate about.
433 */
434 void rotate(SkScalar degrees, SkScalar px, SkScalar py);
435
reed@android.com8a1c16f2008-12-17 15:59:43 +0000436 /** Preconcat the current matrix with the specified skew.
437 @param sx The amount to skew in X
438 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000439 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000440 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000441
442 /** Preconcat the current matrix with the specified matrix.
443 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000444 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000445 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000446
reed@android.com8a1c16f2008-12-17 15:59:43 +0000447 /** Replace the current matrix with a copy of the specified matrix.
448 @param matrix The matrix that will be copied into the current matrix.
449 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000450 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000451
reed@android.com8a1c16f2008-12-17 15:59:43 +0000452 /** Helper for setMatrix(identity). Sets the current matrix to identity.
453 */
454 void resetMatrix();
455
vjiaoblack95302da2016-07-21 10:25:54 -0700456#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -0700457 /** Add the specified translation to the current draw depth of the canvas.
458 @param z The distance to translate in Z.
459 Negative into screen, positive out of screen.
460 Without translation, the draw depth defaults to 0.
461 */
462 void translateZ(SkScalar z);
463
vjiaoblack95302da2016-07-21 10:25:54 -0700464 /** Set the current set of lights in the canvas.
465 @param lights The lights that we want the canvas to have.
466 */
467 void setLights(sk_sp<SkLights> lights);
468
469 /** Returns the current set of lights the canvas uses
470 */
471 sk_sp<SkLights> getLights() const;
472#endif
473
reed@google.com4ed0fb72012-12-12 20:48:18 +0000474 /**
475 * Modify the current clip with the specified rectangle.
476 * @param rect The rect to combine with the current clip
477 * @param op The region op to apply to the current clip
478 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000479 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000480 void clipRect(const SkRect& rect,
481 SkRegion::Op op = SkRegion::kIntersect_Op,
482 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000483
reed@google.com4ed0fb72012-12-12 20:48:18 +0000484 /**
485 * Modify the current clip with the specified SkRRect.
486 * @param rrect The rrect to combine with the current clip
487 * @param op The region op to apply to the current clip
488 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000489 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000490 void clipRRect(const SkRRect& rrect,
491 SkRegion::Op op = SkRegion::kIntersect_Op,
492 bool doAntiAlias = false);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000493
494 /**
495 * Modify the current clip with the specified path.
496 * @param path The path to combine with the current clip
497 * @param op The region op to apply to the current clip
498 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000499 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000500 void clipPath(const SkPath& path,
501 SkRegion::Op op = SkRegion::kIntersect_Op,
502 bool doAntiAlias = false);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000503
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000504 /** EXPERIMENTAL -- only used for testing
505 Set to false to force clips to be hard, even if doAntiAlias=true is
506 passed to clipRect or clipPath.
507 */
508 void setAllowSoftClip(bool allow) {
509 fAllowSoftClip = allow;
510 }
511
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000512 /** EXPERIMENTAL -- only used for testing
513 Set to simplify clip stack using path ops.
514 */
515 void setAllowSimplifyClip(bool allow) {
516 fAllowSimplifyClip = allow;
517 }
518
reed@android.com8a1c16f2008-12-17 15:59:43 +0000519 /** Modify the current clip with the specified region. Note that unlike
520 clipRect() and clipPath() which transform their arguments by the current
521 matrix, clipRegion() assumes its argument is already in device
522 coordinates, and so no transformation is performed.
523 @param deviceRgn The region to apply to the current clip
mtklein6e998e62016-07-13 09:03:48 -0700524 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000525 */
commit-bot@chromium.org759cf482014-03-06 13:18:07 +0000526 void clipRegion(const SkRegion& deviceRgn,
527 SkRegion::Op op = SkRegion::kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000528
529 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the
530 specified region. This does not intersect or in any other way account
531 for the existing clip region.
532 @param deviceRgn The region to copy into the current clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000533 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000534 void setClipRegion(const SkRegion& deviceRgn) {
535 this->clipRegion(deviceRgn, SkRegion::kReplace_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000536 }
537
reed@android.com8a1c16f2008-12-17 15:59:43 +0000538 /** Return true if the specified rectangle, after being transformed by the
539 current matrix, would lie completely outside of the current clip. Call
540 this to check if an area you intend to draw into is clipped out (and
541 therefore you can skip making the draw calls).
542 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000543 @return true if the rect (transformed by the canvas' matrix) does not
544 intersect with the canvas' clip
545 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000546 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000547
548 /** Return true if the specified path, after being transformed by the
549 current matrix, would lie completely outside of the current clip. Call
550 this to check if an area you intend to draw into is clipped out (and
551 therefore you can skip making the draw calls). Note, for speed it may
552 return false even if the path itself might not intersect the clip
553 (i.e. the bounds of the path intersects, but the path does not).
554 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555 @return true if the path (transformed by the canvas' matrix) does not
556 intersect with the canvas' clip
557 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000558 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000559
reed@android.com8a1c16f2008-12-17 15:59:43 +0000560 /** Return the bounds of the current clip (in local coordinates) in the
561 bounds parameter, and return true if it is non-empty. This can be useful
562 in a way similar to quickReject, in that it tells you that drawing
563 outside of these bounds will be clipped out.
564 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000565 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000566
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000567 /** Return the bounds of the current clip, in device coordinates; returns
568 true if non-empty. Maybe faster than getting the clip explicitly and
569 then taking its bounds.
570 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000571 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000572
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000573
reed@android.com8a1c16f2008-12-17 15:59:43 +0000574 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000575 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000576 @param a the alpha component (0..255) of the color to fill the canvas
577 @param r the red component (0..255) of the color to fill the canvas
578 @param g the green component (0..255) of the color to fill the canvas
579 @param b the blue component (0..255) of the color to fill the canvas
580 @param mode the mode to apply the color in (defaults to SrcOver)
581 */
582 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
reed@android.com845fdac2009-06-23 03:01:32 +0000583 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000584
585 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000586 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000587 @param color the color to draw with
588 @param mode the mode to apply the color in (defaults to SrcOver)
589 */
reed8eddfb52014-12-04 07:50:14 -0800590 void drawColor(SkColor color, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000591
reedf4e0d9e2014-12-05 20:49:03 -0800592 /**
593 * Helper method for drawing a color in SRC mode, completely replacing all the pixels
594 * in the current clip with this color.
595 */
596 void clear(SkColor color) {
reed8eddfb52014-12-04 07:50:14 -0800597 this->drawColor(color, SkXfermode::kSrc_Mode);
598 }
reed@google.com2a981812011-04-14 18:59:28 +0000599
600 /**
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000601 * This makes the contents of the canvas undefined. Subsequent calls that
602 * require reading the canvas contents will produce undefined results. Examples
603 * include blending and readPixels. The actual implementation is backend-
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800604 * dependent and one legal implementation is to do nothing. This method
605 * ignores the current clip.
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000606 *
607 * This function should only be called if the caller intends to subsequently
608 * draw to the canvas. The canvas may do real work at discard() time in order
609 * to optimize performance on subsequent draws. Thus, if you call this and then
610 * never draw to the canvas subsequently you may pay a perfomance penalty.
611 */
612 void discard() { this->onDiscard(); }
613
614 /**
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800615 * Fill the entire canvas (restricted to the current clip) with the
reed@google.com2a981812011-04-14 18:59:28 +0000616 * specified paint.
617 * @param paint The paint used to fill the canvas
618 */
reed0846f1b2015-01-09 14:17:40 -0800619 void drawPaint(const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000620
621 enum PointMode {
622 /** drawPoints draws each point separately */
623 kPoints_PointMode,
624 /** drawPoints draws each pair of points as a line segment */
625 kLines_PointMode,
626 /** drawPoints draws the array of points as a polygon */
627 kPolygon_PointMode
628 };
629
630 /** Draw a series of points, interpreted based on the PointMode mode. For
631 all modes, the count parameter is interpreted as the total number of
632 points. For kLine mode, count/2 line segments are drawn.
633 For kPoint mode, each point is drawn centered at its coordinate, and its
634 size is specified by the paint's stroke-width. It draws as a square,
635 unless the paint's cap-type is round, in which the points are drawn as
636 circles.
637 For kLine mode, each pair of points is drawn as a line segment,
638 respecting the paint's settings for cap/join/width.
639 For kPolygon mode, the entire array is drawn as a series of connected
640 line segments.
641 Note that, while similar, kLine and kPolygon modes draw slightly
642 differently than the equivalent path built with a series of moveto,
643 lineto calls, in that the path will draw all of its contours at once,
644 with no interactions if contours intersect each other (think XOR
645 xfermode). drawPoints always draws each element one at a time.
646 @param mode PointMode specifying how to draw the array of points.
647 @param count The number of points in the array
648 @param pts Array of points to draw
649 @param paint The paint used to draw the points
650 */
reed0846f1b2015-01-09 14:17:40 -0800651 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000652
653 /** Helper method for drawing a single point. See drawPoints() for a more
654 details.
655 */
656 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000657
reed@android.com8a1c16f2008-12-17 15:59:43 +0000658 /** Draws a single pixel in the specified color.
659 @param x The X coordinate of which pixel to draw
660 @param y The Y coordiante of which pixel to draw
661 @param color The color to draw
662 */
663 void drawPoint(SkScalar x, SkScalar y, SkColor color);
664
665 /** Draw a line segment with the specified start and stop x,y coordinates,
666 using the specified paint. NOTE: since a line is always "framed", the
667 paint's Style is ignored.
668 @param x0 The x-coordinate of the start point of the line
669 @param y0 The y-coordinate of the start point of the line
670 @param x1 The x-coordinate of the end point of the line
671 @param y1 The y-coordinate of the end point of the line
672 @param paint The paint used to draw the line
673 */
674 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
675 const SkPaint& paint);
676
677 /** Draw the specified rectangle using the specified paint. The rectangle
678 will be filled or stroked based on the Style in the paint.
679 @param rect The rect to be drawn
680 @param paint The paint used to draw the rect
681 */
reed0846f1b2015-01-09 14:17:40 -0800682 void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000683
684 /** Draw the specified rectangle using the specified paint. The rectangle
685 will be filled or framed based on the Style in the paint.
686 @param rect The rect to be drawn
687 @param paint The paint used to draw the rect
688 */
reed@google.com87001ed2014-02-17 16:28:05 +0000689 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000690 SkRect r;
691 r.set(rect); // promotes the ints to scalars
692 this->drawRect(r, paint);
693 }
reed@google.com4b226022011-01-11 18:32:13 +0000694
reed@android.com8a1c16f2008-12-17 15:59:43 +0000695 /** Draw the specified rectangle using the specified paint. The rectangle
696 will be filled or framed based on the Style in the paint.
697 @param left The left side of the rectangle to be drawn
698 @param top The top side of the rectangle to be drawn
699 @param right The right side of the rectangle to be drawn
700 @param bottom The bottom side of the rectangle to be drawn
701 @param paint The paint used to draw the rect
702 */
703 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
704 SkScalar bottom, const SkPaint& paint);
705
msarett44df6512016-08-25 13:54:30 -0700706 /** Draw the outline of the specified region using the specified paint.
707 @param region The region to be drawn
708 @param paint The paint used to draw the region
709 */
msarettdca352e2016-08-26 06:37:45 -0700710 void drawRegion(const SkRegion& region, const SkPaint& paint);
msarett44df6512016-08-25 13:54:30 -0700711
reed@android.com8a1c16f2008-12-17 15:59:43 +0000712 /** 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
bsalomon21af9ca2016-08-25 12:29:23 -0700746 specified oval. Sweep angles are not treated as modulo 360 and thus can
747 exceed a full sweep of the oval. Note that this differs slightly from
748 SkPath::arcTo, which treats the sweep angle mod 360. If the oval is empty
749 or the sweep angle is zero nothing is drawn. If useCenter is true the oval
750 center is inserted into the implied path before the arc and the path is
751 closed back to the, center forming a wedge. Otherwise, the implied path
752 contains just the arc and is not closed.
bsalomonac3aa242016-08-19 11:25:19 -0700753 @param oval The bounds of oval used to define the shape of the arc.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000754 @param startAngle Starting angle (in degrees) where the arc begins
bsalomonac3aa242016-08-19 11:25:19 -0700755 @param sweepAngle Sweep angle (in degrees) measured clockwise.
bsalomon21af9ca2016-08-25 12:29:23 -0700756 @param useCenter true means include the center of the oval.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000757 @param paint The paint used to draw the arc
758 */
759 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
760 bool useCenter, const SkPaint& paint);
761
762 /** Draw the specified round-rect using the specified paint. The round-rect
763 will be filled or framed based on the Style in the paint.
764 @param rect The rectangular bounds of the roundRect to be drawn
765 @param rx The x-radius of the oval used to round the corners
766 @param ry The y-radius of the oval used to round the corners
767 @param paint The paint used to draw the roundRect
768 */
769 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
770 const SkPaint& paint);
771
772 /** Draw the specified path using the specified paint. The path will be
773 filled or framed based on the Style in the paint.
774 @param path The path to be drawn
775 @param paint The paint used to draw the path
776 */
reed0846f1b2015-01-09 14:17:40 -0800777 void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000778
piotaixrd52893c2014-09-25 14:39:40 -0700779 /** Draw the specified image, with its top/left corner at (x,y), using the
780 specified paint, transformed by the current matrix.
781
782 @param image The image to be drawn
783 @param left The position of the left side of the image being drawn
784 @param top The position of the top side of the image being drawn
785 @param paint The paint used to draw the image, or NULL
786 */
reed0846f1b2015-01-09 14:17:40 -0800787 void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
reedf8053da2016-03-17 08:14:57 -0700788 void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
789 const SkPaint* paint = NULL) {
790 this->drawImage(image.get(), left, top, paint);
791 }
piotaixrb5fae932014-09-24 13:03:30 -0700792
reeda5517e22015-07-14 10:54:12 -0700793 /**
794 * Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
795 * trading off speed for exactness.
796 *
797 * When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
798 * the pixels in the image. If there is a src-rect specified, it is intended to restrict the
799 * pixels that will be read. However, for performance reasons, some implementations may slow
800 * down if they cannot read 1-pixel past the src-rect boundary at times.
801 *
802 * This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
803 * If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
804 * must be strictly respected, the caller should pass kStrict.
805 */
806 enum SrcRectConstraint {
807 /**
808 * If kStrict is specified, the implementation must respect the src-rect
809 * (if specified) strictly, and will never sample outside of those bounds during sampling
810 * even when filtering. This may be slower than kFast.
811 */
812 kStrict_SrcRectConstraint,
813
814 /**
815 * If kFast is specified, the implementation may sample outside of the src-rect
bsalomon19e82e32015-10-23 09:27:42 -0700816 * (if specified) by half the width of filter. This allows greater flexibility
reeda5517e22015-07-14 10:54:12 -0700817 * to the implementation and can make the draw much faster.
818 */
819 kFast_SrcRectConstraint,
820 };
821
822 /** Draw the specified image, scaling and translating so that it fills the specified
823 * dst rect. If the src rect is non-null, only that subset of the image is transformed
824 * and drawn.
825 *
826 * @param image The image to be drawn
827 * @param src Optional: specify the subset of the image to be drawn
828 * @param dst The destination rectangle where the scaled/translated
829 * image will be drawn
830 * @param paint The paint used to draw the image, or NULL
831 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
832 */
reede47829b2015-08-06 10:02:53 -0700833 void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
834 const SkPaint* paint,
835 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
836 // variant that takes src SkIRect
837 void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
838 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
839 // variant that assumes src == image-bounds
reede47829b2015-08-06 10:02:53 -0700840 void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
841 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700842
reedf8053da2016-03-17 08:14:57 -0700843 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
844 const SkPaint* paint,
845 SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
846 this->drawImageRect(image.get(), src, dst, paint, constraint);
847 }
848 void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
849 const SkPaint* paint, SrcRectConstraint cons = kStrict_SrcRectConstraint) {
850 this->drawImageRect(image.get(), isrc, dst, paint, cons);
851 }
852 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
853 SrcRectConstraint cons = kStrict_SrcRectConstraint) {
854 this->drawImageRect(image.get(), dst, paint, cons);
855 }
856
reed4c21dc52015-06-25 12:32:03 -0700857 /**
858 * Draw the image stretched differentially to fit into dst.
859 * center is a rect within the image, and logically divides the image
860 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
861 * image is the "center", then the center-rect should be [2, 2, 3, 3].
862 *
863 * If the dst is >= the image size, then...
864 * - The 4 corners are not stretched at all.
865 * - The sides are stretched in only one axis.
866 * - The center is stretched in both axes.
867 * Else, for each axis where dst < image,
868 * - The corners shrink proportionally
869 * - The sides (along the shrink axis) and center are not drawn
870 */
871 void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
reedf8053da2016-03-17 08:14:57 -0700872 const SkPaint* paint = nullptr);
873 void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
874 const SkPaint* paint = nullptr) {
875 this->drawImageNine(image.get(), center, dst, paint);
876 }
reed4c21dc52015-06-25 12:32:03 -0700877
reed@android.com8a1c16f2008-12-17 15:59:43 +0000878 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
879 specified paint, transformed by the current matrix. Note: if the paint
880 contains a maskfilter that generates a mask which extends beyond the
881 bitmap's original width/height, then the bitmap will be drawn as if it
882 were in a Shader with CLAMP mode. Thus the color outside of the original
883 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000884
885 If a shader is present on the paint it will be ignored, except in the
reed@google.comf20fc242014-03-26 13:44:58 +0000886 case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000887 generated by the shader.
888
reed@android.com8a1c16f2008-12-17 15:59:43 +0000889 @param bitmap The bitmap to be drawn
890 @param left The position of the left side of the bitmap being drawn
891 @param top The position of the top side of the bitmap being drawn
892 @param paint The paint used to draw the bitmap, or NULL
893 */
reed0846f1b2015-01-09 14:17:40 -0800894 void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
895 const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000896
reeda5517e22015-07-14 10:54:12 -0700897 /** Draw the specified bitmap, scaling and translating so that it fills the specified
898 * dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
899 * and drawn.
900 *
901 * @param bitmap The bitmap to be drawn
902 * @param src Optional: specify the subset of the bitmap to be drawn
903 * @param dst The destination rectangle where the scaled/translated
904 * bitmap will be drawn
905 * @param paint The paint used to draw the bitmap, or NULL
906 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
907 */
reede47829b2015-08-06 10:02:53 -0700908 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
reed84984ef2015-07-17 07:09:43 -0700909 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700910 // variant where src is SkIRect
reed84984ef2015-07-17 07:09:43 -0700911 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
912 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700913 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
bsalomon19e82e32015-10-23 09:27:42 -0700914 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700915
reed@google.comf0b5e112011-09-07 11:57:34 +0000916 /**
msarettc573a402016-08-02 08:05:56 -0700917 * Draw the bitmap stretched or shrunk differentially to fit into dst.
reed@google.comf0b5e112011-09-07 11:57:34 +0000918 * center is a rect within the bitmap, and logically divides the bitmap
919 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
920 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
921 *
922 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000923 * - The 4 corners are not stretched at all.
924 * - The sides are stretched in only one axis.
925 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000926 * Else, for each axis where dst < bitmap,
927 * - The corners shrink proportionally
928 * - The sides (along the shrink axis) and center are not drawn
929 */
reed0846f1b2015-01-09 14:17:40 -0800930 void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
931 const SkPaint* paint = NULL);
reed@google.comf0b5e112011-09-07 11:57:34 +0000932
msarettc573a402016-08-02 08:05:56 -0700933 /**
934 * Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
935 */
936 struct Lattice {
msarett0764efe2016-09-02 11:24:30 -0700937 enum Flags : uint8_t {
938 // If set, indicates that we should not draw corresponding rect.
939 kTransparent_Flags = 1 << 0,
940 };
msarettc573a402016-08-02 08:05:56 -0700941
msarett0764efe2016-09-02 11:24:30 -0700942 // An array of x-coordinates that divide the bitmap vertically.
943 // These must be unique, increasing, and in the set [0, width).
944 // Does not have ownership.
945 const int* fXDivs;
msarettc573a402016-08-02 08:05:56 -0700946
947 // An array of y-coordinates that divide the bitmap horizontally.
msarett0764efe2016-09-02 11:24:30 -0700948 // These must be unique, increasing, and in the set [0, height).
msarettc573a402016-08-02 08:05:56 -0700949 // Does not have ownership.
msarett0764efe2016-09-02 11:24:30 -0700950 const int* fYDivs;
951
952 // If non-null, the length of this array must be equal to
953 // (fXCount + 1) * (fYCount + 1). Note that we allow the first rect
954 // in each direction to empty (divs[0] = 0). In this case, the
955 // caller still must specify a flag (as a placeholder) for these
956 // empty rects.
957 // The flags correspond to the rects in the lattice, first moving
958 // left to right and then top to bottom.
959 const Flags* fFlags;
960
961 // The number of fXDivs.
962 int fXCount;
msarettc573a402016-08-02 08:05:56 -0700963
964 // The number of fYDivs.
msarett0764efe2016-09-02 11:24:30 -0700965 int fYCount;
msarettc573a402016-08-02 08:05:56 -0700966 };
967
968 /**
969 * Draw the bitmap stretched or shrunk differentially to fit into dst.
970 *
971 * Moving horizontally across the bitmap, alternating rects will be "scalable"
972 * (in the x-dimension) to fit into dst or must be left "fixed". The first rect
973 * is treated as "fixed", but it's possible to specify an empty first rect by
974 * making lattice.fXDivs[0] = 0.
975 *
976 * The scale factor for all "scalable" rects will be the same, and may be greater
977 * than or less than 1 (meaning we can stretch or shrink). If the number of
978 * "fixed" pixels is greater than the width of the dst, we will collapse all of
979 * the "scalable" regions and appropriately downscale the "fixed" regions.
980 *
981 * The same interpretation also applies to the y-dimension.
982 */
983 void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
984 const SkPaint* paint = nullptr);
985 void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
986 const SkPaint* paint = nullptr);
987
reed@android.com8a1c16f2008-12-17 15:59:43 +0000988 /** Draw the text, with origin at (x,y), using the specified paint.
989 The origin is interpreted based on the Align setting in the paint.
990 @param text The text to be drawn
991 @param byteLength The number of bytes to read from the text parameter
992 @param x The x-coordinate of the origin of the text being drawn
993 @param y The y-coordinate of the origin of the text being drawn
994 @param paint The paint used for the text (e.g. color, size, style)
995 */
reedf7430cc2014-12-21 11:38:35 -0800996 void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
997 const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000998
999 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +00001000 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001001 @param text The text to be drawn
1002 @param byteLength The number of bytes to read from the text parameter
1003 @param pos Array of positions, used to position each character
1004 @param paint The paint used for the text (e.g. color, size, style)
1005 */
reedf7430cc2014-12-21 11:38:35 -08001006 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
1007 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +00001008
reed@android.com8a1c16f2008-12-17 15:59:43 +00001009 /** Draw the text, with each character/glyph origin specified by the x
1010 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +00001011 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001012 @param text The text to be drawn
1013 @param byteLength The number of bytes to read from the text parameter
1014 @param xpos Array of x-positions, used to position each character
1015 @param constY The shared Y coordinate for all of the positions
1016 @param paint The paint used for the text (e.g. color, size, style)
1017 */
reedf7430cc2014-12-21 11:38:35 -08001018 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
1019 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +00001020
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021 /** Draw the text, with origin at (x,y), using the specified paint, along
1022 the specified path. The paint's Align setting determins where along the
1023 path to start the text.
1024 @param text The text to be drawn
1025 @param byteLength The number of bytes to read from the text parameter
1026 @param path The path the text should follow for its baseline
1027 @param hOffset The distance along the path to add to the text's
1028 starting position
1029 @param vOffset The distance above(-) or below(+) the path to
1030 position the text
1031 @param paint The paint used for the text
1032 */
reedf7430cc2014-12-21 11:38:35 -08001033 void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
reed@android.com8a1c16f2008-12-17 15:59:43 +00001034 SkScalar vOffset, const SkPaint& paint);
1035
1036 /** Draw the text, with origin at (x,y), using the specified paint, along
1037 the specified path. The paint's Align setting determins where along the
1038 path to start the text.
1039 @param text The text to be drawn
1040 @param byteLength The number of bytes to read from the text parameter
1041 @param path The path the text should follow for its baseline
1042 @param matrix (may be null) Applied to the text before it is
1043 mapped onto the path
1044 @param paint The paint used for the text
1045 */
reedf7430cc2014-12-21 11:38:35 -08001046 void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
1047 const SkMatrix* matrix, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001048
reed45561a02016-07-07 12:47:17 -07001049 /**
1050 * Draw the text with each character/glyph individually transformed by its xform.
1051 * If cullRect is not null, it is a conservative bounds of what will be drawn
reed63f30d92016-07-07 16:32:51 -07001052 * taking into account the xforms and the paint, and will be used to accelerate culling.
reed45561a02016-07-07 12:47:17 -07001053 */
1054 void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
1055 const SkRect* cullRect, const SkPaint& paint);
1056
fmalita00d5c2c2014-08-21 08:53:26 -07001057 /** Draw the text blob, offset by (x,y), using the specified paint.
1058 @param blob The text blob to be drawn
1059 @param x The x-offset of the text being drawn
1060 @param y The y-offset of the text being drawn
1061 @param paint The paint used for the text (e.g. color, size, style)
1062 */
1063 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
reed2ab90572016-08-10 14:16:41 -07001064 void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
1065 this->drawTextBlob(blob.get(), x, y, paint);
1066 }
fmalita00d5c2c2014-08-21 08:53:26 -07001067
reed@android.com8a1c16f2008-12-17 15:59:43 +00001068 /** Draw the picture into this canvas. This method effective brackets the
1069 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +00001070 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001071 @param picture The recorded drawing commands to playback into this
1072 canvas.
1073 */
reed1c2c4412015-04-30 13:09:24 -07001074 void drawPicture(const SkPicture* picture) {
1075 this->drawPicture(picture, NULL, NULL);
1076 }
reedca2622b2016-03-18 07:25:55 -07001077 void drawPicture(const sk_sp<SkPicture>& picture) {
reedf8053da2016-03-17 08:14:57 -07001078 this->drawPicture(picture.get());
1079 }
robertphillips9b14f262014-06-04 05:40:44 -07001080
reedd5fa1a42014-08-09 11:08:05 -07001081 /**
1082 * Draw the picture into this canvas.
1083 *
1084 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1085 * logically equivalent to
1086 * save/concat/drawPicture/restore
1087 *
1088 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1089 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1090 * This is logically equivalent to
1091 * saveLayer(paint)/drawPicture/restore
1092 */
1093 void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
reedca2622b2016-03-18 07:25:55 -07001094 void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) {
reedf8053da2016-03-17 08:14:57 -07001095 this->drawPicture(picture.get(), matrix, paint);
1096 }
reedd5fa1a42014-08-09 11:08:05 -07001097
vjiaoblack95302da2016-07-21 10:25:54 -07001098#ifdef SK_EXPERIMENTAL_SHADOWING
1099 /**
vjiaoblacke6f5d562016-08-25 06:30:23 -07001100 * Draw the picture into this canvas, with shadows!
vjiaoblack95302da2016-07-21 10:25:54 -07001101 *
1102 * We will use the canvas's lights along with the picture information (draw depths of
1103 * objects, etc) to first create a set of shadowmaps for the light-picture pairs, and
1104 * then use that set of shadowmaps to render the scene with shadows.
1105 *
1106 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1107 * logically equivalent to
1108 * save/concat/drawPicture/restore
1109 *
1110 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1111 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1112 * This is logically equivalent to
1113 * saveLayer(paint)/drawPicture/restore
1114 *
vjiaoblacke6f5d562016-08-25 06:30:23 -07001115 * We also support using variance shadow maps for blurred shadows; the user can specify
1116 * what shadow mapping algorithm to use with params.
1117 * - Variance Shadow Mapping works by storing both the depth and depth^2 in the shadow map.
1118 * - Then, the shadow map can be blurred, and when reading from it, the fragment shader
1119 * can calculate the variance of the depth at a position by doing E(x^2) - E(x)^2.
1120 * - We can then use the depth variance and depth at a fragment to arrive at an upper bound
1121 * of the probability that the current surface is shadowed by using Chebyshev's
1122 * inequality, and then use that to shade the fragment.
1123 *
1124 * - There are a few problems with VSM.
1125 * * Light Bleeding | Areas with high variance, such as near the edges of high up rects,
1126 * will cause their shadow penumbras to overwrite otherwise solid
1127 * shadows.
1128 * * Shape Distortion | We can combat Light Bleeding by biasing the shadow (setting
1129 * mostly shaded fragments to completely shaded) and increasing
1130 * the minimum allowed variance. However, this warps and rounds
1131 * out the shape of the shadow.
vjiaoblack95302da2016-07-21 10:25:54 -07001132 */
1133 void drawShadowedPicture(const SkPicture*,
1134 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -07001135 const SkPaint* paint,
1136 const SkShadowParams& params);
vjiaoblack95302da2016-07-21 10:25:54 -07001137 void drawShadowedPicture(const sk_sp<SkPicture>& picture,
1138 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -07001139 const SkPaint* paint,
1140 const SkShadowParams& params) {
1141 this->drawShadowedPicture(picture.get(), matrix, paint, params);
vjiaoblack95302da2016-07-21 10:25:54 -07001142 }
1143#endif
1144
reed@android.com8a1c16f2008-12-17 15:59:43 +00001145 enum VertexMode {
1146 kTriangles_VertexMode,
1147 kTriangleStrip_VertexMode,
1148 kTriangleFan_VertexMode
1149 };
reed@google.com4b226022011-01-11 18:32:13 +00001150
reed@android.com8a1c16f2008-12-17 15:59:43 +00001151 /** Draw the array of vertices, interpreted as triangles (based on mode).
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001152
1153 If both textures and vertex-colors are NULL, it strokes hairlines with
1154 the paint's color. This behavior is a useful debugging mode to visualize
1155 the mesh.
1156
reed@android.com8a1c16f2008-12-17 15:59:43 +00001157 @param vmode How to interpret the array of vertices
1158 @param vertexCount The number of points in the vertices array (and
1159 corresponding texs and colors arrays if non-null)
1160 @param vertices Array of vertices for the mesh
1161 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +00001162 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001163 @param colors May be null. If not null, specifies a color for each
1164 vertex, to be interpolated across the triangle.
1165 @param xmode Used if both texs and colors are present. In this
1166 case the colors are combined with the texture using mode,
1167 before being drawn using the paint. If mode is null, then
reed@google.com8d3cd7a2013-01-30 21:36:11 +00001168 kModulate_Mode is used.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001169 @param indices If not null, array of indices to reference into the
1170 vertex (texs, colors) array.
1171 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001172 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001173 */
reed0846f1b2015-01-09 14:17:40 -08001174 void drawVertices(VertexMode vmode, int vertexCount,
1175 const SkPoint vertices[], const SkPoint texs[],
1176 const SkColor colors[], SkXfermode* xmode,
1177 const uint16_t indices[], int indexCount,
1178 const SkPaint& paint);
reedcfb6bdf2016-03-29 11:32:50 -07001179 void drawVertices(VertexMode vmode, int vertexCount,
1180 const SkPoint vertices[], const SkPoint texs[],
mtklein92d48832016-04-01 04:55:47 -07001181 const SkColor colors[], const sk_sp<SkXfermode>& xmode,
reedcfb6bdf2016-03-29 11:32:50 -07001182 const uint16_t indices[], int indexCount,
1183 const SkPaint& paint) {
1184 this->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode.get(),
1185 indices, indexCount, paint);
1186 }
mtklein6cfa73a2014-08-13 13:33:49 -07001187
dandovb3c9d1c2014-08-12 08:34:29 -07001188 /**
1189 Draw a cubic coons patch
mtklein6cfa73a2014-08-13 13:33:49 -07001190
dandovb3c9d1c2014-08-12 08:34:29 -07001191 @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1192 starting at the top left corner.
1193 @param colors specifies the colors for the corners which will be bilerp across the patch,
1194 their order is clockwise starting at the top left corner.
mtklein6cfa73a2014-08-13 13:33:49 -07001195 @param texCoords specifies the texture coordinates that will be bilerp across the patch,
dandovb3c9d1c2014-08-12 08:34:29 -07001196 their order is the same as the colors.
mtklein6cfa73a2014-08-13 13:33:49 -07001197 @param xmode specifies how are the colors and the textures combined if both of them are
dandovb3c9d1c2014-08-12 08:34:29 -07001198 present.
dandov963137b2014-08-07 07:49:53 -07001199 @param paint Specifies the shader/texture if present.
1200 */
dandovb3c9d1c2014-08-12 08:34:29 -07001201 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1202 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reedcfb6bdf2016-03-29 11:32:50 -07001203 void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
1204 const sk_sp<SkXfermode>& xmode, const SkPaint& paint) {
1205 this->drawPatch(cubics, colors, texCoords, xmode.get(), paint);
1206 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001207
reed3cb38402015-02-06 08:36:15 -08001208 /**
reed71c3c762015-06-24 10:29:17 -07001209 * Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
1210 * coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
1211 * into a quad.
1212 *
1213 * xform maps [0, 0, tex.width, tex.height] -> quad
1214 *
1215 * The color array is optional. When specified, each color modulates the pixels in its
1216 * corresponding quad (via the specified SkXfermode::Mode).
1217 *
1218 * The cullRect is optional. When specified, it must be a conservative bounds of all of the
1219 * resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
1220 * intersect the current clip.
1221 *
1222 * The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
1223 * and xfermode are used to affect each of the quads.
1224 */
1225 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1226 const SkColor colors[], int count, SkXfermode::Mode, const SkRect* cullRect,
1227 const SkPaint* paint);
1228
1229 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
1230 const SkRect* cullRect, const SkPaint* paint) {
1231 this->drawAtlas(atlas, xform, tex, NULL, count, SkXfermode::kDst_Mode, cullRect, paint);
1232 }
1233
reedf8053da2016-03-17 08:14:57 -07001234 void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1235 const SkColor colors[], int count, SkXfermode::Mode mode, const SkRect* cull,
1236 const SkPaint* paint) {
1237 this->drawAtlas(atlas.get(), xform, tex, colors, count, mode, cull, paint);
1238 }
1239 void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1240 int count, const SkRect* cullRect, const SkPaint* paint) {
1241 this->drawAtlas(atlas.get(), xform, tex, nullptr, count, SkXfermode::kDst_Mode,
1242 cullRect, paint);
1243 }
1244
reed71c3c762015-06-24 10:29:17 -07001245 /**
reed3cb38402015-02-06 08:36:15 -08001246 * Draw the contents of this drawable into the canvas. If the canvas is async
1247 * (e.g. it is recording into a picture) then the drawable will be referenced instead,
1248 * to have its draw() method called when the picture is finalized.
1249 *
1250 * If the intent is to force the contents of the drawable into this canvas immediately,
1251 * then drawable->draw(canvas) may be called.
1252 */
reeda8db7282015-07-07 10:22:31 -07001253 void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL);
1254 void drawDrawable(SkDrawable*, SkScalar x, SkScalar y);
reed6a070dc2014-11-11 19:36:09 -08001255
reedf70b5312016-03-04 16:36:20 -08001256 /**
1257 * Send an "annotation" to the canvas. The annotation is a key/value pair, where the key is
1258 * a null-terminated utf8 string, and the value is a blob of data stored in an SkData
1259 * (which may be null). The annotation is associated with the specified rectangle.
1260 *
1261 * The caller still retains its ownership of the data (if any).
1262 *
1263 * Note: on may canvas types, this information is ignored, but some canvases (e.g. recording
1264 * a picture or drawing to a PDF document) will pass on this information.
1265 */
1266 void drawAnnotation(const SkRect&, const char key[], SkData* value);
mtklein0fba3b92016-04-01 04:55:51 -07001267 void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
1268 this->drawAnnotation(rect, key, value.get());
1269 }
reedf70b5312016-03-04 16:36:20 -08001270
reed@android.com8a1c16f2008-12-17 15:59:43 +00001271 //////////////////////////////////////////////////////////////////////////
fmalita77650002016-01-21 18:47:11 -08001272#ifdef SK_INTERNAL
fmalita53d9f1c2016-01-25 06:23:54 -08001273#ifndef SK_SUPPORT_LEGACY_DRAWFILTER
1274 #define SK_SUPPORT_LEGACY_DRAWFILTER
fmalita77650002016-01-21 18:47:11 -08001275#endif
1276#endif
reed@google.com4b226022011-01-11 18:32:13 +00001277
fmalita53d9f1c2016-01-25 06:23:54 -08001278#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
reed@android.com8a1c16f2008-12-17 15:59:43 +00001279 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001280 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001281 @return the canvas' filter (or NULL).
1282 */
fmalita77650002016-01-21 18:47:11 -08001283 SK_ATTR_EXTERNALLY_DEPRECATED("getDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001284 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001285
reed@android.com8a1c16f2008-12-17 15:59:43 +00001286 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1287 As a convenience, the parameter is returned. If an existing filter
1288 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001289 refcnt is incremented. The filter is saved/restored, just like the
1290 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001291 @param filter the new filter (or NULL)
1292 @return the new filter
1293 */
fmalita77650002016-01-21 18:47:11 -08001294 SK_ATTR_EXTERNALLY_DEPRECATED("setDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001295 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
fmalita77650002016-01-21 18:47:11 -08001296#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001297 //////////////////////////////////////////////////////////////////////////
1298
reed@google.com754de5f2014-02-24 19:38:20 +00001299 /**
1300 * Return true if the current clip is empty (i.e. nothing will draw).
1301 * Note: this is not always a free call, so it should not be used
1302 * more often than necessary. However, once the canvas has computed this
1303 * result, subsequent calls will be cheap (until the clip state changes,
1304 * which can happen on any clip..() or restore() call.
1305 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001306 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001307
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001308 /**
1309 * Returns true if the current clip is just a (non-empty) rectangle.
1310 * Returns false if the clip is empty, or if it is complex.
1311 */
1312 virtual bool isClipRect() const;
1313
reed@android.com8a1c16f2008-12-17 15:59:43 +00001314 /** Return the current matrix on the canvas.
1315 This does not account for the translate in any of the devices.
1316 @return The current matrix on the canvas.
1317 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001318 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001319
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001320 /** Return the clip stack. The clip stack stores all the individual
1321 * clips organized by the save/restore frame in which they were
1322 * added.
1323 * @return the current clip stack ("list" of individual clip elements)
1324 */
1325 const SkClipStack* getClipStack() const {
reed687fa1c2015-04-07 08:00:56 -07001326 return fClipStack;
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001327 }
1328
fmalitac3b589a2014-06-05 12:40:07 -07001329 typedef SkCanvasClipVisitor ClipVisitor;
reed@google.com90c07ea2012-04-13 13:50:27 +00001330 /**
1331 * Replays the clip operations, back to front, that have been applied to
1332 * the canvas, calling the appropriate method on the visitor for each
1333 * clip. All clips have already been transformed into device space.
1334 */
1335 void replayClips(ClipVisitor*) const;
1336
reed@android.com8a1c16f2008-12-17 15:59:43 +00001337 ///////////////////////////////////////////////////////////////////////////
1338
robertphillips36736a22016-04-23 08:26:43 -07001339 // don't call
robertphillips175dd9b2016-04-28 14:32:04 -07001340 GrDrawContext* internal_private_accessTopLayerDrawContext();
robertphillips36736a22016-04-23 08:26:43 -07001341
1342 // don't call
1343 static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1344 static bool Internal_Private_GetIgnoreSaveLayerBounds();
1345 static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1346 static bool Internal_Private_GetTreatSpriteAsBitmap();
1347
1348 // TEMP helpers until we switch virtual over to const& for src-rect
1349 void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1350 const SkPaint* paint,
1351 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1352 void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1353 const SkPaint* paint,
1354 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1355
tomhudsoncb3bd182016-05-18 07:24:16 -07001356 // expose minimum amount of information necessary for transitional refactoring
1357 /**
1358 * Returns CTM and clip bounds, translated from canvas coordinates to top layer coordinates.
1359 */
1360 void temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds);
1361
robertphillipsda2cd8b2016-04-21 11:05:32 -07001362protected:
vjiaoblack95302da2016-07-21 10:25:54 -07001363#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -07001364 /** Returns the current (cumulative) draw depth of the canvas.
1365 */
1366 SkScalar getZ() const;
1367
vjiaoblack95302da2016-07-21 10:25:54 -07001368 sk_sp<SkLights> fLights;
1369#endif
1370
reed@google.com76f10a32014-02-05 15:32:21 +00001371 // default impl defers to getDevice()->newSurface(info)
reede8f30622016-03-23 18:59:25 -07001372 virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
reed@google.com76f10a32014-02-05 15:32:21 +00001373
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001374 // default impl defers to its device
reed884e97c2015-05-26 11:31:54 -07001375 virtual bool onPeekPixels(SkPixmap*);
1376 virtual bool onAccessTopLayerPixels(SkPixmap*);
reedea5a6512016-07-07 16:44:27 -07001377 virtual SkImageInfo onImageInfo() const;
1378 virtual bool onGetProps(SkSurfaceProps*) const;
1379 virtual void onFlush();
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001380
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001381 // Subclass save/restore notifiers.
1382 // Overriders should call the corresponding INHERITED method up the inheritance chain.
reed4960eee2015-12-18 07:09:18 -08001383 // getSaveLayerStrategy()'s return value may suppress full layer allocation.
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001384 enum SaveLayerStrategy {
1385 kFullLayer_SaveLayerStrategy,
reed4960eee2015-12-18 07:09:18 -08001386 kNoLayer_SaveLayerStrategy,
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001387 };
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001388
fmalita6ca763f2014-06-17 13:52:18 -07001389 virtual void willSave() {}
reed4960eee2015-12-18 07:09:18 -08001390 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1391 virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) {
1392 return kFullLayer_SaveLayerStrategy;
1393 }
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001394 virtual void willRestore() {}
mtklein6cfa73a2014-08-13 13:33:49 -07001395 virtual void didRestore() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001396 virtual void didConcat(const SkMatrix&) {}
1397 virtual void didSetMatrix(const SkMatrix&) {}
mtkleincbdf0072016-08-19 09:05:27 -07001398 virtual void didTranslate(SkScalar dx, SkScalar dy) {
1399 this->didConcat(SkMatrix::MakeTrans(dx, dy));
1400 }
vjiaoblack95302da2016-07-21 10:25:54 -07001401
1402#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -07001403 virtual void didTranslateZ(SkScalar) {}
vjiaoblack95302da2016-07-21 10:25:54 -07001404#endif
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001405
reedf70b5312016-03-04 16:36:20 -08001406 virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001407 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1408
reed@google.come0d9ce82014-04-23 04:00:17 +00001409 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1410 SkScalar y, const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001411
reed@google.come0d9ce82014-04-23 04:00:17 +00001412 virtual void onDrawPosText(const void* text, size_t byteLength,
1413 const SkPoint pos[], const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001414
reed@google.come0d9ce82014-04-23 04:00:17 +00001415 virtual void onDrawPosTextH(const void* text, size_t byteLength,
1416 const SkScalar xpos[], SkScalar constY,
1417 const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001418
reed@google.come0d9ce82014-04-23 04:00:17 +00001419 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1420 const SkPath& path, const SkMatrix* matrix,
1421 const SkPaint& paint);
reed45561a02016-07-07 12:47:17 -07001422 virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
1423 const SkRect* cullRect, const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001424
fmalita00d5c2c2014-08-21 08:53:26 -07001425 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1426 const SkPaint& paint);
1427
dandovb3c9d1c2014-08-12 08:34:29 -07001428 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
1429 const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint);
reed@google.come0d9ce82014-04-23 04:00:17 +00001430
reeda8db7282015-07-07 10:22:31 -07001431 virtual void onDrawDrawable(SkDrawable*, const SkMatrix*);
reed6a070dc2014-11-11 19:36:09 -08001432
reed41af9662015-01-05 07:49:08 -08001433 virtual void onDrawPaint(const SkPaint&);
1434 virtual void onDrawRect(const SkRect&, const SkPaint&);
msarett44df6512016-08-25 13:54:30 -07001435 virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
reed41af9662015-01-05 07:49:08 -08001436 virtual void onDrawOval(const SkRect&, const SkPaint&);
bsalomonac3aa242016-08-19 11:25:19 -07001437 virtual void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
1438 const SkPaint&);
reed41af9662015-01-05 07:49:08 -08001439 virtual void onDrawRRect(const SkRRect&, const SkPaint&);
1440 virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
1441 virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
1442 const SkPoint texs[], const SkColor colors[], SkXfermode*,
1443 const uint16_t indices[], int indexCount, const SkPaint&);
mtklein2766c002015-06-26 11:45:03 -07001444
reed71c3c762015-06-24 10:29:17 -07001445 virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
1446 int count, SkXfermode::Mode, const SkRect* cull, const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001447 virtual void onDrawPath(const SkPath&, const SkPaint&);
1448 virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
reed562fe472015-07-28 07:35:14 -07001449 virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
1450 SrcRectConstraint);
reed4c21dc52015-06-25 12:32:03 -07001451 virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
1452 const SkPaint*);
msarett16882062016-08-16 09:31:08 -07001453 virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
1454 const SkPaint*);
reed4c21dc52015-06-25 12:32:03 -07001455
reed41af9662015-01-05 07:49:08 -08001456 virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
1457 virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
reed562fe472015-07-28 07:35:14 -07001458 SrcRectConstraint);
reed41af9662015-01-05 07:49:08 -08001459 virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
1460 const SkPaint*);
msarett16882062016-08-16 09:31:08 -07001461 virtual void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
1462 const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001463
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001464 enum ClipEdgeStyle {
1465 kHard_ClipEdgeStyle,
1466 kSoft_ClipEdgeStyle
1467 };
1468
1469 virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1470 virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1471 virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle);
1472 virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op);
1473
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +00001474 virtual void onDiscard();
1475
reedd5fa1a42014-08-09 11:08:05 -07001476 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
robertphillips9b14f262014-06-04 05:40:44 -07001477
vjiaoblack95302da2016-07-21 10:25:54 -07001478#ifdef SK_EXPERIMENTAL_SHADOWING
1479 virtual void onDrawShadowedPicture(const SkPicture*,
1480 const SkMatrix*,
vjiaoblacke6f5d562016-08-25 06:30:23 -07001481 const SkPaint*,
1482 const SkShadowParams& params);
vjiaoblack95302da2016-07-21 10:25:54 -07001483#endif
vjiaoblack5bfee982016-07-22 10:04:15 -07001484
vandebo@chromium.org74b46192012-01-28 01:45:11 +00001485 // Returns the canvas to be used by DrawIter. Default implementation
junov@google.com4370aed2012-01-18 16:21:08 +00001486 // returns this. Subclasses that encapsulate an indirect canvas may
1487 // need to overload this method. The impl must keep track of this, as it
1488 // is not released or deleted by the caller.
1489 virtual SkCanvas* canvasForDrawIter();
1490
junov@chromium.orga907ac32012-02-24 21:54:07 +00001491 // Clip rectangle bounds. Called internally by saveLayer.
1492 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001493 // If non-NULL, The imageFilter parameter will be used to expand the clip
1494 // and offscreen bounds for any margin required by the filter DAG.
reed4960eee2015-12-18 07:09:18 -08001495 bool clipRectBounds(const SkRect* bounds, SaveLayerFlags, SkIRect* intersection,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001496 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001497
reedc83a2972015-07-16 07:40:45 -07001498private:
reed3aafe112016-08-18 12:45:34 -07001499 /** After calling saveLayer(), there can be any number of devices that make
1500 up the top-most drawing area. LayerIter can be used to iterate through
1501 those devices. Note that the iterator is only valid until the next API
1502 call made on the canvas. Ownership of all pointers in the iterator stays
1503 with the canvas, so none of them should be modified or deleted.
1504 */
1505 class LayerIter /*: SkNoncopyable*/ {
1506 public:
1507 /** Initialize iterator with canvas, and set values for 1st device */
1508 LayerIter(SkCanvas*);
1509 ~LayerIter();
1510
1511 /** Return true if the iterator is done */
1512 bool done() const { return fDone; }
1513 /** Cycle to the next device */
1514 void next();
1515
1516 // These reflect the current device in the iterator
1517
1518 SkBaseDevice* device() const;
1519 const SkMatrix& matrix() const;
1520 const SkRasterClip& clip() const;
1521 const SkPaint& paint() const;
1522 int x() const;
1523 int y() const;
1524
1525 private:
1526 // used to embed the SkDrawIter object directly in our instance, w/o
1527 // having to expose that class def to the public. There is an assert
1528 // in our constructor to ensure that fStorage is large enough
1529 // (though needs to be a compile-time-assert!). We use intptr_t to work
1530 // safely with 32 and 64 bit machines (to ensure the storage is enough)
1531 intptr_t fStorage[32];
1532 class SkDrawIter* fImpl; // this points at fStorage
1533 SkPaint fDefaultPaint;
1534 bool fDone;
1535 };
1536
reed4960eee2015-12-18 07:09:18 -08001537 static bool BoundsAffectsClip(SaveLayerFlags);
reedbada1882015-12-21 13:09:44 -08001538 static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
reed4960eee2015-12-18 07:09:18 -08001539
reeda2217ef2016-07-20 06:04:34 -07001540 static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1541 SkBaseDevice* dst, const SkMatrix& ctm,
1542 const SkClipStack* clipStack);
1543
reedc83a2972015-07-16 07:40:45 -07001544 enum ShaderOverrideOpacity {
1545 kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
1546 kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
1547 kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
1548 };
1549
reed@google.com97af1a62012-08-28 12:19:02 +00001550 // notify our surface (if we have one) that we are about to draw, so it
1551 // can perform copy-on-write or invalidate any cached images
reedc83a2972015-07-16 07:40:45 -07001552 void predrawNotify(bool willOverwritesEntireSurface = false);
1553 void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
1554 void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
1555 this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
1556 : kNotOpaque_ShaderOverrideOpacity);
1557 }
reed@google.com97af1a62012-08-28 12:19:02 +00001558
reed@android.com8a1c16f2008-12-17 15:59:43 +00001559 class MCRec;
1560
reed687fa1c2015-04-07 08:00:56 -07001561 SkAutoTUnref<SkClipStack> fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001562 SkDeque fMCStack;
1563 // points to top of stack
1564 MCRec* fMCRec;
1565 // the first N recs that can fit here mean we won't call malloc
reedb679ca82015-04-07 04:40:48 -07001566 enum {
reeda499f902015-05-01 09:34:31 -07001567 kMCRecSize = 128, // most recent measurement
reed31b80a92015-11-16 13:22:24 -08001568 kMCRecCount = 32, // common depth for save/restores
reed8c30a812016-04-20 16:36:51 -07001569 kDeviceCMSize = 176, // most recent measurement
reedb679ca82015-04-07 04:40:48 -07001570 };
1571 intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
reeda499f902015-05-01 09:34:31 -07001572 intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001573
reed4a8126e2014-09-22 07:29:03 -07001574 const SkSurfaceProps fProps;
1575
reed2ff1fce2014-12-11 07:07:37 -08001576 int fSaveCount; // value returned by getSaveCount()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001577
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001578 SkMetaData* fMetaData;
1579
reed@google.com97af1a62012-08-28 12:19:02 +00001580 SkSurface_Base* fSurfaceBase;
1581 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1582 void setSurfaceBase(SkSurface_Base* sb) {
1583 fSurfaceBase = sb;
1584 }
1585 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001586 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001587
reed@android.com8a1c16f2008-12-17 15:59:43 +00001588 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1589 void updateDeviceCMCache();
1590
reed2ff1fce2014-12-11 07:07:37 -08001591 void doSave();
1592 void checkForDeferredSave();
reed8c30a812016-04-20 16:36:51 -07001593 void internalSetMatrix(const SkMatrix&);
reed2ff1fce2014-12-11 07:07:37 -08001594
reed@google.com9c135db2014-03-12 18:28:35 +00001595 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001596 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001597 friend class SkLua; // needs top layer size and offset
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +00001598 friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
reed52d9ac62014-06-30 09:05:34 -07001599 friend class SkSurface_Raster; // needs getDevice()
reedd9544982014-09-09 18:46:22 -07001600 friend class SkRecorder; // InitFlags
mtklein9c5052f2016-08-06 12:51:51 -07001601 friend class SkLiteRecorder; // InitFlags
reedd9544982014-09-09 18:46:22 -07001602 friend class SkNoSaveLayerCanvas; // InitFlags
fmalita2d97bc12014-11-20 10:44:58 -08001603 friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
reedc83a2972015-07-16 07:40:45 -07001604 friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
reed4960eee2015-12-18 07:09:18 -08001605 friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
piotaixrb5fae932014-09-24 13:03:30 -07001606
reedd9544982014-09-09 18:46:22 -07001607 enum InitFlags {
1608 kDefault_InitFlags = 0,
1609 kConservativeRasterClip_InitFlag = 1 << 0,
1610 };
reed78e27682014-11-19 08:04:34 -08001611 SkCanvas(const SkIRect& bounds, InitFlags);
robertphillipsfcf78292015-06-19 11:49:52 -07001612 SkCanvas(SkBaseDevice* device, InitFlags);
reedd9544982014-09-09 18:46:22 -07001613
mtkleinfeaadee2015-04-08 11:25:48 -07001614 void resetForNextPicture(const SkIRect& bounds);
1615
reed8f2e7912014-09-04 12:45:18 -07001616 // needs gettotalclip()
tfarinaa5414c42014-10-10 06:19:09 -07001617 friend class SkCanvasStateUtils;
piotaixrb5fae932014-09-24 13:03:30 -07001618
reed4a8126e2014-09-22 07:29:03 -07001619 // call this each time we attach ourselves to a device
1620 // - constructor
1621 // - internalSaveLayer
1622 void setupDevice(SkBaseDevice*);
1623
reedd9544982014-09-09 18:46:22 -07001624 SkBaseDevice* init(SkBaseDevice*, InitFlags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001625
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001626 /**
senorblancoafc7cce2016-02-02 18:44:15 -08001627 * 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 +00001628 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1629 */
senorblancoafc7cce2016-02-02 18:44:15 -08001630 SkIRect getTopLayerBounds() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001631
reed@google.com71121732012-09-18 15:14:33 +00001632 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001633 const SkRect& dst, const SkPaint* paint,
reeda5517e22015-07-14 10:54:12 -07001634 SrcRectConstraint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001635 void internalDrawPaint(const SkPaint& paint);
reed4960eee2015-12-18 07:09:18 -08001636 void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
reed7503d602016-07-15 14:23:29 -07001637 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001638
reed@android.com8a1c16f2008-12-17 15:59:43 +00001639 // shared by save() and saveLayer()
reed2ff1fce2014-12-11 07:07:37 -08001640 void internalSave();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001641 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001642 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1643 const SkRect& r, SkScalar textSize);
1644 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1645 const char text[], size_t byteLength,
1646 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001647
reedfa35f8e2014-09-04 12:14:36 -07001648 // only for canvasutils
1649 const SkRegion& internal_private_getTotalClip() const;
1650
reedc83a2972015-07-16 07:40:45 -07001651 /*
1652 * Returns true if drawing the specified rect (or all if it is null) with the specified
1653 * paint (or default if null) would overwrite the entire root device of the canvas
1654 * (i.e. the canvas' surface if it had one).
1655 */
1656 bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
1657
reed262a71b2015-12-05 13:07:27 -08001658 /**
1659 * Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
1660 */
1661 bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
reedc83a2972015-07-16 07:40:45 -07001662
msarettfbfa2582016-08-12 08:29:08 -07001663
1664 /**
1665 * Keep track of the device clip bounds and if the matrix is scale-translate. This allows
1666 * us to do a fast quick reject in the common case.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001667 */
msarett9637ea92016-08-18 14:03:30 -07001668 bool fIsScaleTranslate;
msarettfbfa2582016-08-12 08:29:08 -07001669 SkRect fDeviceClipBounds;
1670
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001671 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001672 bool fAllowSimplifyClip;
reed42b73eb2015-11-20 13:42:42 -08001673 const bool fConservativeRasterClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001674
reed@google.com5c3d1472011-02-22 19:12:23 +00001675 class AutoValidateClip : ::SkNoncopyable {
1676 public:
1677 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1678 fCanvas->validateClip();
1679 }
1680 ~AutoValidateClip() { fCanvas->validateClip(); }
1681
1682 private:
1683 const SkCanvas* fCanvas;
1684 };
1685
1686#ifdef SK_DEBUG
1687 void validateClip() const;
1688#else
1689 void validateClip() const {}
1690#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001691
1692 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001693};
1694
1695/** Stack helper class to automatically call restoreToCount() on the canvas
1696 when this object goes out of scope. Use this to guarantee that the canvas
1697 is restored to a known state.
1698*/
1699class SkAutoCanvasRestore : SkNoncopyable {
1700public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001701 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1702 if (fCanvas) {
1703 fSaveCount = canvas->getSaveCount();
1704 if (doSave) {
1705 canvas->save();
1706 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001707 }
1708 }
1709 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001710 if (fCanvas) {
1711 fCanvas->restoreToCount(fSaveCount);
1712 }
1713 }
1714
1715 /**
1716 * Perform the restore now, instead of waiting for the destructor. Will
1717 * only do this once.
1718 */
1719 void restore() {
1720 if (fCanvas) {
1721 fCanvas->restoreToCount(fSaveCount);
1722 fCanvas = NULL;
1723 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001724 }
1725
1726private:
1727 SkCanvas* fCanvas;
1728 int fSaveCount;
1729};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001730#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001731
fmalitac3b589a2014-06-05 12:40:07 -07001732class SkCanvasClipVisitor {
1733public:
1734 virtual ~SkCanvasClipVisitor();
1735 virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0;
1736 virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0;
1737 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0;
1738};
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001739
reed@android.com8a1c16f2008-12-17 15:59:43 +00001740#endif