blob: 9887211057ec42b5dfb7502435a564bfff6190ad [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"
reed374772b2016-10-05 17:33:02 -070012#include "SkBlendMode.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkBitmap.h"
reed73603f32016-09-20 08:42:38 -070014#include "SkClipOp.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015#include "SkDeque.h"
msarette8597a42016-03-24 10:41:47 -070016#include "SkImage.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017#include "SkPaint.h"
18#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000019#include "SkRegion.h"
reed4a8126e2014-09-22 07:29:03 -070020#include "SkSurfaceProps.h"
vjiaoblack95302da2016-07-21 10:25:54 -070021#include "SkLights.h"
vjiaoblacke6f5d562016-08-25 06:30:23 -070022#include "../private/SkShadowParams.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000023
bungemand3ebb482015-08-05 13:57:49 -070024class GrContext;
Brian Osman11052242016-10-27 14:47:55 -040025class GrRenderTargetContext;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000026class SkBaseDevice;
reed6a070dc2014-11-11 19:36:09 -080027class SkCanvasClipVisitor;
bungemand3ebb482015-08-05 13:57:49 -070028class SkClipStack;
reedf70b5312016-03-04 16:36:20 -080029class SkData;
reed@android.com8a1c16f2008-12-17 15:59:43 +000030class SkDraw;
reed3cb38402015-02-06 08:36:15 -080031class SkDrawable;
reed@android.com8a1c16f2008-12-17 15:59:43 +000032class SkDrawFilter;
bungemand3ebb482015-08-05 13:57:49 -070033class SkImageFilter;
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +000034class SkMetaData;
bungemand3ebb482015-08-05 13:57:49 -070035class SkPath;
reed@android.com8a1c16f2008-12-17 15:59:43 +000036class SkPicture;
bungemand3ebb482015-08-05 13:57:49 -070037class SkPixmap;
reed1e7f5e72016-04-27 07:49:17 -070038class SkRasterClip;
reed@google.com4ed0fb72012-12-12 20:48:18 +000039class SkRRect;
reed71c3c762015-06-24 10:29:17 -070040struct SkRSXform;
reed@google.com76f10a32014-02-05 15:32:21 +000041class SkSurface;
reed@google.com97af1a62012-08-28 12:19:02 +000042class SkSurface_Base;
fmalita00d5c2c2014-08-21 08:53:26 -070043class SkTextBlob;
reedfa35f8e2014-09-04 12:14:36 -070044
reed73603f32016-09-20 08:42:38 -070045//#define SK_SUPPORT_LEGACY_CLIP_REGIONOPS
46
reed@android.com8a1c16f2008-12-17 15:59:43 +000047/** \class SkCanvas
48
49 A Canvas encapsulates all of the state about drawing into a device (bitmap).
50 This includes a reference to the device itself, and a stack of matrix/clip
51 values. For any given draw call (e.g. drawRect), the geometry of the object
52 being drawn is transformed by the concatenation of all the matrices in the
53 stack. The transformed geometry is clipped by the intersection of all of
54 the clips in the stack.
55
56 While the Canvas holds the state of the drawing device, the state (style)
57 of the object being drawn is held by the Paint, which is provided as a
58 parameter to each of the draw() methods. The Paint holds attributes such as
59 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
60 etc.
61*/
Mike Reed5df49342016-11-12 08:06:55 -060062class SK_API SkCanvas
63#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
64: public SkRefCnt
65#else
66: SkNoncopyable
67#endif
68{
reedbada1882015-12-21 13:09:44 -080069 enum PrivateSaveLayerFlags {
caryclark952538e2016-02-26 05:01:42 -080070 kDontClipToLayer_PrivateSaveLayerFlag = 1U << 31,
reedbada1882015-12-21 13:09:44 -080071 };
reed73603f32016-09-20 08:42:38 -070072
reed@android.com8a1c16f2008-12-17 15:59:43 +000073public:
reed73603f32016-09-20 08:42:38 -070074#ifdef SK_SUPPORT_LEGACY_CLIP_REGIONOPS
75 typedef SkRegion::Op ClipOp;
76
77 static const ClipOp kDifference_Op = SkRegion::kDifference_Op;
78 static const ClipOp kIntersect_Op = SkRegion::kIntersect_Op;
79 static const ClipOp kUnion_Op = SkRegion::kUnion_Op;
80 static const ClipOp kXOR_Op = SkRegion::kXOR_Op;
81 static const ClipOp kReverseDifference_Op = SkRegion::kReverseDifference_Op;
82 static const ClipOp kReplace_Op = SkRegion::kReplace_Op;
83#else
84 typedef SkClipOp ClipOp;
85
86 static const ClipOp kDifference_Op = kDifference_SkClipOp;
87 static const ClipOp kIntersect_Op = kIntersect_SkClipOp;
88 static const ClipOp kUnion_Op = kUnion_SkClipOp;
89 static const ClipOp kXOR_Op = kXOR_SkClipOp;
90 static const ClipOp kReverseDifference_Op = kReverseDifference_SkClipOp;
91 static const ClipOp kReplace_Op = kReplace_SkClipOp;
92#endif
commit-bot@chromium.orge2543102014-01-31 19:42:58 +000093 /**
commit-bot@chromium.org42b08932014-03-17 02:13:07 +000094 * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
95 * specified pixels. To access the pixels after drawing to them, the caller should call
96 * flush() or call peekPixels(...).
97 *
98 * On failure, return NULL. This can fail for several reasons:
99 * 1. invalid ImageInfo (e.g. negative dimensions)
100 * 2. unsupported ImageInfo for a canvas
101 * - kUnknown_SkColorType, kIndex_8_SkColorType
reed44977482015-02-27 10:23:00 -0800102 * - kUnknown_SkAlphaType
commit-bot@chromium.org42b08932014-03-17 02:13:07 +0000103 * - this list is not complete, so others may also be unsupported
104 *
105 * Note: it is valid to request a supported ImageInfo, but with zero
106 * dimensions.
107 */
Mike Reed5df49342016-11-12 08:06:55 -0600108 static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo&, void*, size_t);
109
110 static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
111 size_t rowBytes) {
112 return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
113 }
114
115#ifdef SK_SUPPORT_LEGACY_CANVAS_IS_REFCNT
116 static SkCanvas* NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
117 return MakeRasterDirect(info, pixels, rowBytes).release();
118 }
commit-bot@chromium.org42b08932014-03-17 02:13:07 +0000119
120 static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) {
Mike Reed5df49342016-11-12 08:06:55 -0600121 return MakeRasterDirectN32(width, height, pixels, rowBytes).release();
commit-bot@chromium.org42b08932014-03-17 02:13:07 +0000122 }
Mike Reed5df49342016-11-12 08:06:55 -0600123#endif
commit-bot@chromium.org42b08932014-03-17 02:13:07 +0000124
125 /**
commit-bot@chromium.orge2543102014-01-31 19:42:58 +0000126 * Creates an empty canvas with no backing device/pixels, and zero
127 * dimensions.
128 */
reed@google.comcde92112011-07-06 20:00:52 +0000129 SkCanvas();
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000130
commit-bot@chromium.orge2543102014-01-31 19:42:58 +0000131 /**
132 * Creates a canvas of the specified dimensions, but explicitly not backed
133 * by any device/pixels. Typically this use used by subclasses who handle
134 * the draw calls in some other way.
135 */
reed96a857e2015-01-25 10:33:58 -0800136 SkCanvas(int width, int height, const SkSurfaceProps* = NULL);
commit-bot@chromium.orge2543102014-01-31 19:42:58 +0000137
reed@google.com6dc74552011-07-21 18:00:46 +0000138 /** Construct a canvas with the specified device to draw into.
bsalomon@google.come97f0852011-06-17 13:10:25 +0000139
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000140 @param device Specifies a device for the canvas to draw into.
141 */
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000142 explicit SkCanvas(SkBaseDevice* device);
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000143
reed@google.com44699382013-10-31 17:28:30 +0000144 /** Construct a canvas with the specified bitmap to draw into.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000145 @param bitmap Specifies a bitmap for the canvas to draw into. Its
146 structure are copied to the canvas.
147 */
148 explicit SkCanvas(const SkBitmap& bitmap);
fmalita3d91aad2015-02-02 05:25:04 -0800149
150 /** Construct a canvas with the specified bitmap to draw into.
151 @param bitmap Specifies a bitmap for the canvas to draw into. Its
152 structure are copied to the canvas.
153 @param props New canvas surface properties.
154 */
155 SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
156
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157 virtual ~SkCanvas();
158
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +0000159 SkMetaData& getMetaData();
160
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000161 /**
162 * Return ImageInfo for this canvas. If the canvas is not backed by pixels
163 * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
164 */
165 SkImageInfo imageInfo() const;
166
brianosman898235c2016-04-06 07:38:23 -0700167 /**
168 * If the canvas is backed by pixels (cpu or gpu), this writes a copy of the SurfaceProps
169 * for the canvas to the location supplied by the caller, and returns true. Otherwise,
170 * return false and leave the supplied props unchanged.
171 */
172 bool getProps(SkSurfaceProps*) const;
173
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174 ///////////////////////////////////////////////////////////////////////////
175
reed@google.com210ce002011-11-01 14:24:23 +0000176 /**
bsalomone63ffef2016-02-05 07:17:34 -0800177 * Trigger the immediate execution of all pending draw operations. For the GPU
178 * backend this will resolve all rendering to the GPU surface backing the
179 * SkSurface that owns this canvas.
junov@chromium.orgbf6c1e42012-01-30 14:53:22 +0000180 */
181 void flush();
182
183 /**
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000184 * Gets the size of the base or root layer in global canvas coordinates. The
185 * origin of the base layer is always (0,0). The current drawable area may be
186 * smaller (due to clipping or saveLayer).
reed@google.com210ce002011-11-01 14:24:23 +0000187 */
tomhudson68260fa2015-03-23 07:22:40 -0700188 virtual SkISize getBaseLayerSize() const;
bsalomon@google.com4ebe3822014-02-26 20:22:32 +0000189
190 /**
191 * DEPRECATED: call getBaseLayerSize
192 */
193 SkISize getDeviceSize() const { return this->getBaseLayerSize(); }
reed@google.com210ce002011-11-01 14:24:23 +0000194
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000195 /**
196 * DEPRECATED.
197 * Return the canvas' device object, which may be null. The device holds
198 * the bitmap of the pixels that the canvas draws into. The reference count
199 * of the returned device is not changed by this call.
200 */
reed52d9ac62014-06-30 09:05:34 -0700201#ifndef SK_SUPPORT_LEGACY_GETDEVICE
202protected: // Can we make this private?
203#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000204 SkBaseDevice* getDevice() const;
reed52d9ac62014-06-30 09:05:34 -0700205public:
reed41e010c2015-06-09 12:16:53 -0700206 SkBaseDevice* getDevice_just_for_deprecated_compatibility_testing() const {
207 return this->getDevice();
208 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209
reed@google.com9266fed2011-03-30 00:18:03 +0000210 /**
211 * saveLayer() can create another device (which is later drawn onto
212 * the previous device). getTopDevice() returns the top-most device current
213 * installed. Note that this can change on other calls like save/restore,
214 * so do not access this device after subsequent canvas calls.
215 * The reference count of the device is not changed.
reed@google.com0b53d592012-03-19 18:26:34 +0000216 *
217 * @param updateMatrixClip If this is true, then before the device is
218 * returned, we ensure that its has been notified about the current
219 * matrix and clip. Note: this happens automatically when the device
220 * is drawn to, but is optional here, as there is a small perf hit
221 * sometimes.
reed@google.com9266fed2011-03-30 00:18:03 +0000222 */
reed@google.com9c135db2014-03-12 18:28:35 +0000223#ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE
224private:
225#endif
robertphillips@google.com1f2f3382013-08-29 11:54:56 +0000226 SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const;
reed@google.com9c135db2014-03-12 18:28:35 +0000227public:
reed@google.com9266fed2011-03-30 00:18:03 +0000228
reed@google.com76f10a32014-02-05 15:32:21 +0000229 /**
230 * Create a new surface matching the specified info, one that attempts to
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000231 * be maximally compatible when used with this canvas. If there is no matching Surface type,
232 * NULL is returned.
reed4a8126e2014-09-22 07:29:03 -0700233 *
234 * If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
235 * inherits the properties of the surface that owns this canvas. If this canvas has no parent
236 * surface, then the new surface is created with default properties.
reed@google.com76f10a32014-02-05 15:32:21 +0000237 */
reede8f30622016-03-23 18:59:25 -0700238 sk_sp<SkSurface> makeSurface(const SkImageInfo&, const SkSurfaceProps* = nullptr);
bsalomon@google.come97f0852011-06-17 13:10:25 +0000239
commit-bot@chromium.org644629c2013-11-21 06:21:58 +0000240 /**
241 * Return the GPU context of the device that is associated with the canvas.
242 * For a canvas with non-GPU device, NULL is returned.
243 */
244 GrContext* getGrContext();
245
reed@google.com4b226022011-01-11 18:32:13 +0000246 ///////////////////////////////////////////////////////////////////////////
247
bsalomon@google.comdaba14b2011-11-02 20:10:48 +0000248 /**
reed@google.com9c135db2014-03-12 18:28:35 +0000249 * If the canvas has writable pixels in its top layer (and is not recording to a picture
250 * or other non-raster target) and has direct access to its pixels (i.e. they are in
251 * local RAM) return the address of those pixels, and if not null,
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000252 * return the ImageInfo, rowBytes and origin. The returned address is only valid
reed@google.com9c135db2014-03-12 18:28:35 +0000253 * while the canvas object is in scope and unchanged. Any API calls made on
254 * canvas (or its parent surface if any) will invalidate the
255 * returned address (and associated information).
256 *
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000257 * On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
reed@google.com9c135db2014-03-12 18:28:35 +0000258 */
commit-bot@chromium.org6b4aaa72014-04-21 21:09:38 +0000259 void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
reed@google.com9c135db2014-03-12 18:28:35 +0000260
261 /**
262 * If the canvas has readable pixels in its base layer (and is not recording to a picture
263 * or other non-raster target) and has direct access to its pixels (i.e. they are in
reed6ceeebd2016-03-09 14:26:26 -0800264 * local RAM) return true, and if not null, return in the pixmap parameter information about
265 * the pixels. The pixmap's pixel address is only valid
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000266 * while the canvas object is in scope and unchanged. Any API calls made on
reed6ceeebd2016-03-09 14:26:26 -0800267 * canvas (or its parent surface if any) will invalidate the pixel address
268 * (and associated information).
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000269 *
reed6ceeebd2016-03-09 14:26:26 -0800270 * On failure, returns false and the pixmap parameter will be ignored.
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +0000271 */
reed6ceeebd2016-03-09 14:26:26 -0800272 bool peekPixels(SkPixmap*);
273
reed@google.com4b226022011-01-11 18:32:13 +0000274 /**
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000275 * Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
276 * converting them into the requested format (SkImageInfo). The base-layer pixels are read
reedb184f7f2014-07-13 04:32:32 -0700277 * starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000278 *
reedb184f7f2014-07-13 04:32:32 -0700279 * The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000280 *
reedb184f7f2014-07-13 04:32:32 -0700281 * srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000282 *
reedb184f7f2014-07-13 04:32:32 -0700283 * srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
284 * then we have two sets of pixels (of equal size). Replace the dst pixels with the
285 * corresponding src pixels, performing any colortype/alphatype transformations needed
286 * (in the case where the src and dst have different colortypes or alphatypes).
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000287 *
288 * This call can fail, returning false, for several reasons:
reedb184f7f2014-07-13 04:32:32 -0700289 * - If srcR does not intersect the base-layer bounds.
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000290 * - If the requested colortype/alphatype cannot be converted from the base-layer's types.
291 * - If this canvas is not backed by pixels (e.g. picture or PDF)
292 */
reedb184f7f2014-07-13 04:32:32 -0700293 bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
294 int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000295
296 /**
297 * Helper for calling readPixels(info, ...). This call will check if bitmap has been allocated.
298 * If not, it will attempt to call allocPixels(). If this fails, it will return false. If not,
299 * it calls through to readPixels(info, ...) and returns its result.
300 */
reedb184f7f2014-07-13 04:32:32 -0700301 bool readPixels(SkBitmap* bitmap, int srcX, int srcY);
commit-bot@chromium.orga713f9c2014-03-17 21:31:26 +0000302
303 /**
304 * Helper for allocating pixels and then calling readPixels(info, ...). The bitmap is resized
305 * to the intersection of srcRect and the base-layer bounds. On success, pixels will be
306 * allocated in bitmap and true returned. On failure, false is returned and bitmap will be
307 * set to empty.
reed@google.com51df9e32010-12-23 19:29:18 +0000308 */
309 bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
reed@google.com51df9e32010-12-23 19:29:18 +0000310
commit-bot@chromium.org4cd9e212014-03-07 03:25:16 +0000311 /**
312 * This method affects the pixels in the base-layer, and operates in pixel coordinates,
313 * ignoring the matrix and clip.
314 *
315 * The specified ImageInfo and (x,y) offset specifies a rectangle: target.
316 *
317 * target.setXYWH(x, y, info.width(), info.height());
318 *
319 * Target is intersected with the bounds of the base-layer. If this intersection is not empty,
320 * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
321 * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
322 * pixels, performing any colortype/alphatype transformations needed (in the case where the
323 * src and dst have different colortypes or alphatypes).
324 *
325 * This call can fail, returning false, for several reasons:
326 * - If the src colortype/alphatype cannot be converted to the canvas' types
327 * - If this canvas is not backed by pixels (e.g. picture or PDF)
328 */
329 bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y);
330
331 /**
332 * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
333 * is just wrapping a texture, returns false and does nothing.
334 */
335 bool writePixels(const SkBitmap& bitmap, int x, int y);
reed@google.com4b226022011-01-11 18:32:13 +0000336
reed@android.com8a1c16f2008-12-17 15:59:43 +0000337 ///////////////////////////////////////////////////////////////////////////
vandebo@chromium.org8d84fac2010-10-13 22:13:05 +0000338
reed@android.comdc3381f2010-02-11 16:05:15 +0000339 /** This call saves the current matrix, clip, and drawFilter, and pushes a
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340 copy onto a private stack. Subsequent calls to translate, scale,
reed@android.comdc3381f2010-02-11 16:05:15 +0000341 rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
342 operate on this copy.
343 When the balancing call to restore() is made, the previous matrix, clip,
344 and drawFilter are restored.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000345
346 @return The value to pass to restoreToCount() to balance this save()
347 */
348 int save();
349
reed@android.com8a1c16f2008-12-17 15:59:43 +0000350 /** This behaves the same as save(), but in addition it allocates an
351 offscreen bitmap. All drawing calls are directed there, and only when
352 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000353 the canvas (or the previous layer).
reed@android.comad164b22010-07-02 17:20:51 +0000354 @param bounds (may be null) This rect, if non-null, is used as a hint to
355 limit the size of the offscreen, and thus drawing may be
356 clipped to it, though that clipping is not guaranteed to
357 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000358 @param paint (may be null) This is copied, and is applied to the
359 offscreen when restore() is called
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000360 @return The value to pass to restoreToCount() to balance this save()
361 */
362 int saveLayer(const SkRect* bounds, const SkPaint* paint);
reed021f6312015-08-09 19:41:13 -0700363 int saveLayer(const SkRect& bounds, const SkPaint* paint) {
364 return this->saveLayer(&bounds, paint);
365 }
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000366
reed70ee31b2015-12-10 13:44:45 -0800367 /**
368 * Temporary name.
369 * Will allow any requests for LCD text to be respected, so the caller must be careful to
370 * only draw on top of opaque sections of the layer to get good results.
371 */
372 int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
373
reed@android.com8a1c16f2008-12-17 15:59:43 +0000374 /** This behaves the same as save(), but in addition it allocates an
375 offscreen bitmap. All drawing calls are directed there, and only when
376 the balancing call to restore() is made is that offscreen transfered to
reed@android.comdc3381f2010-02-11 16:05:15 +0000377 the canvas (or the previous layer).
reed@android.com40408612010-07-02 17:24:23 +0000378 @param bounds (may be null) This rect, if non-null, is used as a hint to
379 limit the size of the offscreen, and thus drawing may be
380 clipped to it, though that clipping is not guaranteed to
381 happen. If exact clipping is desired, use clipRect().
reed@android.com8a1c16f2008-12-17 15:59:43 +0000382 @param alpha This is applied to the offscreen when restore() is called.
commit-bot@chromium.orgd70fa202014-04-24 21:51:58 +0000383 @return The value to pass to restoreToCount() to balance this save()
384 */
385 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
386
reed4960eee2015-12-18 07:09:18 -0800387 enum {
388 kIsOpaque_SaveLayerFlag = 1 << 0,
389 kPreserveLCDText_SaveLayerFlag = 1 << 1,
reedbada1882015-12-21 13:09:44 -0800390
391#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
392 kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
393#endif
reed4960eee2015-12-18 07:09:18 -0800394 };
395 typedef uint32_t SaveLayerFlags;
396
397 struct SaveLayerRec {
reedbfd5f172016-01-07 11:28:08 -0800398 SaveLayerRec()
399 : fBounds(nullptr), fPaint(nullptr), fBackdrop(nullptr), fSaveLayerFlags(0)
400 {}
reed4960eee2015-12-18 07:09:18 -0800401 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
402 : fBounds(bounds)
403 , fPaint(paint)
reedbfd5f172016-01-07 11:28:08 -0800404 , fBackdrop(nullptr)
405 , fSaveLayerFlags(saveLayerFlags)
406 {}
407 SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
408 SaveLayerFlags saveLayerFlags)
409 : fBounds(bounds)
410 , fPaint(paint)
411 , fBackdrop(backdrop)
reed4960eee2015-12-18 07:09:18 -0800412 , fSaveLayerFlags(saveLayerFlags)
413 {}
414
reedbfd5f172016-01-07 11:28:08 -0800415 const SkRect* fBounds; // optional
416 const SkPaint* fPaint; // optional
417 const SkImageFilter* fBackdrop; // optional
418 SaveLayerFlags fSaveLayerFlags;
reed4960eee2015-12-18 07:09:18 -0800419 };
420
421 int saveLayer(const SaveLayerRec&);
422
reed@android.com8a1c16f2008-12-17 15:59:43 +0000423 /** This call balances a previous call to save(), and is used to remove all
reed@android.comdc3381f2010-02-11 16:05:15 +0000424 modifications to the matrix/clip/drawFilter state since the last save
425 call.
426 It is an error to call restore() more times than save() was called.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000427 */
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +0000428 void restore();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000429
430 /** Returns the number of matrix/clip states on the SkCanvas' private stack.
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000431 This will equal # save() calls - # restore() calls + 1. The save count on
432 a new canvas is 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000433 */
junov@chromium.orga907ac32012-02-24 21:54:07 +0000434 int getSaveCount() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000435
436 /** Efficient way to pop any calls to save() that happened after the save
commit-bot@chromium.orgea7d08e2014-02-13 16:00:51 +0000437 count reached saveCount. It is an error for saveCount to be greater than
438 getSaveCount(). To pop all the way back to the initial matrix/clip context
439 pass saveCount == 1.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000440 @param saveCount The number of save() levels to restore from
441 */
442 void restoreToCount(int saveCount);
443
444 /** Preconcat the current matrix with the specified translation
445 @param dx The distance to translate in X
446 @param dy The distance to translate in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000447 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000448 void translate(SkScalar dx, SkScalar dy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000449
450 /** Preconcat the current matrix with the specified scale.
451 @param sx The amount to scale in X
452 @param sy The amount to scale in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000453 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000454 void scale(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000455
bungeman7438bfc2016-07-12 15:01:19 -0700456 /** Preconcat the current matrix with the specified rotation about the origin.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000457 @param degrees The amount to rotate, in degrees
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000459 void rotate(SkScalar degrees);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460
bungeman7438bfc2016-07-12 15:01:19 -0700461 /** Preconcat the current matrix with the specified rotation about a given point.
462 @param degrees The amount to rotate, in degrees
463 @param px The x coordinate of the point to rotate about.
464 @param py The y coordinate of the point to rotate about.
465 */
466 void rotate(SkScalar degrees, SkScalar px, SkScalar py);
467
reed@android.com8a1c16f2008-12-17 15:59:43 +0000468 /** Preconcat the current matrix with the specified skew.
469 @param sx The amount to skew in X
470 @param sy The amount to skew in Y
reed@android.com8a1c16f2008-12-17 15:59:43 +0000471 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000472 void skew(SkScalar sx, SkScalar sy);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000473
474 /** Preconcat the current matrix with the specified matrix.
475 @param matrix The matrix to preconcatenate with the current matrix
reed@android.com8a1c16f2008-12-17 15:59:43 +0000476 */
commit-bot@chromium.org92362382014-03-18 12:51:48 +0000477 void concat(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000478
reed@android.com8a1c16f2008-12-17 15:59:43 +0000479 /** Replace the current matrix with a copy of the specified matrix.
480 @param matrix The matrix that will be copied into the current matrix.
481 */
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +0000482 void setMatrix(const SkMatrix& matrix);
reed@google.com4b226022011-01-11 18:32:13 +0000483
reed@android.com8a1c16f2008-12-17 15:59:43 +0000484 /** Helper for setMatrix(identity). Sets the current matrix to identity.
485 */
486 void resetMatrix();
487
vjiaoblack95302da2016-07-21 10:25:54 -0700488#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -0700489 /** Add the specified translation to the current draw depth of the canvas.
490 @param z The distance to translate in Z.
491 Negative into screen, positive out of screen.
492 Without translation, the draw depth defaults to 0.
493 */
494 void translateZ(SkScalar z);
495
vjiaoblack95302da2016-07-21 10:25:54 -0700496 /** Set the current set of lights in the canvas.
497 @param lights The lights that we want the canvas to have.
498 */
499 void setLights(sk_sp<SkLights> lights);
500
501 /** Returns the current set of lights the canvas uses
502 */
503 sk_sp<SkLights> getLights() const;
504#endif
505
reed@google.com4ed0fb72012-12-12 20:48:18 +0000506 /**
507 * Modify the current clip with the specified rectangle.
508 * @param rect The rect to combine with the current clip
509 * @param op The region op to apply to the current clip
510 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000511 */
reed66998382016-09-21 11:15:07 -0700512 void clipRect(const SkRect& rect, ClipOp, bool doAntiAlias);
513 void clipRect(const SkRect& rect, ClipOp op) {
514 this->clipRect(rect, op, false);
515 }
516 void clipRect(const SkRect& rect, bool doAntiAlias = false) {
517 this->clipRect(rect, kIntersect_Op, doAntiAlias);
518 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000519
reed@google.com4ed0fb72012-12-12 20:48:18 +0000520 /**
521 * Modify the current clip with the specified SkRRect.
522 * @param rrect The rrect to combine with the current clip
523 * @param op The region op to apply to the current clip
524 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000525 */
reed66998382016-09-21 11:15:07 -0700526 void clipRRect(const SkRRect& rrect, ClipOp op, bool doAntiAlias);
527 void clipRRect(const SkRRect& rrect, ClipOp op) {
528 this->clipRRect(rrect, op, false);
529 }
530 void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
531 this->clipRRect(rrect, kIntersect_Op, doAntiAlias);
532 }
reed@google.com4ed0fb72012-12-12 20:48:18 +0000533
534 /**
535 * Modify the current clip with the specified path.
536 * @param path The path to combine with the current clip
537 * @param op The region op to apply to the current clip
538 * @param doAntiAlias true if the clip should be antialiased
reed@google.com4ed0fb72012-12-12 20:48:18 +0000539 */
reed66998382016-09-21 11:15:07 -0700540 void clipPath(const SkPath& path, ClipOp op, bool doAntiAlias);
541 void clipPath(const SkPath& path, ClipOp op) {
542 this->clipPath(path, op, false);
543 }
544 void clipPath(const SkPath& path, bool doAntiAlias = false) {
545 this->clipPath(path, kIntersect_Op, doAntiAlias);
546 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000547
caryclark@google.com8f0a7b82012-11-07 14:54:49 +0000548 /** EXPERIMENTAL -- only used for testing
caryclark@google.com45a75fb2013-04-25 13:34:40 +0000549 Set to simplify clip stack using path ops.
550 */
551 void setAllowSimplifyClip(bool allow) {
552 fAllowSimplifyClip = allow;
553 }
554
reed@android.com8a1c16f2008-12-17 15:59:43 +0000555 /** Modify the current clip with the specified region. Note that unlike
556 clipRect() and clipPath() which transform their arguments by the current
557 matrix, clipRegion() assumes its argument is already in device
558 coordinates, and so no transformation is performed.
559 @param deviceRgn The region to apply to the current clip
mtklein6e998e62016-07-13 09:03:48 -0700560 @param op The region op to apply to the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000561 */
reed73603f32016-09-20 08:42:38 -0700562 void clipRegion(const SkRegion& deviceRgn, ClipOp op = kIntersect_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000563
reed@android.com8a1c16f2008-12-17 15:59:43 +0000564 /** Return true if the specified rectangle, after being transformed by the
565 current matrix, would lie completely outside of the current clip. Call
566 this to check if an area you intend to draw into is clipped out (and
567 therefore you can skip making the draw calls).
568 @param rect the rect to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000569 @return true if the rect (transformed by the canvas' matrix) does not
570 intersect with the canvas' clip
571 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000572 bool quickReject(const SkRect& rect) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000573
574 /** Return true if the specified path, after being transformed by the
575 current matrix, would lie completely outside of the current clip. Call
576 this to check if an area you intend to draw into is clipped out (and
577 therefore you can skip making the draw calls). Note, for speed it may
578 return false even if the path itself might not intersect the clip
579 (i.e. the bounds of the path intersects, but the path does not).
580 @param path The path to compare with the current clip
reed@android.com8a1c16f2008-12-17 15:59:43 +0000581 @return true if the path (transformed by the canvas' matrix) does not
582 intersect with the canvas' clip
583 */
reed@google.com3b3e8952012-08-16 20:53:31 +0000584 bool quickReject(const SkPath& path) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000585
reed@android.com8a1c16f2008-12-17 15:59:43 +0000586 /** Return the bounds of the current clip (in local coordinates) in the
587 bounds parameter, and return true if it is non-empty. This can be useful
588 in a way similar to quickReject, in that it tells you that drawing
589 outside of these bounds will be clipped out.
590 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000591 virtual bool getClipBounds(SkRect* bounds) const;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000592
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000593 /** Return the bounds of the current clip, in device coordinates; returns
594 true if non-empty. Maybe faster than getting the clip explicitly and
595 then taking its bounds.
596 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +0000597 virtual bool getClipDeviceBounds(SkIRect* bounds) const;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000598
tomhudson@google.combcb671c2011-09-13 15:07:58 +0000599
reed@android.com8a1c16f2008-12-17 15:59:43 +0000600 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000601 specified ARGB color, using the specified mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000602 @param a the alpha component (0..255) of the color to fill the canvas
603 @param r the red component (0..255) of the color to fill the canvas
604 @param g the green component (0..255) of the color to fill the canvas
605 @param b the blue component (0..255) of the color to fill the canvas
606 @param mode the mode to apply the color in (defaults to SrcOver)
607 */
reed374772b2016-10-05 17:33:02 -0700608 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode = SkBlendMode::kSrcOver);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000609
610 /** Fill the entire canvas' bitmap (restricted to the current clip) with the
reed@android.com845fdac2009-06-23 03:01:32 +0000611 specified color and mode.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000612 @param color the color to draw with
613 @param mode the mode to apply the color in (defaults to SrcOver)
614 */
reed374772b2016-10-05 17:33:02 -0700615 void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000616
reedf4e0d9e2014-12-05 20:49:03 -0800617 /**
618 * Helper method for drawing a color in SRC mode, completely replacing all the pixels
619 * in the current clip with this color.
620 */
621 void clear(SkColor color) {
reed374772b2016-10-05 17:33:02 -0700622 this->drawColor(color, SkBlendMode::kSrc);
reed8eddfb52014-12-04 07:50:14 -0800623 }
reed@google.com2a981812011-04-14 18:59:28 +0000624
625 /**
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000626 * This makes the contents of the canvas undefined. Subsequent calls that
627 * require reading the canvas contents will produce undefined results. Examples
628 * include blending and readPixels. The actual implementation is backend-
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800629 * dependent and one legal implementation is to do nothing. This method
630 * ignores the current clip.
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +0000631 *
632 * This function should only be called if the caller intends to subsequently
633 * draw to the canvas. The canvas may do real work at discard() time in order
634 * to optimize performance on subsequent draws. Thus, if you call this and then
635 * never draw to the canvas subsequently you may pay a perfomance penalty.
636 */
637 void discard() { this->onDiscard(); }
638
639 /**
benjaminwagnera1bb8e02015-12-11 14:08:58 -0800640 * Fill the entire canvas (restricted to the current clip) with the
reed@google.com2a981812011-04-14 18:59:28 +0000641 * specified paint.
642 * @param paint The paint used to fill the canvas
643 */
reed0846f1b2015-01-09 14:17:40 -0800644 void drawPaint(const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000645
646 enum PointMode {
647 /** drawPoints draws each point separately */
648 kPoints_PointMode,
649 /** drawPoints draws each pair of points as a line segment */
650 kLines_PointMode,
651 /** drawPoints draws the array of points as a polygon */
652 kPolygon_PointMode
653 };
654
655 /** Draw a series of points, interpreted based on the PointMode mode. For
656 all modes, the count parameter is interpreted as the total number of
657 points. For kLine mode, count/2 line segments are drawn.
658 For kPoint mode, each point is drawn centered at its coordinate, and its
659 size is specified by the paint's stroke-width. It draws as a square,
660 unless the paint's cap-type is round, in which the points are drawn as
661 circles.
662 For kLine mode, each pair of points is drawn as a line segment,
663 respecting the paint's settings for cap/join/width.
664 For kPolygon mode, the entire array is drawn as a series of connected
665 line segments.
666 Note that, while similar, kLine and kPolygon modes draw slightly
667 differently than the equivalent path built with a series of moveto,
668 lineto calls, in that the path will draw all of its contours at once,
669 with no interactions if contours intersect each other (think XOR
670 xfermode). drawPoints always draws each element one at a time.
671 @param mode PointMode specifying how to draw the array of points.
672 @param count The number of points in the array
673 @param pts Array of points to draw
674 @param paint The paint used to draw the points
675 */
reed0846f1b2015-01-09 14:17:40 -0800676 void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000677
678 /** Helper method for drawing a single point. See drawPoints() for a more
679 details.
680 */
681 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +0000682
reed@android.com8a1c16f2008-12-17 15:59:43 +0000683 /** Draws a single pixel in the specified color.
684 @param x The X coordinate of which pixel to draw
685 @param y The Y coordiante of which pixel to draw
686 @param color The color to draw
687 */
688 void drawPoint(SkScalar x, SkScalar y, SkColor color);
689
690 /** Draw a line segment with the specified start and stop x,y coordinates,
691 using the specified paint. NOTE: since a line is always "framed", the
692 paint's Style is ignored.
693 @param x0 The x-coordinate of the start point of the line
694 @param y0 The y-coordinate of the start point of the line
695 @param x1 The x-coordinate of the end point of the line
696 @param y1 The y-coordinate of the end point of the line
697 @param paint The paint used to draw the line
698 */
699 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
700 const SkPaint& paint);
701
702 /** Draw the specified rectangle using the specified paint. The rectangle
703 will be filled or stroked based on the Style in the paint.
704 @param rect The rect to be drawn
705 @param paint The paint used to draw the rect
706 */
reed0846f1b2015-01-09 14:17:40 -0800707 void drawRect(const SkRect& rect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000708
709 /** Draw the specified rectangle using the specified paint. The rectangle
710 will be filled or framed based on the Style in the paint.
711 @param rect The rect to be drawn
712 @param paint The paint used to draw the rect
713 */
reed@google.com87001ed2014-02-17 16:28:05 +0000714 void drawIRect(const SkIRect& rect, const SkPaint& paint) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000715 SkRect r;
716 r.set(rect); // promotes the ints to scalars
717 this->drawRect(r, paint);
718 }
reed@google.com4b226022011-01-11 18:32:13 +0000719
reed@android.com8a1c16f2008-12-17 15:59:43 +0000720 /** Draw the specified rectangle using the specified paint. The rectangle
721 will be filled or framed based on the Style in the paint.
722 @param left The left side of the rectangle to be drawn
723 @param top The top side of the rectangle to be drawn
724 @param right The right side of the rectangle to be drawn
725 @param bottom The bottom side of the rectangle to be drawn
726 @param paint The paint used to draw the rect
727 */
728 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right,
729 SkScalar bottom, const SkPaint& paint);
730
msarett44df6512016-08-25 13:54:30 -0700731 /** Draw the outline of the specified region using the specified paint.
732 @param region The region to be drawn
733 @param paint The paint used to draw the region
734 */
msarettdca352e2016-08-26 06:37:45 -0700735 void drawRegion(const SkRegion& region, const SkPaint& paint);
msarett44df6512016-08-25 13:54:30 -0700736
reed@android.com8a1c16f2008-12-17 15:59:43 +0000737 /** Draw the specified oval using the specified paint. The oval will be
738 filled or framed based on the Style in the paint.
739 @param oval The rectangle bounds of the oval to be drawn
740 @param paint The paint used to draw the oval
741 */
reed0846f1b2015-01-09 14:17:40 -0800742 void drawOval(const SkRect& oval, const SkPaint&);
reed@google.com4ed0fb72012-12-12 20:48:18 +0000743
744 /**
745 * Draw the specified RRect using the specified paint The rrect will be filled or stroked
746 * based on the Style in the paint.
747 *
748 * @param rrect The round-rect to draw
749 * @param paint The paint used to draw the round-rect
750 */
reed0846f1b2015-01-09 14:17:40 -0800751 void drawRRect(const SkRRect& rrect, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000752
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +0000753 /**
754 * Draw the annulus formed by the outer and inner rrects. The results
755 * are undefined if the outer does not contain the inner.
756 */
757 void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&);
758
reed@android.com8a1c16f2008-12-17 15:59:43 +0000759 /** Draw the specified circle using the specified paint. If radius is <= 0,
760 then nothing will be drawn. The circle will be filled
761 or framed based on the Style in the paint.
762 @param cx The x-coordinate of the center of the cirle to be drawn
763 @param cy The y-coordinate of the center of the cirle to be drawn
764 @param radius The radius of the cirle to be drawn
765 @param paint The paint used to draw the circle
766 */
767 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
768 const SkPaint& paint);
769
770 /** Draw the specified arc, which will be scaled to fit inside the
bsalomon21af9ca2016-08-25 12:29:23 -0700771 specified oval. Sweep angles are not treated as modulo 360 and thus can
772 exceed a full sweep of the oval. Note that this differs slightly from
773 SkPath::arcTo, which treats the sweep angle mod 360. If the oval is empty
774 or the sweep angle is zero nothing is drawn. If useCenter is true the oval
775 center is inserted into the implied path before the arc and the path is
776 closed back to the, center forming a wedge. Otherwise, the implied path
777 contains just the arc and is not closed.
bsalomonac3aa242016-08-19 11:25:19 -0700778 @param oval The bounds of oval used to define the shape of the arc.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000779 @param startAngle Starting angle (in degrees) where the arc begins
bsalomonac3aa242016-08-19 11:25:19 -0700780 @param sweepAngle Sweep angle (in degrees) measured clockwise.
bsalomon21af9ca2016-08-25 12:29:23 -0700781 @param useCenter true means include the center of the oval.
reed@android.com8a1c16f2008-12-17 15:59:43 +0000782 @param paint The paint used to draw the arc
783 */
784 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
785 bool useCenter, const SkPaint& paint);
786
787 /** Draw the specified round-rect using the specified paint. The round-rect
788 will be filled or framed based on the Style in the paint.
789 @param rect The rectangular bounds of the roundRect to be drawn
790 @param rx The x-radius of the oval used to round the corners
791 @param ry The y-radius of the oval used to round the corners
792 @param paint The paint used to draw the roundRect
793 */
794 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
795 const SkPaint& paint);
796
797 /** Draw the specified path using the specified paint. The path will be
798 filled or framed based on the Style in the paint.
799 @param path The path to be drawn
800 @param paint The paint used to draw the path
801 */
reed0846f1b2015-01-09 14:17:40 -0800802 void drawPath(const SkPath& path, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000803
piotaixrd52893c2014-09-25 14:39:40 -0700804 /** Draw the specified image, with its top/left corner at (x,y), using the
805 specified paint, transformed by the current matrix.
806
807 @param image The image to be drawn
808 @param left The position of the left side of the image being drawn
809 @param top The position of the top side of the image being drawn
810 @param paint The paint used to draw the image, or NULL
811 */
reed0846f1b2015-01-09 14:17:40 -0800812 void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
reedf8053da2016-03-17 08:14:57 -0700813 void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
814 const SkPaint* paint = NULL) {
815 this->drawImage(image.get(), left, top, paint);
816 }
piotaixrb5fae932014-09-24 13:03:30 -0700817
reeda5517e22015-07-14 10:54:12 -0700818 /**
819 * Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
820 * trading off speed for exactness.
821 *
822 * When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
823 * the pixels in the image. If there is a src-rect specified, it is intended to restrict the
824 * pixels that will be read. However, for performance reasons, some implementations may slow
825 * down if they cannot read 1-pixel past the src-rect boundary at times.
826 *
827 * This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
828 * If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
829 * must be strictly respected, the caller should pass kStrict.
830 */
831 enum SrcRectConstraint {
832 /**
833 * If kStrict is specified, the implementation must respect the src-rect
834 * (if specified) strictly, and will never sample outside of those bounds during sampling
835 * even when filtering. This may be slower than kFast.
836 */
837 kStrict_SrcRectConstraint,
838
839 /**
840 * If kFast is specified, the implementation may sample outside of the src-rect
bsalomon19e82e32015-10-23 09:27:42 -0700841 * (if specified) by half the width of filter. This allows greater flexibility
reeda5517e22015-07-14 10:54:12 -0700842 * to the implementation and can make the draw much faster.
843 */
844 kFast_SrcRectConstraint,
845 };
846
847 /** Draw the specified image, scaling and translating so that it fills the specified
848 * dst rect. If the src rect is non-null, only that subset of the image is transformed
849 * and drawn.
850 *
851 * @param image The image to be drawn
852 * @param src Optional: specify the subset of the image to be drawn
853 * @param dst The destination rectangle where the scaled/translated
854 * image will be drawn
855 * @param paint The paint used to draw the image, or NULL
856 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
857 */
reede47829b2015-08-06 10:02:53 -0700858 void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
859 const SkPaint* paint,
860 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
861 // variant that takes src SkIRect
862 void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
863 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
864 // variant that assumes src == image-bounds
reede47829b2015-08-06 10:02:53 -0700865 void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
866 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700867
reedf8053da2016-03-17 08:14:57 -0700868 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
869 const SkPaint* paint,
870 SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
871 this->drawImageRect(image.get(), src, dst, paint, constraint);
872 }
873 void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
874 const SkPaint* paint, SrcRectConstraint cons = kStrict_SrcRectConstraint) {
875 this->drawImageRect(image.get(), isrc, dst, paint, cons);
876 }
877 void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
878 SrcRectConstraint cons = kStrict_SrcRectConstraint) {
879 this->drawImageRect(image.get(), dst, paint, cons);
880 }
881
reed4c21dc52015-06-25 12:32:03 -0700882 /**
883 * Draw the image stretched differentially to fit into dst.
884 * center is a rect within the image, and logically divides the image
885 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
886 * image is the "center", then the center-rect should be [2, 2, 3, 3].
887 *
888 * If the dst is >= the image size, then...
889 * - The 4 corners are not stretched at all.
890 * - The sides are stretched in only one axis.
891 * - The center is stretched in both axes.
892 * Else, for each axis where dst < image,
893 * - The corners shrink proportionally
894 * - The sides (along the shrink axis) and center are not drawn
895 */
896 void drawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
reedf8053da2016-03-17 08:14:57 -0700897 const SkPaint* paint = nullptr);
898 void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
899 const SkPaint* paint = nullptr) {
900 this->drawImageNine(image.get(), center, dst, paint);
901 }
reed4c21dc52015-06-25 12:32:03 -0700902
reed@android.com8a1c16f2008-12-17 15:59:43 +0000903 /** Draw the specified bitmap, with its top/left corner at (x,y), using the
904 specified paint, transformed by the current matrix. Note: if the paint
905 contains a maskfilter that generates a mask which extends beyond the
906 bitmap's original width/height, then the bitmap will be drawn as if it
907 were in a Shader with CLAMP mode. Thus the color outside of the original
908 width/height will be the edge color replicated.
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000909
910 If a shader is present on the paint it will be ignored, except in the
reed@google.comf20fc242014-03-26 13:44:58 +0000911 case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
commit-bot@chromium.org91246b92013-12-05 15:43:19 +0000912 generated by the shader.
913
reed@android.com8a1c16f2008-12-17 15:59:43 +0000914 @param bitmap The bitmap to be drawn
915 @param left The position of the left side of the bitmap being drawn
916 @param top The position of the top side of the bitmap being drawn
917 @param paint The paint used to draw the bitmap, or NULL
918 */
reed0846f1b2015-01-09 14:17:40 -0800919 void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
920 const SkPaint* paint = NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000921
reeda5517e22015-07-14 10:54:12 -0700922 /** Draw the specified bitmap, scaling and translating so that it fills the specified
923 * dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
924 * and drawn.
925 *
926 * @param bitmap The bitmap to be drawn
927 * @param src Optional: specify the subset of the bitmap to be drawn
928 * @param dst The destination rectangle where the scaled/translated
929 * bitmap will be drawn
930 * @param paint The paint used to draw the bitmap, or NULL
931 * @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
932 */
reede47829b2015-08-06 10:02:53 -0700933 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
reed84984ef2015-07-17 07:09:43 -0700934 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700935 // variant where src is SkIRect
reed84984ef2015-07-17 07:09:43 -0700936 void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
937 const SkPaint* paint, SrcRectConstraint = kStrict_SrcRectConstraint);
reede47829b2015-08-06 10:02:53 -0700938 void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
bsalomon19e82e32015-10-23 09:27:42 -0700939 SrcRectConstraint = kStrict_SrcRectConstraint);
reed84984ef2015-07-17 07:09:43 -0700940
reed@google.comf0b5e112011-09-07 11:57:34 +0000941 /**
msarettc573a402016-08-02 08:05:56 -0700942 * Draw the bitmap stretched or shrunk differentially to fit into dst.
reed@google.comf0b5e112011-09-07 11:57:34 +0000943 * center is a rect within the bitmap, and logically divides the bitmap
944 * into 9 sections (3x3). For example, if the middle pixel of a [5x5]
945 * bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
946 *
947 * If the dst is >= the bitmap size, then...
robertphillips@google.com9bf380c2013-07-25 12:10:42 +0000948 * - The 4 corners are not stretched at all.
949 * - The sides are stretched in only one axis.
950 * - The center is stretched in both axes.
reed@google.comf0b5e112011-09-07 11:57:34 +0000951 * Else, for each axis where dst < bitmap,
952 * - The corners shrink proportionally
953 * - The sides (along the shrink axis) and center are not drawn
954 */
reed0846f1b2015-01-09 14:17:40 -0800955 void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
956 const SkPaint* paint = NULL);
reed@google.comf0b5e112011-09-07 11:57:34 +0000957
msarettc573a402016-08-02 08:05:56 -0700958 /**
959 * Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
msarett71df2d72016-09-30 12:41:42 -0700960 *
961 * If the lattice divs or bounds are invalid, the entire lattice
962 * struct will be ignored on the draw call.
msarettc573a402016-08-02 08:05:56 -0700963 */
964 struct Lattice {
msarett0764efe2016-09-02 11:24:30 -0700965 enum Flags : uint8_t {
966 // If set, indicates that we should not draw corresponding rect.
967 kTransparent_Flags = 1 << 0,
968 };
msarettc573a402016-08-02 08:05:56 -0700969
msarett0764efe2016-09-02 11:24:30 -0700970 // An array of x-coordinates that divide the bitmap vertically.
msarett71df2d72016-09-30 12:41:42 -0700971 // These must be unique, increasing, and in the set [fBounds.fLeft, fBounds.fRight).
msarett0764efe2016-09-02 11:24:30 -0700972 // Does not have ownership.
msarett71df2d72016-09-30 12:41:42 -0700973 const int* fXDivs;
msarettc573a402016-08-02 08:05:56 -0700974
975 // An array of y-coordinates that divide the bitmap horizontally.
msarett71df2d72016-09-30 12:41:42 -0700976 // These must be unique, increasing, and in the set [fBounds.fTop, fBounds.fBottom).
msarettc573a402016-08-02 08:05:56 -0700977 // Does not have ownership.
msarett71df2d72016-09-30 12:41:42 -0700978 const int* fYDivs;
msarett0764efe2016-09-02 11:24:30 -0700979
980 // If non-null, the length of this array must be equal to
981 // (fXCount + 1) * (fYCount + 1). Note that we allow the first rect
msarett71df2d72016-09-30 12:41:42 -0700982 // in each direction to be empty (ex: fXDivs[0] = fBounds.fLeft).
983 // In this case, the caller still must specify a flag (as a placeholder)
984 // for these empty rects.
msarett0764efe2016-09-02 11:24:30 -0700985 // The flags correspond to the rects in the lattice, first moving
986 // left to right and then top to bottom.
msarett71df2d72016-09-30 12:41:42 -0700987 const Flags* fFlags;
msarett0764efe2016-09-02 11:24:30 -0700988
989 // The number of fXDivs.
msarett71df2d72016-09-30 12:41:42 -0700990 int fXCount;
msarettc573a402016-08-02 08:05:56 -0700991
992 // The number of fYDivs.
msarett71df2d72016-09-30 12:41:42 -0700993 int fYCount;
994
995 // The bound to draw from. Must be contained by the src that is being drawn,
996 // non-empty, and non-inverted.
997 // If nullptr, the bounds are the entire src.
998 const SkIRect* fBounds;
msarettc573a402016-08-02 08:05:56 -0700999 };
1000
1001 /**
1002 * Draw the bitmap stretched or shrunk differentially to fit into dst.
1003 *
1004 * Moving horizontally across the bitmap, alternating rects will be "scalable"
1005 * (in the x-dimension) to fit into dst or must be left "fixed". The first rect
1006 * is treated as "fixed", but it's possible to specify an empty first rect by
1007 * making lattice.fXDivs[0] = 0.
1008 *
1009 * The scale factor for all "scalable" rects will be the same, and may be greater
1010 * than or less than 1 (meaning we can stretch or shrink). If the number of
1011 * "fixed" pixels is greater than the width of the dst, we will collapse all of
1012 * the "scalable" regions and appropriately downscale the "fixed" regions.
1013 *
1014 * The same interpretation also applies to the y-dimension.
1015 */
1016 void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1017 const SkPaint* paint = nullptr);
1018 void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1019 const SkPaint* paint = nullptr);
1020
reed@android.com8a1c16f2008-12-17 15:59:43 +00001021 /** Draw the text, with origin at (x,y), using the specified paint.
1022 The origin is interpreted based on the Align setting in the paint.
1023 @param text The text to be drawn
1024 @param byteLength The number of bytes to read from the text parameter
1025 @param x The x-coordinate of the origin of the text being drawn
1026 @param y The y-coordinate of the origin of the text being drawn
1027 @param paint The paint used for the text (e.g. color, size, style)
1028 */
reedf7430cc2014-12-21 11:38:35 -08001029 void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
1030 const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001031
1032 /** Draw the text, with each character/glyph origin specified by the pos[]
reed@google.com4b226022011-01-11 18:32:13 +00001033 array. The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001034 @param text The text to be drawn
1035 @param byteLength The number of bytes to read from the text parameter
1036 @param pos Array of positions, used to position each character
1037 @param paint The paint used for the text (e.g. color, size, style)
1038 */
reedf7430cc2014-12-21 11:38:35 -08001039 void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
1040 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +00001041
reed@android.com8a1c16f2008-12-17 15:59:43 +00001042 /** Draw the text, with each character/glyph origin specified by the x
1043 coordinate taken from the xpos[] array, and the y from the constY param.
reed@google.com4b226022011-01-11 18:32:13 +00001044 The origin is interpreted by the Align setting in the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001045 @param text The text to be drawn
1046 @param byteLength The number of bytes to read from the text parameter
1047 @param xpos Array of x-positions, used to position each character
1048 @param constY The shared Y coordinate for all of the positions
1049 @param paint The paint used for the text (e.g. color, size, style)
1050 */
reedf7430cc2014-12-21 11:38:35 -08001051 void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
1052 const SkPaint& paint);
reed@google.com4b226022011-01-11 18:32:13 +00001053
reed@android.com8a1c16f2008-12-17 15:59:43 +00001054 /** Draw the text, with origin at (x,y), using the specified paint, along
1055 the specified path. The paint's Align setting determins where along the
1056 path to start the text.
1057 @param text The text to be drawn
1058 @param byteLength The number of bytes to read from the text parameter
1059 @param path The path the text should follow for its baseline
1060 @param hOffset The distance along the path to add to the text's
1061 starting position
1062 @param vOffset The distance above(-) or below(+) the path to
1063 position the text
1064 @param paint The paint used for the text
1065 */
reedf7430cc2014-12-21 11:38:35 -08001066 void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
reed@android.com8a1c16f2008-12-17 15:59:43 +00001067 SkScalar vOffset, const SkPaint& paint);
1068
1069 /** Draw the text, with origin at (x,y), using the specified paint, along
1070 the specified path. The paint's Align setting determins where along the
1071 path to start the text.
1072 @param text The text to be drawn
1073 @param byteLength The number of bytes to read from the text parameter
1074 @param path The path the text should follow for its baseline
1075 @param matrix (may be null) Applied to the text before it is
1076 mapped onto the path
1077 @param paint The paint used for the text
1078 */
reedf7430cc2014-12-21 11:38:35 -08001079 void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
1080 const SkMatrix* matrix, const SkPaint& paint);
reed@android.com8a1c16f2008-12-17 15:59:43 +00001081
reed45561a02016-07-07 12:47:17 -07001082 /**
1083 * Draw the text with each character/glyph individually transformed by its xform.
1084 * If cullRect is not null, it is a conservative bounds of what will be drawn
reed63f30d92016-07-07 16:32:51 -07001085 * taking into account the xforms and the paint, and will be used to accelerate culling.
reed45561a02016-07-07 12:47:17 -07001086 */
1087 void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
1088 const SkRect* cullRect, const SkPaint& paint);
1089
fmalita00d5c2c2014-08-21 08:53:26 -07001090 /** Draw the text blob, offset by (x,y), using the specified paint.
1091 @param blob The text blob to be drawn
1092 @param x The x-offset of the text being drawn
1093 @param y The y-offset of the text being drawn
1094 @param paint The paint used for the text (e.g. color, size, style)
1095 */
1096 void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
reed2ab90572016-08-10 14:16:41 -07001097 void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
1098 this->drawTextBlob(blob.get(), x, y, paint);
1099 }
fmalita00d5c2c2014-08-21 08:53:26 -07001100
reed@android.com8a1c16f2008-12-17 15:59:43 +00001101 /** Draw the picture into this canvas. This method effective brackets the
1102 playback of the picture's draw calls with save/restore, so the state
djsollen@google.coma44de962013-01-02 16:59:19 +00001103 of this canvas will be unchanged after this call.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001104 @param picture The recorded drawing commands to playback into this
1105 canvas.
1106 */
reed1c2c4412015-04-30 13:09:24 -07001107 void drawPicture(const SkPicture* picture) {
1108 this->drawPicture(picture, NULL, NULL);
1109 }
reedca2622b2016-03-18 07:25:55 -07001110 void drawPicture(const sk_sp<SkPicture>& picture) {
reedf8053da2016-03-17 08:14:57 -07001111 this->drawPicture(picture.get());
1112 }
robertphillips9b14f262014-06-04 05:40:44 -07001113
reedd5fa1a42014-08-09 11:08:05 -07001114 /**
1115 * Draw the picture into this canvas.
1116 *
1117 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1118 * logically equivalent to
1119 * save/concat/drawPicture/restore
1120 *
1121 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1122 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1123 * This is logically equivalent to
1124 * saveLayer(paint)/drawPicture/restore
1125 */
1126 void drawPicture(const SkPicture*, const SkMatrix* matrix, const SkPaint* paint);
reedca2622b2016-03-18 07:25:55 -07001127 void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) {
reedf8053da2016-03-17 08:14:57 -07001128 this->drawPicture(picture.get(), matrix, paint);
1129 }
reedd5fa1a42014-08-09 11:08:05 -07001130
vjiaoblack95302da2016-07-21 10:25:54 -07001131#ifdef SK_EXPERIMENTAL_SHADOWING
1132 /**
vjiaoblacke6f5d562016-08-25 06:30:23 -07001133 * Draw the picture into this canvas, with shadows!
vjiaoblack95302da2016-07-21 10:25:54 -07001134 *
1135 * We will use the canvas's lights along with the picture information (draw depths of
1136 * objects, etc) to first create a set of shadowmaps for the light-picture pairs, and
1137 * then use that set of shadowmaps to render the scene with shadows.
1138 *
1139 * If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1140 * logically equivalent to
1141 * save/concat/drawPicture/restore
1142 *
1143 * If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1144 * alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1145 * This is logically equivalent to
1146 * saveLayer(paint)/drawPicture/restore
1147 *
vjiaoblacke6f5d562016-08-25 06:30:23 -07001148 * We also support using variance shadow maps for blurred shadows; the user can specify
1149 * what shadow mapping algorithm to use with params.
1150 * - Variance Shadow Mapping works by storing both the depth and depth^2 in the shadow map.
1151 * - Then, the shadow map can be blurred, and when reading from it, the fragment shader
1152 * can calculate the variance of the depth at a position by doing E(x^2) - E(x)^2.
1153 * - We can then use the depth variance and depth at a fragment to arrive at an upper bound
1154 * of the probability that the current surface is shadowed by using Chebyshev's
1155 * inequality, and then use that to shade the fragment.
1156 *
1157 * - There are a few problems with VSM.
1158 * * Light Bleeding | Areas with high variance, such as near the edges of high up rects,
1159 * will cause their shadow penumbras to overwrite otherwise solid
1160 * shadows.
1161 * * Shape Distortion | We can combat Light Bleeding by biasing the shadow (setting
1162 * mostly shaded fragments to completely shaded) and increasing
1163 * the minimum allowed variance. However, this warps and rounds
1164 * out the shape of the shadow.
vjiaoblack95302da2016-07-21 10:25:54 -07001165 */
1166 void drawShadowedPicture(const SkPicture*,
1167 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -07001168 const SkPaint* paint,
1169 const SkShadowParams& params);
vjiaoblack95302da2016-07-21 10:25:54 -07001170 void drawShadowedPicture(const sk_sp<SkPicture>& picture,
1171 const SkMatrix* matrix,
vjiaoblacke6f5d562016-08-25 06:30:23 -07001172 const SkPaint* paint,
1173 const SkShadowParams& params) {
1174 this->drawShadowedPicture(picture.get(), matrix, paint, params);
vjiaoblack95302da2016-07-21 10:25:54 -07001175 }
1176#endif
1177
reed@android.com8a1c16f2008-12-17 15:59:43 +00001178 enum VertexMode {
1179 kTriangles_VertexMode,
1180 kTriangleStrip_VertexMode,
1181 kTriangleFan_VertexMode
1182 };
reed@google.com4b226022011-01-11 18:32:13 +00001183
reed@android.com8a1c16f2008-12-17 15:59:43 +00001184 /** Draw the array of vertices, interpreted as triangles (based on mode).
commit-bot@chromium.org559a8832014-05-30 10:08:22 +00001185
1186 If both textures and vertex-colors are NULL, it strokes hairlines with
1187 the paint's color. This behavior is a useful debugging mode to visualize
1188 the mesh.
1189
reed@android.com8a1c16f2008-12-17 15:59:43 +00001190 @param vmode How to interpret the array of vertices
1191 @param vertexCount The number of points in the vertices array (and
1192 corresponding texs and colors arrays if non-null)
1193 @param vertices Array of vertices for the mesh
1194 @param texs May be null. If not null, specifies the coordinate
robertphillips@google.com631a59b2013-07-31 14:57:53 +00001195 in _texture_ space (not uv space) for each vertex.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001196 @param colors May be null. If not null, specifies a color for each
1197 vertex, to be interpolated across the triangle.
Mike Reed7d954ad2016-10-28 15:42:34 -04001198 @param mode Used if both texs and colors are present. In this
reed@android.com8a1c16f2008-12-17 15:59:43 +00001199 case the colors are combined with the texture using mode,
Mike Reed7d954ad2016-10-28 15:42:34 -04001200 before being drawn using the paint.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001201 @param indices If not null, array of indices to reference into the
1202 vertex (texs, colors) array.
1203 @param indexCount number of entries in the indices array (if not null)
reed@google.com4b226022011-01-11 18:32:13 +00001204 @param paint Specifies the shader/texture if present.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001205 */
reed0846f1b2015-01-09 14:17:40 -08001206 void drawVertices(VertexMode vmode, int vertexCount,
1207 const SkPoint vertices[], const SkPoint texs[],
Mike Reed7d954ad2016-10-28 15:42:34 -04001208 const SkColor colors[], SkBlendMode mode,
reed0846f1b2015-01-09 14:17:40 -08001209 const uint16_t indices[], int indexCount,
1210 const SkPaint& paint);
reedcfb6bdf2016-03-29 11:32:50 -07001211 void drawVertices(VertexMode vmode, int vertexCount,
1212 const SkPoint vertices[], const SkPoint texs[],
Mike Reed7d954ad2016-10-28 15:42:34 -04001213 const SkColor colors[], const uint16_t indices[], int indexCount,
1214 const SkPaint& paint) {
1215 this->drawVertices(vmode, vertexCount, vertices, texs, colors, SkBlendMode::kModulate,
1216 indices, indexCount, paint);
1217 }
1218
dandovb3c9d1c2014-08-12 08:34:29 -07001219 /**
1220 Draw a cubic coons patch
mtklein6cfa73a2014-08-13 13:33:49 -07001221
dandovb3c9d1c2014-08-12 08:34:29 -07001222 @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1223 starting at the top left corner.
1224 @param colors specifies the colors for the corners which will be bilerp across the patch,
1225 their order is clockwise starting at the top left corner.
mtklein6cfa73a2014-08-13 13:33:49 -07001226 @param texCoords specifies the texture coordinates that will be bilerp across the patch,
dandovb3c9d1c2014-08-12 08:34:29 -07001227 their order is the same as the colors.
Mike Reed7d954ad2016-10-28 15:42:34 -04001228 @param mode specifies how are the colors and the textures combined if both of them are
dandovb3c9d1c2014-08-12 08:34:29 -07001229 present.
dandov963137b2014-08-07 07:49:53 -07001230 @param paint Specifies the shader/texture if present.
1231 */
dandovb3c9d1c2014-08-12 08:34:29 -07001232 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
Mike Reed7d954ad2016-10-28 15:42:34 -04001233 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
1234 void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1235 const SkPoint texCoords[4], const SkPaint& paint) {
1236 this->drawPatch(cubics, colors, texCoords, SkBlendMode::kModulate, paint);
1237 }
1238
reed3cb38402015-02-06 08:36:15 -08001239 /**
reed71c3c762015-06-24 10:29:17 -07001240 * Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
1241 * coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
1242 * into a quad.
1243 *
1244 * xform maps [0, 0, tex.width, tex.height] -> quad
1245 *
1246 * The color array is optional. When specified, each color modulates the pixels in its
Mike Reed7d954ad2016-10-28 15:42:34 -04001247 * corresponding quad (via the specified SkBlendMode).
reed71c3c762015-06-24 10:29:17 -07001248 *
1249 * The cullRect is optional. When specified, it must be a conservative bounds of all of the
1250 * resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
1251 * intersect the current clip.
1252 *
1253 * The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
Mike Reed7d954ad2016-10-28 15:42:34 -04001254 * and blendmode are used to affect each of the quads.
reed71c3c762015-06-24 10:29:17 -07001255 */
1256 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
Mike Reed7d954ad2016-10-28 15:42:34 -04001257 const SkColor colors[], int count, SkBlendMode, const SkRect* cullRect,
reed71c3c762015-06-24 10:29:17 -07001258 const SkPaint* paint);
Mike Reed7d954ad2016-10-28 15:42:34 -04001259 void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1260 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
1261 const SkPaint* paint) {
1262 this->drawAtlas(atlas.get(), xform, tex, colors, count, mode, cullRect, paint);
1263 }
reed71c3c762015-06-24 10:29:17 -07001264 void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
1265 const SkRect* cullRect, const SkPaint* paint) {
Mike Reed7d954ad2016-10-28 15:42:34 -04001266 this->drawAtlas(atlas, xform, tex, nullptr, count, SkBlendMode::kDst, cullRect, paint);
1267 }
1268 void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1269 int count, const SkRect* cullRect, const SkPaint* paint) {
1270 this->drawAtlas(atlas.get(), xform, tex, nullptr, count, SkBlendMode::kDst,
1271 cullRect, paint);
1272 }
1273
reed71c3c762015-06-24 10:29:17 -07001274 /**
reed3cb38402015-02-06 08:36:15 -08001275 * Draw the contents of this drawable into the canvas. If the canvas is async
1276 * (e.g. it is recording into a picture) then the drawable will be referenced instead,
1277 * to have its draw() method called when the picture is finalized.
1278 *
1279 * If the intent is to force the contents of the drawable into this canvas immediately,
1280 * then drawable->draw(canvas) may be called.
1281 */
reeda8db7282015-07-07 10:22:31 -07001282 void drawDrawable(SkDrawable* drawable, const SkMatrix* = NULL);
1283 void drawDrawable(SkDrawable*, SkScalar x, SkScalar y);
reed6a070dc2014-11-11 19:36:09 -08001284
reedf70b5312016-03-04 16:36:20 -08001285 /**
1286 * Send an "annotation" to the canvas. The annotation is a key/value pair, where the key is
1287 * a null-terminated utf8 string, and the value is a blob of data stored in an SkData
1288 * (which may be null). The annotation is associated with the specified rectangle.
1289 *
1290 * The caller still retains its ownership of the data (if any).
1291 *
1292 * Note: on may canvas types, this information is ignored, but some canvases (e.g. recording
1293 * a picture or drawing to a PDF document) will pass on this information.
1294 */
1295 void drawAnnotation(const SkRect&, const char key[], SkData* value);
mtklein0fba3b92016-04-01 04:55:51 -07001296 void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
1297 this->drawAnnotation(rect, key, value.get());
1298 }
reedf70b5312016-03-04 16:36:20 -08001299
reed@android.com8a1c16f2008-12-17 15:59:43 +00001300 //////////////////////////////////////////////////////////////////////////
fmalita77650002016-01-21 18:47:11 -08001301#ifdef SK_INTERNAL
fmalita53d9f1c2016-01-25 06:23:54 -08001302#ifndef SK_SUPPORT_LEGACY_DRAWFILTER
1303 #define SK_SUPPORT_LEGACY_DRAWFILTER
fmalita77650002016-01-21 18:47:11 -08001304#endif
1305#endif
reed@google.com4b226022011-01-11 18:32:13 +00001306
fmalita53d9f1c2016-01-25 06:23:54 -08001307#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
reed@android.com8a1c16f2008-12-17 15:59:43 +00001308 /** Get the current filter object. The filter's reference count is not
reed@android.comdc3381f2010-02-11 16:05:15 +00001309 affected. The filter is saved/restored, just like the matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001310 @return the canvas' filter (or NULL).
1311 */
fmalita77650002016-01-21 18:47:11 -08001312 SK_ATTR_EXTERNALLY_DEPRECATED("getDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001313 SkDrawFilter* getDrawFilter() const;
reed@google.com4b226022011-01-11 18:32:13 +00001314
reed@android.com8a1c16f2008-12-17 15:59:43 +00001315 /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1316 As a convenience, the parameter is returned. If an existing filter
1317 exists, its refcnt is decrement. If the new filter is not null, its
reed@android.comdc3381f2010-02-11 16:05:15 +00001318 refcnt is incremented. The filter is saved/restored, just like the
1319 matrix and clip.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001320 @param filter the new filter (or NULL)
1321 @return the new filter
1322 */
fmalita77650002016-01-21 18:47:11 -08001323 SK_ATTR_EXTERNALLY_DEPRECATED("setDrawFilter use is deprecated")
reed@android.com8a1c16f2008-12-17 15:59:43 +00001324 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
fmalita77650002016-01-21 18:47:11 -08001325#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +00001326 //////////////////////////////////////////////////////////////////////////
1327
reed@google.com754de5f2014-02-24 19:38:20 +00001328 /**
1329 * Return true if the current clip is empty (i.e. nothing will draw).
1330 * Note: this is not always a free call, so it should not be used
1331 * more often than necessary. However, once the canvas has computed this
1332 * result, subsequent calls will be cheap (until the clip state changes,
1333 * which can happen on any clip..() or restore() call.
1334 */
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001335 virtual bool isClipEmpty() const;
reed@google.com754de5f2014-02-24 19:38:20 +00001336
commit-bot@chromium.org5c70cdc2014-03-08 03:57:19 +00001337 /**
1338 * Returns true if the current clip is just a (non-empty) rectangle.
1339 * Returns false if the clip is empty, or if it is complex.
1340 */
1341 virtual bool isClipRect() const;
1342
reed@android.com8a1c16f2008-12-17 15:59:43 +00001343 /** Return the current matrix on the canvas.
1344 This does not account for the translate in any of the devices.
1345 @return The current matrix on the canvas.
1346 */
junov@chromium.orga907ac32012-02-24 21:54:07 +00001347 const SkMatrix& getTotalMatrix() const;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001348
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001349 /** Return the clip stack. The clip stack stores all the individual
1350 * clips organized by the save/restore frame in which they were
1351 * added.
1352 * @return the current clip stack ("list" of individual clip elements)
1353 */
1354 const SkClipStack* getClipStack() const {
bungeman6bd52842016-10-27 09:30:08 -07001355 return fClipStack.get();
robertphillips@google.com40a1ae42012-07-13 15:36:15 +00001356 }
1357
fmalitac3b589a2014-06-05 12:40:07 -07001358 typedef SkCanvasClipVisitor ClipVisitor;
reed@google.com90c07ea2012-04-13 13:50:27 +00001359 /**
1360 * Replays the clip operations, back to front, that have been applied to
1361 * the canvas, calling the appropriate method on the visitor for each
1362 * clip. All clips have already been transformed into device space.
1363 */
1364 void replayClips(ClipVisitor*) const;
1365
reed@android.com8a1c16f2008-12-17 15:59:43 +00001366 ///////////////////////////////////////////////////////////////////////////
1367
robertphillips36736a22016-04-23 08:26:43 -07001368 // don't call
Brian Osman11052242016-10-27 14:47:55 -04001369 GrRenderTargetContext* internal_private_accessTopLayerRenderTargetContext();
robertphillips36736a22016-04-23 08:26:43 -07001370
1371 // don't call
1372 static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1373 static bool Internal_Private_GetIgnoreSaveLayerBounds();
1374 static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1375 static bool Internal_Private_GetTreatSpriteAsBitmap();
1376
1377 // TEMP helpers until we switch virtual over to const& for src-rect
1378 void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1379 const SkPaint* paint,
1380 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1381 void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1382 const SkPaint* paint,
1383 SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1384
tomhudsoncb3bd182016-05-18 07:24:16 -07001385 // expose minimum amount of information necessary for transitional refactoring
1386 /**
1387 * Returns CTM and clip bounds, translated from canvas coordinates to top layer coordinates.
1388 */
1389 void temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds);
1390
robertphillipsda2cd8b2016-04-21 11:05:32 -07001391protected:
vjiaoblack95302da2016-07-21 10:25:54 -07001392#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -07001393 /** Returns the current (cumulative) draw depth of the canvas.
1394 */
1395 SkScalar getZ() const;
1396
vjiaoblack95302da2016-07-21 10:25:54 -07001397 sk_sp<SkLights> fLights;
1398#endif
1399
reed@google.com76f10a32014-02-05 15:32:21 +00001400 // default impl defers to getDevice()->newSurface(info)
reede8f30622016-03-23 18:59:25 -07001401 virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&);
reed@google.com76f10a32014-02-05 15:32:21 +00001402
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001403 // default impl defers to its device
reed884e97c2015-05-26 11:31:54 -07001404 virtual bool onPeekPixels(SkPixmap*);
1405 virtual bool onAccessTopLayerPixels(SkPixmap*);
reedea5a6512016-07-07 16:44:27 -07001406 virtual SkImageInfo onImageInfo() const;
1407 virtual bool onGetProps(SkSurfaceProps*) const;
1408 virtual void onFlush();
commit-bot@chromium.orgc3bd8af2014-02-13 17:14:46 +00001409
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001410 // Subclass save/restore notifiers.
1411 // Overriders should call the corresponding INHERITED method up the inheritance chain.
reed4960eee2015-12-18 07:09:18 -08001412 // getSaveLayerStrategy()'s return value may suppress full layer allocation.
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001413 enum SaveLayerStrategy {
1414 kFullLayer_SaveLayerStrategy,
reed4960eee2015-12-18 07:09:18 -08001415 kNoLayer_SaveLayerStrategy,
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001416 };
commit-bot@chromium.orge54a23f2014-03-12 20:21:48 +00001417
fmalita6ca763f2014-06-17 13:52:18 -07001418 virtual void willSave() {}
reed4960eee2015-12-18 07:09:18 -08001419 // Overriders should call the corresponding INHERITED method up the inheritance chain.
1420 virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) {
1421 return kFullLayer_SaveLayerStrategy;
1422 }
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001423 virtual void willRestore() {}
mtklein6cfa73a2014-08-13 13:33:49 -07001424 virtual void didRestore() {}
commit-bot@chromium.orgfc6dfba2014-05-14 13:13:44 +00001425 virtual void didConcat(const SkMatrix&) {}
1426 virtual void didSetMatrix(const SkMatrix&) {}
mtkleincbdf0072016-08-19 09:05:27 -07001427 virtual void didTranslate(SkScalar dx, SkScalar dy) {
1428 this->didConcat(SkMatrix::MakeTrans(dx, dy));
1429 }
vjiaoblack95302da2016-07-21 10:25:54 -07001430
1431#ifdef SK_EXPERIMENTAL_SHADOWING
vjiaoblacke5de1302016-07-13 14:05:28 -07001432 virtual void didTranslateZ(SkScalar) {}
vjiaoblack95302da2016-07-21 10:25:54 -07001433#endif
commit-bot@chromium.org44c48d02014-03-13 20:03:58 +00001434
reedf70b5312016-03-04 16:36:20 -08001435 virtual void onDrawAnnotation(const SkRect&, const char key[], SkData* value);
commit-bot@chromium.orged9806f2014-02-21 02:32:36 +00001436 virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
1437
reed@google.come0d9ce82014-04-23 04:00:17 +00001438 virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1439 SkScalar y, const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001440
reed@google.come0d9ce82014-04-23 04:00:17 +00001441 virtual void onDrawPosText(const void* text, size_t byteLength,
1442 const SkPoint pos[], const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001443
reed@google.come0d9ce82014-04-23 04:00:17 +00001444 virtual void onDrawPosTextH(const void* text, size_t byteLength,
1445 const SkScalar xpos[], SkScalar constY,
1446 const SkPaint& paint);
skia.committer@gmail.comb0430d02014-04-24 03:05:07 +00001447
reed@google.come0d9ce82014-04-23 04:00:17 +00001448 virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1449 const SkPath& path, const SkMatrix* matrix,
1450 const SkPaint& paint);
reed45561a02016-07-07 12:47:17 -07001451 virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
1452 const SkRect* cullRect, const SkPaint& paint);
mtklein6cfa73a2014-08-13 13:33:49 -07001453
fmalita00d5c2c2014-08-21 08:53:26 -07001454 virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1455 const SkPaint& paint);
1456
dandovb3c9d1c2014-08-12 08:34:29 -07001457 virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
Mike Reedfaba3712016-11-03 14:45:31 -04001458 const SkPoint texCoords[4], SkBlendMode, const SkPaint& paint);
reed@google.come0d9ce82014-04-23 04:00:17 +00001459
reeda8db7282015-07-07 10:22:31 -07001460 virtual void onDrawDrawable(SkDrawable*, const SkMatrix*);
reed6a070dc2014-11-11 19:36:09 -08001461
reed41af9662015-01-05 07:49:08 -08001462 virtual void onDrawPaint(const SkPaint&);
1463 virtual void onDrawRect(const SkRect&, const SkPaint&);
msarett44df6512016-08-25 13:54:30 -07001464 virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
reed41af9662015-01-05 07:49:08 -08001465 virtual void onDrawOval(const SkRect&, const SkPaint&);
bsalomonac3aa242016-08-19 11:25:19 -07001466 virtual void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
1467 const SkPaint&);
reed41af9662015-01-05 07:49:08 -08001468 virtual void onDrawRRect(const SkRRect&, const SkPaint&);
1469 virtual void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&);
1470 virtual void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[],
Mike Reedfaba3712016-11-03 14:45:31 -04001471 const SkPoint texs[], const SkColor colors[], SkBlendMode,
reed41af9662015-01-05 07:49:08 -08001472 const uint16_t indices[], int indexCount, const SkPaint&);
mtklein2766c002015-06-26 11:45:03 -07001473
reed71c3c762015-06-24 10:29:17 -07001474 virtual void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
Mike Reedfaba3712016-11-03 14:45:31 -04001475 int count, SkBlendMode, const SkRect* cull, const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001476 virtual void onDrawPath(const SkPath&, const SkPaint&);
1477 virtual void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*);
reed562fe472015-07-28 07:35:14 -07001478 virtual void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
1479 SrcRectConstraint);
reed4c21dc52015-06-25 12:32:03 -07001480 virtual void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,
1481 const SkPaint*);
msarett16882062016-08-16 09:31:08 -07001482 virtual void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
1483 const SkPaint*);
reed4c21dc52015-06-25 12:32:03 -07001484
reed41af9662015-01-05 07:49:08 -08001485 virtual void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*);
1486 virtual void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
reed562fe472015-07-28 07:35:14 -07001487 SrcRectConstraint);
reed41af9662015-01-05 07:49:08 -08001488 virtual void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
1489 const SkPaint*);
msarett16882062016-08-16 09:31:08 -07001490 virtual void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
1491 const SkPaint*);
reed41af9662015-01-05 07:49:08 -08001492
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001493 enum ClipEdgeStyle {
1494 kHard_ClipEdgeStyle,
1495 kSoft_ClipEdgeStyle
1496 };
1497
reed73603f32016-09-20 08:42:38 -07001498 virtual void onClipRect(const SkRect& rect, ClipOp, ClipEdgeStyle);
1499 virtual void onClipRRect(const SkRRect& rrect, ClipOp, ClipEdgeStyle);
1500 virtual void onClipPath(const SkPath& path, ClipOp, ClipEdgeStyle);
1501 virtual void onClipRegion(const SkRegion& deviceRgn, ClipOp);
robertphillips@google.com8f90a892014-02-28 18:19:39 +00001502
commit-bot@chromium.org28361fa2014-03-28 16:08:05 +00001503 virtual void onDiscard();
1504
reedd5fa1a42014-08-09 11:08:05 -07001505 virtual void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*);
robertphillips9b14f262014-06-04 05:40:44 -07001506
vjiaoblack95302da2016-07-21 10:25:54 -07001507#ifdef SK_EXPERIMENTAL_SHADOWING
1508 virtual void onDrawShadowedPicture(const SkPicture*,
1509 const SkMatrix*,
vjiaoblacke6f5d562016-08-25 06:30:23 -07001510 const SkPaint*,
1511 const SkShadowParams& params);
vjiaoblack95302da2016-07-21 10:25:54 -07001512#endif
Herb Derby13569782016-10-06 14:33:43 -04001513
junov@chromium.orga907ac32012-02-24 21:54:07 +00001514 // Clip rectangle bounds. Called internally by saveLayer.
1515 // returns false if the entire rectangle is entirely clipped out
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001516 // If non-NULL, The imageFilter parameter will be used to expand the clip
1517 // and offscreen bounds for any margin required by the filter DAG.
reed4960eee2015-12-18 07:09:18 -08001518 bool clipRectBounds(const SkRect* bounds, SaveLayerFlags, SkIRect* intersection,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +00001519 const SkImageFilter* imageFilter = NULL);
junov@chromium.orga907ac32012-02-24 21:54:07 +00001520
reedc83a2972015-07-16 07:40:45 -07001521private:
reed3aafe112016-08-18 12:45:34 -07001522 /** After calling saveLayer(), there can be any number of devices that make
1523 up the top-most drawing area. LayerIter can be used to iterate through
1524 those devices. Note that the iterator is only valid until the next API
1525 call made on the canvas. Ownership of all pointers in the iterator stays
1526 with the canvas, so none of them should be modified or deleted.
1527 */
1528 class LayerIter /*: SkNoncopyable*/ {
1529 public:
1530 /** Initialize iterator with canvas, and set values for 1st device */
1531 LayerIter(SkCanvas*);
1532 ~LayerIter();
1533
1534 /** Return true if the iterator is done */
1535 bool done() const { return fDone; }
1536 /** Cycle to the next device */
1537 void next();
1538
1539 // These reflect the current device in the iterator
1540
1541 SkBaseDevice* device() const;
1542 const SkMatrix& matrix() const;
1543 const SkRasterClip& clip() const;
1544 const SkPaint& paint() const;
1545 int x() const;
1546 int y() const;
1547
1548 private:
1549 // used to embed the SkDrawIter object directly in our instance, w/o
1550 // having to expose that class def to the public. There is an assert
1551 // in our constructor to ensure that fStorage is large enough
1552 // (though needs to be a compile-time-assert!). We use intptr_t to work
1553 // safely with 32 and 64 bit machines (to ensure the storage is enough)
1554 intptr_t fStorage[32];
1555 class SkDrawIter* fImpl; // this points at fStorage
1556 SkPaint fDefaultPaint;
1557 bool fDone;
1558 };
Herb Derby13569782016-10-06 14:33:43 -04001559
reed4960eee2015-12-18 07:09:18 -08001560 static bool BoundsAffectsClip(SaveLayerFlags);
reedbada1882015-12-21 13:09:44 -08001561 static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
reed4960eee2015-12-18 07:09:18 -08001562
reeda2217ef2016-07-20 06:04:34 -07001563 static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1564 SkBaseDevice* dst, const SkMatrix& ctm,
1565 const SkClipStack* clipStack);
1566
reedc83a2972015-07-16 07:40:45 -07001567 enum ShaderOverrideOpacity {
1568 kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
1569 kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
1570 kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
1571 };
1572
reed@google.com97af1a62012-08-28 12:19:02 +00001573 // notify our surface (if we have one) that we are about to draw, so it
1574 // can perform copy-on-write or invalidate any cached images
reedc83a2972015-07-16 07:40:45 -07001575 void predrawNotify(bool willOverwritesEntireSurface = false);
1576 void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
1577 void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
1578 this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
1579 : kNotOpaque_ShaderOverrideOpacity);
1580 }
reed@google.com97af1a62012-08-28 12:19:02 +00001581
reed@android.com8a1c16f2008-12-17 15:59:43 +00001582 class MCRec;
1583
bungeman6bd52842016-10-27 09:30:08 -07001584 sk_sp<SkClipStack> fClipStack;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001585 SkDeque fMCStack;
1586 // points to top of stack
1587 MCRec* fMCRec;
1588 // the first N recs that can fit here mean we won't call malloc
reedb679ca82015-04-07 04:40:48 -07001589 enum {
reeda499f902015-05-01 09:34:31 -07001590 kMCRecSize = 128, // most recent measurement
reed31b80a92015-11-16 13:22:24 -08001591 kMCRecCount = 32, // common depth for save/restores
reed8c30a812016-04-20 16:36:51 -07001592 kDeviceCMSize = 176, // most recent measurement
reedb679ca82015-04-07 04:40:48 -07001593 };
1594 intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
reeda499f902015-05-01 09:34:31 -07001595 intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
reed@android.com8a1c16f2008-12-17 15:59:43 +00001596
reed4a8126e2014-09-22 07:29:03 -07001597 const SkSurfaceProps fProps;
1598
reed2ff1fce2014-12-11 07:07:37 -08001599 int fSaveCount; // value returned by getSaveCount()
reed@android.com8a1c16f2008-12-17 15:59:43 +00001600
mike@reedtribe.org74bb77e2012-09-26 02:24:45 +00001601 SkMetaData* fMetaData;
1602
reed@google.com97af1a62012-08-28 12:19:02 +00001603 SkSurface_Base* fSurfaceBase;
1604 SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
1605 void setSurfaceBase(SkSurface_Base* sb) {
1606 fSurfaceBase = sb;
1607 }
1608 friend class SkSurface_Base;
junov@chromium.org45c3db82013-04-11 17:52:05 +00001609 friend class SkSurface_Gpu;
skia.committer@gmail.comfc843592012-10-11 02:01:14 +00001610
reed@android.com8a1c16f2008-12-17 15:59:43 +00001611 bool fDeviceCMDirty; // cleared by updateDeviceCMCache()
1612 void updateDeviceCMCache();
1613
reed2ff1fce2014-12-11 07:07:37 -08001614 void doSave();
1615 void checkForDeferredSave();
reed8c30a812016-04-20 16:36:51 -07001616 void internalSetMatrix(const SkMatrix&);
reed2ff1fce2014-12-11 07:07:37 -08001617
reed@google.com9c135db2014-03-12 18:28:35 +00001618 friend class SkDrawIter; // needs setupDrawForLayerDevice()
reed@google.com8926b162012-03-23 15:36:36 +00001619 friend class AutoDrawLooper;
reed@google.com9c135db2014-03-12 18:28:35 +00001620 friend class SkLua; // needs top layer size and offset
commit-bot@chromium.org2a67e122014-05-19 13:53:10 +00001621 friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
reed52d9ac62014-06-30 09:05:34 -07001622 friend class SkSurface_Raster; // needs getDevice()
reedd9544982014-09-09 18:46:22 -07001623 friend class SkRecorder; // InitFlags
mtklein9c5052f2016-08-06 12:51:51 -07001624 friend class SkLiteRecorder; // InitFlags
Florin Malitaee424ac2016-12-01 12:47:59 -05001625 friend class SkNoDrawCanvas; // InitFlags
Mike Klein1a427912016-11-29 13:46:06 -05001626 friend class SkNWayCanvas; // InitFlags
fmalita2d97bc12014-11-20 10:44:58 -08001627 friend class SkPictureImageFilter; // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
reedc83a2972015-07-16 07:40:45 -07001628 friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
reed4960eee2015-12-18 07:09:18 -08001629 friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
Mike Reedee677f72016-10-21 13:51:49 -04001630 friend class SkPipeCanvas; // InitFlags
Herb Derby13569782016-10-06 14:33:43 -04001631 friend class SkDeferredCanvas; // For use of resetForNextPicture
Matt Sarett22886c42016-11-22 11:31:41 -05001632 friend class SkOverdrawCanvas;
piotaixrb5fae932014-09-24 13:03:30 -07001633
reedd9544982014-09-09 18:46:22 -07001634 enum InitFlags {
1635 kDefault_InitFlags = 0,
1636 kConservativeRasterClip_InitFlag = 1 << 0,
1637 };
reed78e27682014-11-19 08:04:34 -08001638 SkCanvas(const SkIRect& bounds, InitFlags);
robertphillipsfcf78292015-06-19 11:49:52 -07001639 SkCanvas(SkBaseDevice* device, InitFlags);
reedd9544982014-09-09 18:46:22 -07001640
mtkleinfeaadee2015-04-08 11:25:48 -07001641 void resetForNextPicture(const SkIRect& bounds);
1642
reed8f2e7912014-09-04 12:45:18 -07001643 // needs gettotalclip()
tfarinaa5414c42014-10-10 06:19:09 -07001644 friend class SkCanvasStateUtils;
piotaixrb5fae932014-09-24 13:03:30 -07001645
reed4a8126e2014-09-22 07:29:03 -07001646 // call this each time we attach ourselves to a device
1647 // - constructor
1648 // - internalSaveLayer
1649 void setupDevice(SkBaseDevice*);
1650
reedd9544982014-09-09 18:46:22 -07001651 SkBaseDevice* init(SkBaseDevice*, InitFlags);
reed@google.comf0b5e112011-09-07 11:57:34 +00001652
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001653 /**
senorblancoafc7cce2016-02-02 18:44:15 -08001654 * 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 +00001655 * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1656 */
senorblancoafc7cce2016-02-02 18:44:15 -08001657 SkIRect getTopLayerBounds() const;
commit-bot@chromium.org403f8d72014-02-17 15:24:26 +00001658
reed@google.com71121732012-09-18 15:14:33 +00001659 void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
commit-bot@chromium.orgeed779d2013-08-16 10:24:37 +00001660 const SkRect& dst, const SkPaint* paint,
reeda5517e22015-07-14 10:54:12 -07001661 SrcRectConstraint);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001662 void internalDrawPaint(const SkPaint& paint);
reed4960eee2015-12-18 07:09:18 -08001663 void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
reed7503d602016-07-15 14:23:29 -07001664 void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*);
bsalomon@google.comfa6ac932011-10-05 19:57:55 +00001665
reed@android.com8a1c16f2008-12-17 15:59:43 +00001666 // shared by save() and saveLayer()
reed2ff1fce2014-12-11 07:07:37 -08001667 void internalSave();
reed@android.com8a1c16f2008-12-17 15:59:43 +00001668 void internalRestore();
bungeman@google.com52c748b2011-08-22 21:30:43 +00001669 static void DrawRect(const SkDraw& draw, const SkPaint& paint,
1670 const SkRect& r, SkScalar textSize);
1671 static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
1672 const char text[], size_t byteLength,
1673 SkScalar x, SkScalar y);
reed@google.com4b226022011-01-11 18:32:13 +00001674
reedfa35f8e2014-09-04 12:14:36 -07001675 // only for canvasutils
1676 const SkRegion& internal_private_getTotalClip() const;
1677
reedc83a2972015-07-16 07:40:45 -07001678 /*
1679 * Returns true if drawing the specified rect (or all if it is null) with the specified
1680 * paint (or default if null) would overwrite the entire root device of the canvas
1681 * (i.e. the canvas' surface if it had one).
1682 */
1683 bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
1684
reed262a71b2015-12-05 13:07:27 -08001685 /**
1686 * Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
1687 */
1688 bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
reedc83a2972015-07-16 07:40:45 -07001689
msarettfbfa2582016-08-12 08:29:08 -07001690
1691 /**
1692 * Keep track of the device clip bounds and if the matrix is scale-translate. This allows
1693 * us to do a fast quick reject in the common case.
reed@android.com8a1c16f2008-12-17 15:59:43 +00001694 */
msarett9637ea92016-08-18 14:03:30 -07001695 bool fIsScaleTranslate;
msarettfbfa2582016-08-12 08:29:08 -07001696 SkRect fDeviceClipBounds;
1697
caryclark@google.com8f0a7b82012-11-07 14:54:49 +00001698 bool fAllowSoftClip;
caryclark@google.com45a75fb2013-04-25 13:34:40 +00001699 bool fAllowSimplifyClip;
reed42b73eb2015-11-20 13:42:42 -08001700 const bool fConservativeRasterClip;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001701
reed@google.com5c3d1472011-02-22 19:12:23 +00001702 class AutoValidateClip : ::SkNoncopyable {
1703 public:
1704 explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1705 fCanvas->validateClip();
1706 }
1707 ~AutoValidateClip() { fCanvas->validateClip(); }
1708
1709 private:
1710 const SkCanvas* fCanvas;
1711 };
1712
1713#ifdef SK_DEBUG
1714 void validateClip() const;
1715#else
1716 void validateClip() const {}
1717#endif
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +00001718
1719 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +00001720};
1721
1722/** Stack helper class to automatically call restoreToCount() on the canvas
1723 when this object goes out of scope. Use this to guarantee that the canvas
1724 is restored to a known state.
1725*/
1726class SkAutoCanvasRestore : SkNoncopyable {
1727public:
commit-bot@chromium.org28871192013-10-14 15:28:01 +00001728 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1729 if (fCanvas) {
1730 fSaveCount = canvas->getSaveCount();
1731 if (doSave) {
1732 canvas->save();
1733 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001734 }
1735 }
1736 ~SkAutoCanvasRestore() {
reed@google.comf6c9a5b2012-11-20 15:12:21 +00001737 if (fCanvas) {
1738 fCanvas->restoreToCount(fSaveCount);
1739 }
1740 }
1741
1742 /**
1743 * Perform the restore now, instead of waiting for the destructor. Will
1744 * only do this once.
1745 */
1746 void restore() {
1747 if (fCanvas) {
1748 fCanvas->restoreToCount(fSaveCount);
1749 fCanvas = NULL;
1750 }
reed@android.com8a1c16f2008-12-17 15:59:43 +00001751 }
1752
1753private:
1754 SkCanvas* fCanvas;
1755 int fSaveCount;
1756};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +00001757#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
reed@android.com8a1c16f2008-12-17 15:59:43 +00001758
fmalitac3b589a2014-06-05 12:40:07 -07001759class SkCanvasClipVisitor {
1760public:
1761 virtual ~SkCanvasClipVisitor();
reed73603f32016-09-20 08:42:38 -07001762 virtual void clipRect(const SkRect&, SkCanvas::ClipOp, bool antialias) = 0;
1763 virtual void clipRRect(const SkRRect&, SkCanvas::ClipOp, bool antialias) = 0;
1764 virtual void clipPath(const SkPath&, SkCanvas::ClipOp, bool antialias) = 0;
fmalitac3b589a2014-06-05 12:40:07 -07001765};
commit-bot@chromium.org2a5cd602014-05-30 20:41:20 +00001766
reed@android.com8a1c16f2008-12-17 15:59:43 +00001767#endif