Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright 2006 The Android Open Source Project |
michael@0 | 3 | * |
michael@0 | 4 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 5 | * found in the LICENSE file. |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | #ifndef SkCanvas_DEFINED |
michael@0 | 9 | #define SkCanvas_DEFINED |
michael@0 | 10 | |
michael@0 | 11 | #include "SkTypes.h" |
michael@0 | 12 | #include "SkBitmap.h" |
michael@0 | 13 | #include "SkDeque.h" |
michael@0 | 14 | #include "SkClipStack.h" |
michael@0 | 15 | #include "SkPaint.h" |
michael@0 | 16 | #include "SkRefCnt.h" |
michael@0 | 17 | #include "SkPath.h" |
michael@0 | 18 | #include "SkRegion.h" |
michael@0 | 19 | #include "SkXfermode.h" |
michael@0 | 20 | |
michael@0 | 21 | // if not defined, we always assume ClipToLayer for saveLayer() |
michael@0 | 22 | //#define SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
michael@0 | 23 | |
michael@0 | 24 | |
michael@0 | 25 | //#define SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG |
michael@0 | 26 | //#define SK_SUPPORT_LEGACY_GETCLIPTYPE |
michael@0 | 27 | //#define SK_SUPPORT_LEGACY_GETTOTALCLIP |
michael@0 | 28 | //#define SK_SUPPORT_LEGACY_GETTOPDEVICE |
michael@0 | 29 | |
michael@0 | 30 | class SkBounder; |
michael@0 | 31 | class SkBaseDevice; |
michael@0 | 32 | class SkDraw; |
michael@0 | 33 | class SkDrawFilter; |
michael@0 | 34 | class SkMetaData; |
michael@0 | 35 | class SkPicture; |
michael@0 | 36 | class SkRRect; |
michael@0 | 37 | class SkSurface; |
michael@0 | 38 | class SkSurface_Base; |
michael@0 | 39 | class GrContext; |
michael@0 | 40 | class GrRenderTarget; |
michael@0 | 41 | |
michael@0 | 42 | /** \class SkCanvas |
michael@0 | 43 | |
michael@0 | 44 | A Canvas encapsulates all of the state about drawing into a device (bitmap). |
michael@0 | 45 | This includes a reference to the device itself, and a stack of matrix/clip |
michael@0 | 46 | values. For any given draw call (e.g. drawRect), the geometry of the object |
michael@0 | 47 | being drawn is transformed by the concatenation of all the matrices in the |
michael@0 | 48 | stack. The transformed geometry is clipped by the intersection of all of |
michael@0 | 49 | the clips in the stack. |
michael@0 | 50 | |
michael@0 | 51 | While the Canvas holds the state of the drawing device, the state (style) |
michael@0 | 52 | of the object being drawn is held by the Paint, which is provided as a |
michael@0 | 53 | parameter to each of the draw() methods. The Paint holds attributes such as |
michael@0 | 54 | color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns), |
michael@0 | 55 | etc. |
michael@0 | 56 | */ |
michael@0 | 57 | class SK_API SkCanvas : public SkRefCnt { |
michael@0 | 58 | public: |
michael@0 | 59 | SK_DECLARE_INST_COUNT(SkCanvas) |
michael@0 | 60 | |
michael@0 | 61 | /** |
michael@0 | 62 | * Attempt to allocate an offscreen raster canvas, matching the ImageInfo. |
michael@0 | 63 | * On success, return a new canvas that will draw into that offscreen. |
michael@0 | 64 | * |
michael@0 | 65 | * The caller can access the pixels after drawing into this canvas by |
michael@0 | 66 | * calling readPixels() or peekPixels(). |
michael@0 | 67 | * |
michael@0 | 68 | * If the requested ImageInfo is opaque (either the colortype is |
michael@0 | 69 | * intrinsically opaque like RGB_565, or the info's alphatype is kOpaque) |
michael@0 | 70 | * then the pixel memory may be uninitialized. Otherwise, the pixel memory |
michael@0 | 71 | * will be initialized to 0, which is interpreted as transparent. |
michael@0 | 72 | * |
michael@0 | 73 | * On failure, return NULL. This can fail for several reasons: |
michael@0 | 74 | * 1. the memory allocation failed (e.g. request is too large) |
michael@0 | 75 | * 2. invalid ImageInfo (e.g. negative dimensions) |
michael@0 | 76 | * 3. unsupported ImageInfo for a canvas |
michael@0 | 77 | * - kUnknown_SkColorType, kIndex_8_SkColorType |
michael@0 | 78 | * - kIgnore_SkAlphaType |
michael@0 | 79 | * - this list is not complete, so others may also be unsupported |
michael@0 | 80 | * |
michael@0 | 81 | * Note: it is valid to request a supported ImageInfo, but with zero |
michael@0 | 82 | * dimensions. |
michael@0 | 83 | */ |
michael@0 | 84 | static SkCanvas* NewRaster(const SkImageInfo&); |
michael@0 | 85 | |
michael@0 | 86 | static SkCanvas* NewRasterN32(int width, int height) { |
michael@0 | 87 | return NewRaster(SkImageInfo::MakeN32Premul(width, height)); |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | /** |
michael@0 | 91 | * Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the |
michael@0 | 92 | * specified pixels. To access the pixels after drawing to them, the caller should call |
michael@0 | 93 | * flush() or call peekPixels(...). |
michael@0 | 94 | * |
michael@0 | 95 | * On failure, return NULL. This can fail for several reasons: |
michael@0 | 96 | * 1. invalid ImageInfo (e.g. negative dimensions) |
michael@0 | 97 | * 2. unsupported ImageInfo for a canvas |
michael@0 | 98 | * - kUnknown_SkColorType, kIndex_8_SkColorType |
michael@0 | 99 | * - kIgnore_SkAlphaType |
michael@0 | 100 | * - this list is not complete, so others may also be unsupported |
michael@0 | 101 | * |
michael@0 | 102 | * Note: it is valid to request a supported ImageInfo, but with zero |
michael@0 | 103 | * dimensions. |
michael@0 | 104 | */ |
michael@0 | 105 | static SkCanvas* NewRasterDirect(const SkImageInfo&, void*, size_t); |
michael@0 | 106 | |
michael@0 | 107 | static SkCanvas* NewRasterDirectN32(int width, int height, SkPMColor* pixels, size_t rowBytes) { |
michael@0 | 108 | return NewRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes); |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | /** |
michael@0 | 112 | * Creates an empty canvas with no backing device/pixels, and zero |
michael@0 | 113 | * dimensions. |
michael@0 | 114 | */ |
michael@0 | 115 | SkCanvas(); |
michael@0 | 116 | |
michael@0 | 117 | /** |
michael@0 | 118 | * Creates a canvas of the specified dimensions, but explicitly not backed |
michael@0 | 119 | * by any device/pixels. Typically this use used by subclasses who handle |
michael@0 | 120 | * the draw calls in some other way. |
michael@0 | 121 | */ |
michael@0 | 122 | SkCanvas(int width, int height); |
michael@0 | 123 | |
michael@0 | 124 | /** Construct a canvas with the specified device to draw into. |
michael@0 | 125 | |
michael@0 | 126 | @param device Specifies a device for the canvas to draw into. |
michael@0 | 127 | */ |
michael@0 | 128 | explicit SkCanvas(SkBaseDevice* device); |
michael@0 | 129 | |
michael@0 | 130 | /** Construct a canvas with the specified bitmap to draw into. |
michael@0 | 131 | @param bitmap Specifies a bitmap for the canvas to draw into. Its |
michael@0 | 132 | structure are copied to the canvas. |
michael@0 | 133 | */ |
michael@0 | 134 | explicit SkCanvas(const SkBitmap& bitmap); |
michael@0 | 135 | virtual ~SkCanvas(); |
michael@0 | 136 | |
michael@0 | 137 | SkMetaData& getMetaData(); |
michael@0 | 138 | |
michael@0 | 139 | /** |
michael@0 | 140 | * Return ImageInfo for this canvas. If the canvas is not backed by pixels |
michael@0 | 141 | * (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType. |
michael@0 | 142 | */ |
michael@0 | 143 | SkImageInfo imageInfo() const; |
michael@0 | 144 | |
michael@0 | 145 | /////////////////////////////////////////////////////////////////////////// |
michael@0 | 146 | |
michael@0 | 147 | /** |
michael@0 | 148 | * Trigger the immediate execution of all pending draw operations. |
michael@0 | 149 | */ |
michael@0 | 150 | void flush(); |
michael@0 | 151 | |
michael@0 | 152 | /** |
michael@0 | 153 | * Gets the size of the base or root layer in global canvas coordinates. The |
michael@0 | 154 | * origin of the base layer is always (0,0). The current drawable area may be |
michael@0 | 155 | * smaller (due to clipping or saveLayer). |
michael@0 | 156 | */ |
michael@0 | 157 | SkISize getBaseLayerSize() const; |
michael@0 | 158 | |
michael@0 | 159 | /** |
michael@0 | 160 | * DEPRECATED: call getBaseLayerSize |
michael@0 | 161 | */ |
michael@0 | 162 | SkISize getDeviceSize() const { return this->getBaseLayerSize(); } |
michael@0 | 163 | |
michael@0 | 164 | /** |
michael@0 | 165 | * DEPRECATED. |
michael@0 | 166 | * Return the canvas' device object, which may be null. The device holds |
michael@0 | 167 | * the bitmap of the pixels that the canvas draws into. The reference count |
michael@0 | 168 | * of the returned device is not changed by this call. |
michael@0 | 169 | */ |
michael@0 | 170 | SkBaseDevice* getDevice() const; |
michael@0 | 171 | |
michael@0 | 172 | /** |
michael@0 | 173 | * saveLayer() can create another device (which is later drawn onto |
michael@0 | 174 | * the previous device). getTopDevice() returns the top-most device current |
michael@0 | 175 | * installed. Note that this can change on other calls like save/restore, |
michael@0 | 176 | * so do not access this device after subsequent canvas calls. |
michael@0 | 177 | * The reference count of the device is not changed. |
michael@0 | 178 | * |
michael@0 | 179 | * @param updateMatrixClip If this is true, then before the device is |
michael@0 | 180 | * returned, we ensure that its has been notified about the current |
michael@0 | 181 | * matrix and clip. Note: this happens automatically when the device |
michael@0 | 182 | * is drawn to, but is optional here, as there is a small perf hit |
michael@0 | 183 | * sometimes. |
michael@0 | 184 | */ |
michael@0 | 185 | #ifndef SK_SUPPORT_LEGACY_GETTOPDEVICE |
michael@0 | 186 | private: |
michael@0 | 187 | #endif |
michael@0 | 188 | SkBaseDevice* getTopDevice(bool updateMatrixClip = false) const; |
michael@0 | 189 | public: |
michael@0 | 190 | |
michael@0 | 191 | /** |
michael@0 | 192 | * Create a new surface matching the specified info, one that attempts to |
michael@0 | 193 | * be maximally compatible when used with this canvas. |
michael@0 | 194 | */ |
michael@0 | 195 | SkSurface* newSurface(const SkImageInfo&); |
michael@0 | 196 | |
michael@0 | 197 | /** |
michael@0 | 198 | * Return the GPU context of the device that is associated with the canvas. |
michael@0 | 199 | * For a canvas with non-GPU device, NULL is returned. |
michael@0 | 200 | */ |
michael@0 | 201 | GrContext* getGrContext(); |
michael@0 | 202 | |
michael@0 | 203 | /////////////////////////////////////////////////////////////////////////// |
michael@0 | 204 | |
michael@0 | 205 | /** |
michael@0 | 206 | * If the canvas has writable pixels in its top layer (and is not recording to a picture |
michael@0 | 207 | * or other non-raster target) and has direct access to its pixels (i.e. they are in |
michael@0 | 208 | * local RAM) return the address of those pixels, and if not null, |
michael@0 | 209 | * return the ImageInfo and rowBytes. The returned address is only valid |
michael@0 | 210 | * while the canvas object is in scope and unchanged. Any API calls made on |
michael@0 | 211 | * canvas (or its parent surface if any) will invalidate the |
michael@0 | 212 | * returned address (and associated information). |
michael@0 | 213 | * |
michael@0 | 214 | * On failure, returns NULL and the info and rowBytes parameters are |
michael@0 | 215 | * ignored. |
michael@0 | 216 | */ |
michael@0 | 217 | void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes); |
michael@0 | 218 | |
michael@0 | 219 | /** |
michael@0 | 220 | * If the canvas has readable pixels in its base layer (and is not recording to a picture |
michael@0 | 221 | * or other non-raster target) and has direct access to its pixels (i.e. they are in |
michael@0 | 222 | * local RAM) return the const-address of those pixels, and if not null, |
michael@0 | 223 | * return the ImageInfo and rowBytes. The returned address is only valid |
michael@0 | 224 | * while the canvas object is in scope and unchanged. Any API calls made on |
michael@0 | 225 | * canvas (or its parent surface if any) will invalidate the |
michael@0 | 226 | * returned address (and associated information). |
michael@0 | 227 | * |
michael@0 | 228 | * On failure, returns NULL and the info and rowBytes parameters are |
michael@0 | 229 | * ignored. |
michael@0 | 230 | */ |
michael@0 | 231 | const void* peekPixels(SkImageInfo* info, size_t* rowBytes); |
michael@0 | 232 | |
michael@0 | 233 | /** |
michael@0 | 234 | * This enum can be used with read/writePixels to perform a pixel ops to or |
michael@0 | 235 | * from an 8888 config other than Skia's native config (SkPMColor). There |
michael@0 | 236 | * are three byte orders supported: native, BGRA, and RGBA. Each has a |
michael@0 | 237 | * premultiplied and unpremultiplied variant. |
michael@0 | 238 | * |
michael@0 | 239 | * Components of a 8888 pixel can be packed/unpacked from a 32bit word using |
michael@0 | 240 | * either byte offsets or shift values. Byte offsets are endian-invariant |
michael@0 | 241 | * while shifts are not. BGRA and RGBA configs are defined by byte |
michael@0 | 242 | * orderings. The native config is defined by shift values (SK_A32_SHIFT, |
michael@0 | 243 | * ..., SK_B32_SHIFT). |
michael@0 | 244 | */ |
michael@0 | 245 | enum Config8888 { |
michael@0 | 246 | /** |
michael@0 | 247 | * Skia's native order specified by: |
michael@0 | 248 | * SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT |
michael@0 | 249 | * |
michael@0 | 250 | * kNative_Premul_Config8888 is equivalent to SkPMColor |
michael@0 | 251 | * kNative_Unpremul_Config8888 has the same component order as SkPMColor |
michael@0 | 252 | * but is not premultiplied. |
michael@0 | 253 | */ |
michael@0 | 254 | kNative_Premul_Config8888, |
michael@0 | 255 | kNative_Unpremul_Config8888, |
michael@0 | 256 | /** |
michael@0 | 257 | * low byte to high byte: B, G, R, A. |
michael@0 | 258 | */ |
michael@0 | 259 | kBGRA_Premul_Config8888, |
michael@0 | 260 | kBGRA_Unpremul_Config8888, |
michael@0 | 261 | /** |
michael@0 | 262 | * low byte to high byte: R, G, B, A. |
michael@0 | 263 | */ |
michael@0 | 264 | kRGBA_Premul_Config8888, |
michael@0 | 265 | kRGBA_Unpremul_Config8888 |
michael@0 | 266 | }; |
michael@0 | 267 | |
michael@0 | 268 | /** |
michael@0 | 269 | * On success (returns true), copy the canvas pixels into the bitmap. |
michael@0 | 270 | * On failure, the bitmap parameter is left unchanged and false is |
michael@0 | 271 | * returned. |
michael@0 | 272 | * |
michael@0 | 273 | * The canvas' pixels are converted to the bitmap's config. The only |
michael@0 | 274 | * supported config is kARGB_8888_Config, though this is likely to be |
michael@0 | 275 | * relaxed in the future. The meaning of config kARGB_8888_Config is |
michael@0 | 276 | * modified by the enum param config8888. The default value interprets |
michael@0 | 277 | * kARGB_8888_Config as SkPMColor |
michael@0 | 278 | * |
michael@0 | 279 | * If the bitmap has pixels already allocated, the canvas pixels will be |
michael@0 | 280 | * written there. If not, bitmap->allocPixels() will be called |
michael@0 | 281 | * automatically. If the bitmap is backed by a texture readPixels will |
michael@0 | 282 | * fail. |
michael@0 | 283 | * |
michael@0 | 284 | * The actual pixels written is the intersection of the canvas' bounds, and |
michael@0 | 285 | * the rectangle formed by the bitmap's width,height and the specified x,y. |
michael@0 | 286 | * If bitmap pixels extend outside of that intersection, they will not be |
michael@0 | 287 | * modified. |
michael@0 | 288 | * |
michael@0 | 289 | * Other failure conditions: |
michael@0 | 290 | * * If the canvas is backed by a non-raster device (e.g. PDF) then |
michael@0 | 291 | * readPixels will fail. |
michael@0 | 292 | * * If bitmap is texture-backed then readPixels will fail. (This may be |
michael@0 | 293 | * relaxed in the future.) |
michael@0 | 294 | * |
michael@0 | 295 | * Example that reads the entire canvas into a bitmap using the native |
michael@0 | 296 | * SkPMColor: |
michael@0 | 297 | * SkISize size = canvas->getDeviceSize(); |
michael@0 | 298 | * bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth, |
michael@0 | 299 | * size.fHeight); |
michael@0 | 300 | * if (canvas->readPixels(bitmap, 0, 0)) { |
michael@0 | 301 | * // use the pixels |
michael@0 | 302 | * } |
michael@0 | 303 | */ |
michael@0 | 304 | bool readPixels(SkBitmap* bitmap, |
michael@0 | 305 | int x, int y, |
michael@0 | 306 | Config8888 config8888 = kNative_Premul_Config8888); |
michael@0 | 307 | |
michael@0 | 308 | /** |
michael@0 | 309 | * DEPRECATED: This will be removed as soon as webkit is no longer relying |
michael@0 | 310 | * on it. The bitmap is resized to the intersection of srcRect and the |
michael@0 | 311 | * canvas bounds. New pixels are always allocated on success. Bitmap is |
michael@0 | 312 | * unmodified on failure. |
michael@0 | 313 | */ |
michael@0 | 314 | bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap); |
michael@0 | 315 | |
michael@0 | 316 | #ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG |
michael@0 | 317 | /** |
michael@0 | 318 | * DEPRECATED |
michael@0 | 319 | * Similar to draw sprite, this method will copy the pixels in bitmap onto |
michael@0 | 320 | * the canvas, with the top/left corner specified by (x, y). The canvas' |
michael@0 | 321 | * pixel values are completely replaced: there is no blending. |
michael@0 | 322 | * |
michael@0 | 323 | * Currently if bitmap is backed by a texture this is a no-op. This may be |
michael@0 | 324 | * relaxed in the future. |
michael@0 | 325 | * |
michael@0 | 326 | * If the bitmap has config kARGB_8888_Config then the config8888 param |
michael@0 | 327 | * will determines how the pixel valuess are intepreted. If the bitmap is |
michael@0 | 328 | * not kARGB_8888_Config then this parameter is ignored. |
michael@0 | 329 | * |
michael@0 | 330 | * Note: If you are recording drawing commands on this canvas to |
michael@0 | 331 | * SkPicture, writePixels() is ignored! |
michael@0 | 332 | */ |
michael@0 | 333 | void writePixels(const SkBitmap& bitmap, int x, int y, Config8888 config8888); |
michael@0 | 334 | #endif |
michael@0 | 335 | |
michael@0 | 336 | /** |
michael@0 | 337 | * This method affects the pixels in the base-layer, and operates in pixel coordinates, |
michael@0 | 338 | * ignoring the matrix and clip. |
michael@0 | 339 | * |
michael@0 | 340 | * The specified ImageInfo and (x,y) offset specifies a rectangle: target. |
michael@0 | 341 | * |
michael@0 | 342 | * target.setXYWH(x, y, info.width(), info.height()); |
michael@0 | 343 | * |
michael@0 | 344 | * Target is intersected with the bounds of the base-layer. If this intersection is not empty, |
michael@0 | 345 | * then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes |
michael@0 | 346 | * and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src |
michael@0 | 347 | * pixels, performing any colortype/alphatype transformations needed (in the case where the |
michael@0 | 348 | * src and dst have different colortypes or alphatypes). |
michael@0 | 349 | * |
michael@0 | 350 | * This call can fail, returning false, for several reasons: |
michael@0 | 351 | * - If the src colortype/alphatype cannot be converted to the canvas' types |
michael@0 | 352 | * - If this canvas is not backed by pixels (e.g. picture or PDF) |
michael@0 | 353 | */ |
michael@0 | 354 | bool writePixels(const SkImageInfo&, const void* pixels, size_t rowBytes, int x, int y); |
michael@0 | 355 | |
michael@0 | 356 | /** |
michael@0 | 357 | * Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap |
michael@0 | 358 | * is just wrapping a texture, returns false and does nothing. |
michael@0 | 359 | */ |
michael@0 | 360 | bool writePixels(const SkBitmap& bitmap, int x, int y); |
michael@0 | 361 | |
michael@0 | 362 | /////////////////////////////////////////////////////////////////////////// |
michael@0 | 363 | |
michael@0 | 364 | enum SaveFlags { |
michael@0 | 365 | /** save the matrix state, restoring it on restore() */ |
michael@0 | 366 | kMatrix_SaveFlag = 0x01, |
michael@0 | 367 | /** save the clip state, restoring it on restore() */ |
michael@0 | 368 | kClip_SaveFlag = 0x02, |
michael@0 | 369 | /** the layer needs to support per-pixel alpha */ |
michael@0 | 370 | kHasAlphaLayer_SaveFlag = 0x04, |
michael@0 | 371 | /** the layer needs to support 8-bits per color component */ |
michael@0 | 372 | kFullColorLayer_SaveFlag = 0x08, |
michael@0 | 373 | /** |
michael@0 | 374 | * the layer should clip against the bounds argument |
michael@0 | 375 | * |
michael@0 | 376 | * if SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG is undefined, this is treated as always on. |
michael@0 | 377 | */ |
michael@0 | 378 | kClipToLayer_SaveFlag = 0x10, |
michael@0 | 379 | |
michael@0 | 380 | // helper masks for common choices |
michael@0 | 381 | kMatrixClip_SaveFlag = 0x03, |
michael@0 | 382 | #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG |
michael@0 | 383 | kARGB_NoClipLayer_SaveFlag = 0x0F, |
michael@0 | 384 | #endif |
michael@0 | 385 | kARGB_ClipLayer_SaveFlag = 0x1F |
michael@0 | 386 | }; |
michael@0 | 387 | |
michael@0 | 388 | /** This call saves the current matrix, clip, and drawFilter, and pushes a |
michael@0 | 389 | copy onto a private stack. Subsequent calls to translate, scale, |
michael@0 | 390 | rotate, skew, concat or clipRect, clipPath, and setDrawFilter all |
michael@0 | 391 | operate on this copy. |
michael@0 | 392 | When the balancing call to restore() is made, the previous matrix, clip, |
michael@0 | 393 | and drawFilter are restored. |
michael@0 | 394 | @param flags The flags govern what portion of the Matrix/Clip/drawFilter |
michael@0 | 395 | state the save (and matching restore) effect. For example, |
michael@0 | 396 | if only kMatrix is specified, then only the matrix state |
michael@0 | 397 | will be pushed and popped. Likewise for the clip if kClip |
michael@0 | 398 | is specified. However, the drawFilter is always affected |
michael@0 | 399 | by calls to save/restore. |
michael@0 | 400 | @return The value to pass to restoreToCount() to balance this save() |
michael@0 | 401 | */ |
michael@0 | 402 | int save(SaveFlags flags = kMatrixClip_SaveFlag); |
michael@0 | 403 | |
michael@0 | 404 | /** This behaves the same as save(), but in addition it allocates an |
michael@0 | 405 | offscreen bitmap. All drawing calls are directed there, and only when |
michael@0 | 406 | the balancing call to restore() is made is that offscreen transfered to |
michael@0 | 407 | the canvas (or the previous layer). |
michael@0 | 408 | @param bounds (may be null) This rect, if non-null, is used as a hint to |
michael@0 | 409 | limit the size of the offscreen, and thus drawing may be |
michael@0 | 410 | clipped to it, though that clipping is not guaranteed to |
michael@0 | 411 | happen. If exact clipping is desired, use clipRect(). |
michael@0 | 412 | @param paint (may be null) This is copied, and is applied to the |
michael@0 | 413 | offscreen when restore() is called |
michael@0 | 414 | @param flags LayerFlags |
michael@0 | 415 | @return The value to pass to restoreToCount() to balance this save() |
michael@0 | 416 | */ |
michael@0 | 417 | int saveLayer(const SkRect* bounds, const SkPaint* paint, |
michael@0 | 418 | SaveFlags flags = kARGB_ClipLayer_SaveFlag); |
michael@0 | 419 | |
michael@0 | 420 | /** This behaves the same as save(), but in addition it allocates an |
michael@0 | 421 | offscreen bitmap. All drawing calls are directed there, and only when |
michael@0 | 422 | the balancing call to restore() is made is that offscreen transfered to |
michael@0 | 423 | the canvas (or the previous layer). |
michael@0 | 424 | @param bounds (may be null) This rect, if non-null, is used as a hint to |
michael@0 | 425 | limit the size of the offscreen, and thus drawing may be |
michael@0 | 426 | clipped to it, though that clipping is not guaranteed to |
michael@0 | 427 | happen. If exact clipping is desired, use clipRect(). |
michael@0 | 428 | @param alpha This is applied to the offscreen when restore() is called. |
michael@0 | 429 | @param flags LayerFlags |
michael@0 | 430 | @return The value to pass to restoreToCount() to balance this save() |
michael@0 | 431 | */ |
michael@0 | 432 | int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, |
michael@0 | 433 | SaveFlags flags = kARGB_ClipLayer_SaveFlag); |
michael@0 | 434 | |
michael@0 | 435 | /** This call balances a previous call to save(), and is used to remove all |
michael@0 | 436 | modifications to the matrix/clip/drawFilter state since the last save |
michael@0 | 437 | call. |
michael@0 | 438 | It is an error to call restore() more times than save() was called. |
michael@0 | 439 | */ |
michael@0 | 440 | void restore(); |
michael@0 | 441 | |
michael@0 | 442 | /** Returns the number of matrix/clip states on the SkCanvas' private stack. |
michael@0 | 443 | This will equal # save() calls - # restore() calls + 1. The save count on |
michael@0 | 444 | a new canvas is 1. |
michael@0 | 445 | */ |
michael@0 | 446 | int getSaveCount() const; |
michael@0 | 447 | |
michael@0 | 448 | /** Efficient way to pop any calls to save() that happened after the save |
michael@0 | 449 | count reached saveCount. It is an error for saveCount to be greater than |
michael@0 | 450 | getSaveCount(). To pop all the way back to the initial matrix/clip context |
michael@0 | 451 | pass saveCount == 1. |
michael@0 | 452 | @param saveCount The number of save() levels to restore from |
michael@0 | 453 | */ |
michael@0 | 454 | void restoreToCount(int saveCount); |
michael@0 | 455 | |
michael@0 | 456 | /** Returns true if drawing is currently going to a layer (from saveLayer) |
michael@0 | 457 | * rather than to the root device. |
michael@0 | 458 | */ |
michael@0 | 459 | virtual bool isDrawingToLayer() const; |
michael@0 | 460 | |
michael@0 | 461 | /** Preconcat the current matrix with the specified translation |
michael@0 | 462 | @param dx The distance to translate in X |
michael@0 | 463 | @param dy The distance to translate in Y |
michael@0 | 464 | returns true if the operation succeeded (e.g. did not overflow) |
michael@0 | 465 | */ |
michael@0 | 466 | bool translate(SkScalar dx, SkScalar dy); |
michael@0 | 467 | |
michael@0 | 468 | /** Preconcat the current matrix with the specified scale. |
michael@0 | 469 | @param sx The amount to scale in X |
michael@0 | 470 | @param sy The amount to scale in Y |
michael@0 | 471 | returns true if the operation succeeded (e.g. did not overflow) |
michael@0 | 472 | */ |
michael@0 | 473 | bool scale(SkScalar sx, SkScalar sy); |
michael@0 | 474 | |
michael@0 | 475 | /** Preconcat the current matrix with the specified rotation. |
michael@0 | 476 | @param degrees The amount to rotate, in degrees |
michael@0 | 477 | returns true if the operation succeeded (e.g. did not overflow) |
michael@0 | 478 | */ |
michael@0 | 479 | bool rotate(SkScalar degrees); |
michael@0 | 480 | |
michael@0 | 481 | /** Preconcat the current matrix with the specified skew. |
michael@0 | 482 | @param sx The amount to skew in X |
michael@0 | 483 | @param sy The amount to skew in Y |
michael@0 | 484 | returns true if the operation succeeded (e.g. did not overflow) |
michael@0 | 485 | */ |
michael@0 | 486 | bool skew(SkScalar sx, SkScalar sy); |
michael@0 | 487 | |
michael@0 | 488 | /** Preconcat the current matrix with the specified matrix. |
michael@0 | 489 | @param matrix The matrix to preconcatenate with the current matrix |
michael@0 | 490 | @return true if the operation succeeded (e.g. did not overflow) |
michael@0 | 491 | */ |
michael@0 | 492 | bool concat(const SkMatrix& matrix); |
michael@0 | 493 | |
michael@0 | 494 | /** Replace the current matrix with a copy of the specified matrix. |
michael@0 | 495 | @param matrix The matrix that will be copied into the current matrix. |
michael@0 | 496 | */ |
michael@0 | 497 | void setMatrix(const SkMatrix& matrix); |
michael@0 | 498 | |
michael@0 | 499 | /** Helper for setMatrix(identity). Sets the current matrix to identity. |
michael@0 | 500 | */ |
michael@0 | 501 | void resetMatrix(); |
michael@0 | 502 | |
michael@0 | 503 | /** |
michael@0 | 504 | * Modify the current clip with the specified rectangle. |
michael@0 | 505 | * @param rect The rect to combine with the current clip |
michael@0 | 506 | * @param op The region op to apply to the current clip |
michael@0 | 507 | * @param doAntiAlias true if the clip should be antialiased |
michael@0 | 508 | */ |
michael@0 | 509 | void clipRect(const SkRect& rect, |
michael@0 | 510 | SkRegion::Op op = SkRegion::kIntersect_Op, |
michael@0 | 511 | bool doAntiAlias = false); |
michael@0 | 512 | |
michael@0 | 513 | /** |
michael@0 | 514 | * Modify the current clip with the specified SkRRect. |
michael@0 | 515 | * @param rrect The rrect to combine with the current clip |
michael@0 | 516 | * @param op The region op to apply to the current clip |
michael@0 | 517 | * @param doAntiAlias true if the clip should be antialiased |
michael@0 | 518 | */ |
michael@0 | 519 | void clipRRect(const SkRRect& rrect, |
michael@0 | 520 | SkRegion::Op op = SkRegion::kIntersect_Op, |
michael@0 | 521 | bool doAntiAlias = false); |
michael@0 | 522 | |
michael@0 | 523 | /** |
michael@0 | 524 | * Modify the current clip with the specified path. |
michael@0 | 525 | * @param path The path to combine with the current clip |
michael@0 | 526 | * @param op The region op to apply to the current clip |
michael@0 | 527 | * @param doAntiAlias true if the clip should be antialiased |
michael@0 | 528 | */ |
michael@0 | 529 | void clipPath(const SkPath& path, |
michael@0 | 530 | SkRegion::Op op = SkRegion::kIntersect_Op, |
michael@0 | 531 | bool doAntiAlias = false); |
michael@0 | 532 | |
michael@0 | 533 | /** EXPERIMENTAL -- only used for testing |
michael@0 | 534 | Set to false to force clips to be hard, even if doAntiAlias=true is |
michael@0 | 535 | passed to clipRect or clipPath. |
michael@0 | 536 | */ |
michael@0 | 537 | void setAllowSoftClip(bool allow) { |
michael@0 | 538 | fAllowSoftClip = allow; |
michael@0 | 539 | } |
michael@0 | 540 | |
michael@0 | 541 | /** EXPERIMENTAL -- only used for testing |
michael@0 | 542 | Set to simplify clip stack using path ops. |
michael@0 | 543 | */ |
michael@0 | 544 | void setAllowSimplifyClip(bool allow) { |
michael@0 | 545 | fAllowSimplifyClip = allow; |
michael@0 | 546 | } |
michael@0 | 547 | |
michael@0 | 548 | /** Modify the current clip with the specified region. Note that unlike |
michael@0 | 549 | clipRect() and clipPath() which transform their arguments by the current |
michael@0 | 550 | matrix, clipRegion() assumes its argument is already in device |
michael@0 | 551 | coordinates, and so no transformation is performed. |
michael@0 | 552 | @param deviceRgn The region to apply to the current clip |
michael@0 | 553 | @param op The region op to apply to the current clip |
michael@0 | 554 | */ |
michael@0 | 555 | void clipRegion(const SkRegion& deviceRgn, |
michael@0 | 556 | SkRegion::Op op = SkRegion::kIntersect_Op); |
michael@0 | 557 | |
michael@0 | 558 | /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the |
michael@0 | 559 | specified region. This does not intersect or in any other way account |
michael@0 | 560 | for the existing clip region. |
michael@0 | 561 | @param deviceRgn The region to copy into the current clip. |
michael@0 | 562 | */ |
michael@0 | 563 | void setClipRegion(const SkRegion& deviceRgn) { |
michael@0 | 564 | this->clipRegion(deviceRgn, SkRegion::kReplace_Op); |
michael@0 | 565 | } |
michael@0 | 566 | |
michael@0 | 567 | /** Return true if the specified rectangle, after being transformed by the |
michael@0 | 568 | current matrix, would lie completely outside of the current clip. Call |
michael@0 | 569 | this to check if an area you intend to draw into is clipped out (and |
michael@0 | 570 | therefore you can skip making the draw calls). |
michael@0 | 571 | @param rect the rect to compare with the current clip |
michael@0 | 572 | @return true if the rect (transformed by the canvas' matrix) does not |
michael@0 | 573 | intersect with the canvas' clip |
michael@0 | 574 | */ |
michael@0 | 575 | bool quickReject(const SkRect& rect) const; |
michael@0 | 576 | |
michael@0 | 577 | /** Return true if the specified path, after being transformed by the |
michael@0 | 578 | current matrix, would lie completely outside of the current clip. Call |
michael@0 | 579 | this to check if an area you intend to draw into is clipped out (and |
michael@0 | 580 | therefore you can skip making the draw calls). Note, for speed it may |
michael@0 | 581 | return false even if the path itself might not intersect the clip |
michael@0 | 582 | (i.e. the bounds of the path intersects, but the path does not). |
michael@0 | 583 | @param path The path to compare with the current clip |
michael@0 | 584 | @return true if the path (transformed by the canvas' matrix) does not |
michael@0 | 585 | intersect with the canvas' clip |
michael@0 | 586 | */ |
michael@0 | 587 | bool quickReject(const SkPath& path) const; |
michael@0 | 588 | |
michael@0 | 589 | /** Return true if the horizontal band specified by top and bottom is |
michael@0 | 590 | completely clipped out. This is a conservative calculation, meaning |
michael@0 | 591 | that it is possible that if the method returns false, the band may still |
michael@0 | 592 | in fact be clipped out, but the converse is not true. If this method |
michael@0 | 593 | returns true, then the band is guaranteed to be clipped out. |
michael@0 | 594 | @param top The top of the horizontal band to compare with the clip |
michael@0 | 595 | @param bottom The bottom of the horizontal and to compare with the clip |
michael@0 | 596 | @return true if the horizontal band is completely clipped out (i.e. does |
michael@0 | 597 | not intersect the current clip) |
michael@0 | 598 | */ |
michael@0 | 599 | bool quickRejectY(SkScalar top, SkScalar bottom) const { |
michael@0 | 600 | SkASSERT(top <= bottom); |
michael@0 | 601 | |
michael@0 | 602 | #ifndef SK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT |
michael@0 | 603 | // TODO: add a hasPerspective method similar to getLocalClipBounds. This |
michael@0 | 604 | // would cache the SkMatrix::hasPerspective result. Alternatively, have |
michael@0 | 605 | // the MC stack just set a hasPerspective boolean as it is updated. |
michael@0 | 606 | if (this->getTotalMatrix().hasPerspective()) { |
michael@0 | 607 | // TODO: consider implementing some half-plane test between the |
michael@0 | 608 | // two Y planes and the device-bounds (i.e., project the top and |
michael@0 | 609 | // bottom Y planes and then determine if the clip bounds is completely |
michael@0 | 610 | // outside either one). |
michael@0 | 611 | return false; |
michael@0 | 612 | } |
michael@0 | 613 | #endif |
michael@0 | 614 | |
michael@0 | 615 | const SkRect& clipR = this->getLocalClipBounds(); |
michael@0 | 616 | // In the case where the clip is empty and we are provided with a |
michael@0 | 617 | // negative top and positive bottom parameter then this test will return |
michael@0 | 618 | // false even though it will be clipped. We have chosen to exclude that |
michael@0 | 619 | // check as it is rare and would result double the comparisons. |
michael@0 | 620 | return top >= clipR.fBottom || bottom <= clipR.fTop; |
michael@0 | 621 | } |
michael@0 | 622 | |
michael@0 | 623 | /** Return the bounds of the current clip (in local coordinates) in the |
michael@0 | 624 | bounds parameter, and return true if it is non-empty. This can be useful |
michael@0 | 625 | in a way similar to quickReject, in that it tells you that drawing |
michael@0 | 626 | outside of these bounds will be clipped out. |
michael@0 | 627 | */ |
michael@0 | 628 | virtual bool getClipBounds(SkRect* bounds) const; |
michael@0 | 629 | |
michael@0 | 630 | /** Return the bounds of the current clip, in device coordinates; returns |
michael@0 | 631 | true if non-empty. Maybe faster than getting the clip explicitly and |
michael@0 | 632 | then taking its bounds. |
michael@0 | 633 | */ |
michael@0 | 634 | virtual bool getClipDeviceBounds(SkIRect* bounds) const; |
michael@0 | 635 | |
michael@0 | 636 | |
michael@0 | 637 | /** Fill the entire canvas' bitmap (restricted to the current clip) with the |
michael@0 | 638 | specified ARGB color, using the specified mode. |
michael@0 | 639 | @param a the alpha component (0..255) of the color to fill the canvas |
michael@0 | 640 | @param r the red component (0..255) of the color to fill the canvas |
michael@0 | 641 | @param g the green component (0..255) of the color to fill the canvas |
michael@0 | 642 | @param b the blue component (0..255) of the color to fill the canvas |
michael@0 | 643 | @param mode the mode to apply the color in (defaults to SrcOver) |
michael@0 | 644 | */ |
michael@0 | 645 | void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, |
michael@0 | 646 | SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode); |
michael@0 | 647 | |
michael@0 | 648 | /** Fill the entire canvas' bitmap (restricted to the current clip) with the |
michael@0 | 649 | specified color and mode. |
michael@0 | 650 | @param color the color to draw with |
michael@0 | 651 | @param mode the mode to apply the color in (defaults to SrcOver) |
michael@0 | 652 | */ |
michael@0 | 653 | void drawColor(SkColor color, |
michael@0 | 654 | SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode); |
michael@0 | 655 | |
michael@0 | 656 | /** |
michael@0 | 657 | * This erases the entire drawing surface to the specified color, |
michael@0 | 658 | * irrespective of the clip. It does not blend with the previous pixels, |
michael@0 | 659 | * but always overwrites them. |
michael@0 | 660 | * |
michael@0 | 661 | * It is roughly equivalent to the following: |
michael@0 | 662 | * canvas.save(); |
michael@0 | 663 | * canvas.clipRect(hugeRect, kReplace_Op); |
michael@0 | 664 | * paint.setColor(color); |
michael@0 | 665 | * paint.setXfermodeMode(kSrc_Mode); |
michael@0 | 666 | * canvas.drawPaint(paint); |
michael@0 | 667 | * canvas.restore(); |
michael@0 | 668 | * though it is almost always much more efficient. |
michael@0 | 669 | */ |
michael@0 | 670 | virtual void clear(SkColor); |
michael@0 | 671 | |
michael@0 | 672 | /** |
michael@0 | 673 | * Fill the entire canvas' bitmap (restricted to the current clip) with the |
michael@0 | 674 | * specified paint. |
michael@0 | 675 | * @param paint The paint used to fill the canvas |
michael@0 | 676 | */ |
michael@0 | 677 | virtual void drawPaint(const SkPaint& paint); |
michael@0 | 678 | |
michael@0 | 679 | enum PointMode { |
michael@0 | 680 | /** drawPoints draws each point separately */ |
michael@0 | 681 | kPoints_PointMode, |
michael@0 | 682 | /** drawPoints draws each pair of points as a line segment */ |
michael@0 | 683 | kLines_PointMode, |
michael@0 | 684 | /** drawPoints draws the array of points as a polygon */ |
michael@0 | 685 | kPolygon_PointMode |
michael@0 | 686 | }; |
michael@0 | 687 | |
michael@0 | 688 | /** Draw a series of points, interpreted based on the PointMode mode. For |
michael@0 | 689 | all modes, the count parameter is interpreted as the total number of |
michael@0 | 690 | points. For kLine mode, count/2 line segments are drawn. |
michael@0 | 691 | For kPoint mode, each point is drawn centered at its coordinate, and its |
michael@0 | 692 | size is specified by the paint's stroke-width. It draws as a square, |
michael@0 | 693 | unless the paint's cap-type is round, in which the points are drawn as |
michael@0 | 694 | circles. |
michael@0 | 695 | For kLine mode, each pair of points is drawn as a line segment, |
michael@0 | 696 | respecting the paint's settings for cap/join/width. |
michael@0 | 697 | For kPolygon mode, the entire array is drawn as a series of connected |
michael@0 | 698 | line segments. |
michael@0 | 699 | Note that, while similar, kLine and kPolygon modes draw slightly |
michael@0 | 700 | differently than the equivalent path built with a series of moveto, |
michael@0 | 701 | lineto calls, in that the path will draw all of its contours at once, |
michael@0 | 702 | with no interactions if contours intersect each other (think XOR |
michael@0 | 703 | xfermode). drawPoints always draws each element one at a time. |
michael@0 | 704 | @param mode PointMode specifying how to draw the array of points. |
michael@0 | 705 | @param count The number of points in the array |
michael@0 | 706 | @param pts Array of points to draw |
michael@0 | 707 | @param paint The paint used to draw the points |
michael@0 | 708 | */ |
michael@0 | 709 | virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], |
michael@0 | 710 | const SkPaint& paint); |
michael@0 | 711 | |
michael@0 | 712 | /** Helper method for drawing a single point. See drawPoints() for a more |
michael@0 | 713 | details. |
michael@0 | 714 | */ |
michael@0 | 715 | void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint); |
michael@0 | 716 | |
michael@0 | 717 | /** Draws a single pixel in the specified color. |
michael@0 | 718 | @param x The X coordinate of which pixel to draw |
michael@0 | 719 | @param y The Y coordiante of which pixel to draw |
michael@0 | 720 | @param color The color to draw |
michael@0 | 721 | */ |
michael@0 | 722 | void drawPoint(SkScalar x, SkScalar y, SkColor color); |
michael@0 | 723 | |
michael@0 | 724 | /** Draw a line segment with the specified start and stop x,y coordinates, |
michael@0 | 725 | using the specified paint. NOTE: since a line is always "framed", the |
michael@0 | 726 | paint's Style is ignored. |
michael@0 | 727 | @param x0 The x-coordinate of the start point of the line |
michael@0 | 728 | @param y0 The y-coordinate of the start point of the line |
michael@0 | 729 | @param x1 The x-coordinate of the end point of the line |
michael@0 | 730 | @param y1 The y-coordinate of the end point of the line |
michael@0 | 731 | @param paint The paint used to draw the line |
michael@0 | 732 | */ |
michael@0 | 733 | void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, |
michael@0 | 734 | const SkPaint& paint); |
michael@0 | 735 | |
michael@0 | 736 | /** Draw the specified rectangle using the specified paint. The rectangle |
michael@0 | 737 | will be filled or stroked based on the Style in the paint. |
michael@0 | 738 | @param rect The rect to be drawn |
michael@0 | 739 | @param paint The paint used to draw the rect |
michael@0 | 740 | */ |
michael@0 | 741 | virtual void drawRect(const SkRect& rect, const SkPaint& paint); |
michael@0 | 742 | |
michael@0 | 743 | /** Draw the specified rectangle using the specified paint. The rectangle |
michael@0 | 744 | will be filled or framed based on the Style in the paint. |
michael@0 | 745 | @param rect The rect to be drawn |
michael@0 | 746 | @param paint The paint used to draw the rect |
michael@0 | 747 | */ |
michael@0 | 748 | void drawIRect(const SkIRect& rect, const SkPaint& paint) { |
michael@0 | 749 | SkRect r; |
michael@0 | 750 | r.set(rect); // promotes the ints to scalars |
michael@0 | 751 | this->drawRect(r, paint); |
michael@0 | 752 | } |
michael@0 | 753 | |
michael@0 | 754 | /** Draw the specified rectangle using the specified paint. The rectangle |
michael@0 | 755 | will be filled or framed based on the Style in the paint. |
michael@0 | 756 | @param left The left side of the rectangle to be drawn |
michael@0 | 757 | @param top The top side of the rectangle to be drawn |
michael@0 | 758 | @param right The right side of the rectangle to be drawn |
michael@0 | 759 | @param bottom The bottom side of the rectangle to be drawn |
michael@0 | 760 | @param paint The paint used to draw the rect |
michael@0 | 761 | */ |
michael@0 | 762 | void drawRectCoords(SkScalar left, SkScalar top, SkScalar right, |
michael@0 | 763 | SkScalar bottom, const SkPaint& paint); |
michael@0 | 764 | |
michael@0 | 765 | /** Draw the specified oval using the specified paint. The oval will be |
michael@0 | 766 | filled or framed based on the Style in the paint. |
michael@0 | 767 | @param oval The rectangle bounds of the oval to be drawn |
michael@0 | 768 | @param paint The paint used to draw the oval |
michael@0 | 769 | */ |
michael@0 | 770 | virtual void drawOval(const SkRect& oval, const SkPaint&); |
michael@0 | 771 | |
michael@0 | 772 | /** |
michael@0 | 773 | * Draw the specified RRect using the specified paint The rrect will be filled or stroked |
michael@0 | 774 | * based on the Style in the paint. |
michael@0 | 775 | * |
michael@0 | 776 | * @param rrect The round-rect to draw |
michael@0 | 777 | * @param paint The paint used to draw the round-rect |
michael@0 | 778 | */ |
michael@0 | 779 | virtual void drawRRect(const SkRRect& rrect, const SkPaint& paint); |
michael@0 | 780 | |
michael@0 | 781 | /** |
michael@0 | 782 | * Draw the annulus formed by the outer and inner rrects. The results |
michael@0 | 783 | * are undefined if the outer does not contain the inner. |
michael@0 | 784 | */ |
michael@0 | 785 | void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint&); |
michael@0 | 786 | |
michael@0 | 787 | /** Draw the specified circle using the specified paint. If radius is <= 0, |
michael@0 | 788 | then nothing will be drawn. The circle will be filled |
michael@0 | 789 | or framed based on the Style in the paint. |
michael@0 | 790 | @param cx The x-coordinate of the center of the cirle to be drawn |
michael@0 | 791 | @param cy The y-coordinate of the center of the cirle to be drawn |
michael@0 | 792 | @param radius The radius of the cirle to be drawn |
michael@0 | 793 | @param paint The paint used to draw the circle |
michael@0 | 794 | */ |
michael@0 | 795 | void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, |
michael@0 | 796 | const SkPaint& paint); |
michael@0 | 797 | |
michael@0 | 798 | /** Draw the specified arc, which will be scaled to fit inside the |
michael@0 | 799 | specified oval. If the sweep angle is >= 360, then the oval is drawn |
michael@0 | 800 | completely. Note that this differs slightly from SkPath::arcTo, which |
michael@0 | 801 | treats the sweep angle mod 360. |
michael@0 | 802 | @param oval The bounds of oval used to define the shape of the arc |
michael@0 | 803 | @param startAngle Starting angle (in degrees) where the arc begins |
michael@0 | 804 | @param sweepAngle Sweep angle (in degrees) measured clockwise |
michael@0 | 805 | @param useCenter true means include the center of the oval. For filling |
michael@0 | 806 | this will draw a wedge. False means just use the arc. |
michael@0 | 807 | @param paint The paint used to draw the arc |
michael@0 | 808 | */ |
michael@0 | 809 | void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, |
michael@0 | 810 | bool useCenter, const SkPaint& paint); |
michael@0 | 811 | |
michael@0 | 812 | /** Draw the specified round-rect using the specified paint. The round-rect |
michael@0 | 813 | will be filled or framed based on the Style in the paint. |
michael@0 | 814 | @param rect The rectangular bounds of the roundRect to be drawn |
michael@0 | 815 | @param rx The x-radius of the oval used to round the corners |
michael@0 | 816 | @param ry The y-radius of the oval used to round the corners |
michael@0 | 817 | @param paint The paint used to draw the roundRect |
michael@0 | 818 | */ |
michael@0 | 819 | void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, |
michael@0 | 820 | const SkPaint& paint); |
michael@0 | 821 | |
michael@0 | 822 | /** Draw the specified path using the specified paint. The path will be |
michael@0 | 823 | filled or framed based on the Style in the paint. |
michael@0 | 824 | @param path The path to be drawn |
michael@0 | 825 | @param paint The paint used to draw the path |
michael@0 | 826 | */ |
michael@0 | 827 | virtual void drawPath(const SkPath& path, const SkPaint& paint); |
michael@0 | 828 | |
michael@0 | 829 | /** Draw the specified bitmap, with its top/left corner at (x,y), using the |
michael@0 | 830 | specified paint, transformed by the current matrix. Note: if the paint |
michael@0 | 831 | contains a maskfilter that generates a mask which extends beyond the |
michael@0 | 832 | bitmap's original width/height, then the bitmap will be drawn as if it |
michael@0 | 833 | were in a Shader with CLAMP mode. Thus the color outside of the original |
michael@0 | 834 | width/height will be the edge color replicated. |
michael@0 | 835 | |
michael@0 | 836 | If a shader is present on the paint it will be ignored, except in the |
michael@0 | 837 | case where the bitmap is kA8_Config. In that case, the color is |
michael@0 | 838 | generated by the shader. |
michael@0 | 839 | |
michael@0 | 840 | @param bitmap The bitmap to be drawn |
michael@0 | 841 | @param left The position of the left side of the bitmap being drawn |
michael@0 | 842 | @param top The position of the top side of the bitmap being drawn |
michael@0 | 843 | @param paint The paint used to draw the bitmap, or NULL |
michael@0 | 844 | */ |
michael@0 | 845 | virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, |
michael@0 | 846 | const SkPaint* paint = NULL); |
michael@0 | 847 | |
michael@0 | 848 | enum DrawBitmapRectFlags { |
michael@0 | 849 | kNone_DrawBitmapRectFlag = 0x0, |
michael@0 | 850 | /** |
michael@0 | 851 | * When filtering is enabled, allow the color samples outside of |
michael@0 | 852 | * the src rect (but still in the src bitmap) to bleed into the |
michael@0 | 853 | * drawn portion |
michael@0 | 854 | */ |
michael@0 | 855 | kBleed_DrawBitmapRectFlag = 0x1, |
michael@0 | 856 | }; |
michael@0 | 857 | |
michael@0 | 858 | /** Draw the specified bitmap, with the specified matrix applied (before the |
michael@0 | 859 | canvas' matrix is applied). |
michael@0 | 860 | @param bitmap The bitmap to be drawn |
michael@0 | 861 | @param src Optional: specify the subset of the bitmap to be drawn |
michael@0 | 862 | @param dst The destination rectangle where the scaled/translated |
michael@0 | 863 | image will be drawn |
michael@0 | 864 | @param paint The paint used to draw the bitmap, or NULL |
michael@0 | 865 | */ |
michael@0 | 866 | virtual void drawBitmapRectToRect(const SkBitmap& bitmap, const SkRect* src, |
michael@0 | 867 | const SkRect& dst, |
michael@0 | 868 | const SkPaint* paint = NULL, |
michael@0 | 869 | DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag); |
michael@0 | 870 | |
michael@0 | 871 | void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, |
michael@0 | 872 | const SkPaint* paint = NULL) { |
michael@0 | 873 | this->drawBitmapRectToRect(bitmap, NULL, dst, paint, kNone_DrawBitmapRectFlag); |
michael@0 | 874 | } |
michael@0 | 875 | |
michael@0 | 876 | void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* isrc, |
michael@0 | 877 | const SkRect& dst, const SkPaint* paint = NULL, |
michael@0 | 878 | DrawBitmapRectFlags flags = kNone_DrawBitmapRectFlag) { |
michael@0 | 879 | SkRect realSrcStorage; |
michael@0 | 880 | SkRect* realSrcPtr = NULL; |
michael@0 | 881 | if (isrc) { |
michael@0 | 882 | realSrcStorage.set(*isrc); |
michael@0 | 883 | realSrcPtr = &realSrcStorage; |
michael@0 | 884 | } |
michael@0 | 885 | this->drawBitmapRectToRect(bitmap, realSrcPtr, dst, paint, flags); |
michael@0 | 886 | } |
michael@0 | 887 | |
michael@0 | 888 | virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, |
michael@0 | 889 | const SkPaint* paint = NULL); |
michael@0 | 890 | |
michael@0 | 891 | /** |
michael@0 | 892 | * Draw the bitmap stretched differentially to fit into dst. |
michael@0 | 893 | * center is a rect within the bitmap, and logically divides the bitmap |
michael@0 | 894 | * into 9 sections (3x3). For example, if the middle pixel of a [5x5] |
michael@0 | 895 | * bitmap is the "center", then the center-rect should be [2, 2, 3, 3]. |
michael@0 | 896 | * |
michael@0 | 897 | * If the dst is >= the bitmap size, then... |
michael@0 | 898 | * - The 4 corners are not stretched at all. |
michael@0 | 899 | * - The sides are stretched in only one axis. |
michael@0 | 900 | * - The center is stretched in both axes. |
michael@0 | 901 | * Else, for each axis where dst < bitmap, |
michael@0 | 902 | * - The corners shrink proportionally |
michael@0 | 903 | * - The sides (along the shrink axis) and center are not drawn |
michael@0 | 904 | */ |
michael@0 | 905 | virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, |
michael@0 | 906 | const SkRect& dst, const SkPaint* paint = NULL); |
michael@0 | 907 | |
michael@0 | 908 | /** Draw the specified bitmap, with its top/left corner at (x,y), |
michael@0 | 909 | NOT transformed by the current matrix. Note: if the paint |
michael@0 | 910 | contains a maskfilter that generates a mask which extends beyond the |
michael@0 | 911 | bitmap's original width/height, then the bitmap will be drawn as if it |
michael@0 | 912 | were in a Shader with CLAMP mode. Thus the color outside of the original |
michael@0 | 913 | width/height will be the edge color replicated. |
michael@0 | 914 | @param bitmap The bitmap to be drawn |
michael@0 | 915 | @param left The position of the left side of the bitmap being drawn |
michael@0 | 916 | @param top The position of the top side of the bitmap being drawn |
michael@0 | 917 | @param paint The paint used to draw the bitmap, or NULL |
michael@0 | 918 | */ |
michael@0 | 919 | virtual void drawSprite(const SkBitmap& bitmap, int left, int top, |
michael@0 | 920 | const SkPaint* paint = NULL); |
michael@0 | 921 | |
michael@0 | 922 | /** Draw the text, with origin at (x,y), using the specified paint. |
michael@0 | 923 | The origin is interpreted based on the Align setting in the paint. |
michael@0 | 924 | @param text The text to be drawn |
michael@0 | 925 | @param byteLength The number of bytes to read from the text parameter |
michael@0 | 926 | @param x The x-coordinate of the origin of the text being drawn |
michael@0 | 927 | @param y The y-coordinate of the origin of the text being drawn |
michael@0 | 928 | @param paint The paint used for the text (e.g. color, size, style) |
michael@0 | 929 | */ |
michael@0 | 930 | virtual void drawText(const void* text, size_t byteLength, SkScalar x, |
michael@0 | 931 | SkScalar y, const SkPaint& paint); |
michael@0 | 932 | |
michael@0 | 933 | /** Draw the text, with each character/glyph origin specified by the pos[] |
michael@0 | 934 | array. The origin is interpreted by the Align setting in the paint. |
michael@0 | 935 | @param text The text to be drawn |
michael@0 | 936 | @param byteLength The number of bytes to read from the text parameter |
michael@0 | 937 | @param pos Array of positions, used to position each character |
michael@0 | 938 | @param paint The paint used for the text (e.g. color, size, style) |
michael@0 | 939 | */ |
michael@0 | 940 | virtual void drawPosText(const void* text, size_t byteLength, |
michael@0 | 941 | const SkPoint pos[], const SkPaint& paint); |
michael@0 | 942 | |
michael@0 | 943 | /** Draw the text, with each character/glyph origin specified by the x |
michael@0 | 944 | coordinate taken from the xpos[] array, and the y from the constY param. |
michael@0 | 945 | The origin is interpreted by the Align setting in the paint. |
michael@0 | 946 | @param text The text to be drawn |
michael@0 | 947 | @param byteLength The number of bytes to read from the text parameter |
michael@0 | 948 | @param xpos Array of x-positions, used to position each character |
michael@0 | 949 | @param constY The shared Y coordinate for all of the positions |
michael@0 | 950 | @param paint The paint used for the text (e.g. color, size, style) |
michael@0 | 951 | */ |
michael@0 | 952 | virtual void drawPosTextH(const void* text, size_t byteLength, |
michael@0 | 953 | const SkScalar xpos[], SkScalar constY, |
michael@0 | 954 | const SkPaint& paint); |
michael@0 | 955 | |
michael@0 | 956 | /** Draw the text, with origin at (x,y), using the specified paint, along |
michael@0 | 957 | the specified path. The paint's Align setting determins where along the |
michael@0 | 958 | path to start the text. |
michael@0 | 959 | @param text The text to be drawn |
michael@0 | 960 | @param byteLength The number of bytes to read from the text parameter |
michael@0 | 961 | @param path The path the text should follow for its baseline |
michael@0 | 962 | @param hOffset The distance along the path to add to the text's |
michael@0 | 963 | starting position |
michael@0 | 964 | @param vOffset The distance above(-) or below(+) the path to |
michael@0 | 965 | position the text |
michael@0 | 966 | @param paint The paint used for the text |
michael@0 | 967 | */ |
michael@0 | 968 | void drawTextOnPathHV(const void* text, size_t byteLength, |
michael@0 | 969 | const SkPath& path, SkScalar hOffset, |
michael@0 | 970 | SkScalar vOffset, const SkPaint& paint); |
michael@0 | 971 | |
michael@0 | 972 | /** Draw the text, with origin at (x,y), using the specified paint, along |
michael@0 | 973 | the specified path. The paint's Align setting determins where along the |
michael@0 | 974 | path to start the text. |
michael@0 | 975 | @param text The text to be drawn |
michael@0 | 976 | @param byteLength The number of bytes to read from the text parameter |
michael@0 | 977 | @param path The path the text should follow for its baseline |
michael@0 | 978 | @param matrix (may be null) Applied to the text before it is |
michael@0 | 979 | mapped onto the path |
michael@0 | 980 | @param paint The paint used for the text |
michael@0 | 981 | */ |
michael@0 | 982 | virtual void drawTextOnPath(const void* text, size_t byteLength, |
michael@0 | 983 | const SkPath& path, const SkMatrix* matrix, |
michael@0 | 984 | const SkPaint& paint); |
michael@0 | 985 | |
michael@0 | 986 | /** PRIVATE / EXPERIMENTAL -- do not call |
michael@0 | 987 | Perform back-end analysis/optimization of a picture. This may attach |
michael@0 | 988 | optimization data to the picture which can be used by a later |
michael@0 | 989 | drawPicture call. |
michael@0 | 990 | @param picture The recorded drawing commands to analyze/optimize |
michael@0 | 991 | */ |
michael@0 | 992 | void EXPERIMENTAL_optimize(SkPicture* picture); |
michael@0 | 993 | |
michael@0 | 994 | /** Draw the picture into this canvas. This method effective brackets the |
michael@0 | 995 | playback of the picture's draw calls with save/restore, so the state |
michael@0 | 996 | of this canvas will be unchanged after this call. |
michael@0 | 997 | @param picture The recorded drawing commands to playback into this |
michael@0 | 998 | canvas. |
michael@0 | 999 | */ |
michael@0 | 1000 | virtual void drawPicture(SkPicture& picture); |
michael@0 | 1001 | |
michael@0 | 1002 | enum VertexMode { |
michael@0 | 1003 | kTriangles_VertexMode, |
michael@0 | 1004 | kTriangleStrip_VertexMode, |
michael@0 | 1005 | kTriangleFan_VertexMode |
michael@0 | 1006 | }; |
michael@0 | 1007 | |
michael@0 | 1008 | /** Draw the array of vertices, interpreted as triangles (based on mode). |
michael@0 | 1009 | @param vmode How to interpret the array of vertices |
michael@0 | 1010 | @param vertexCount The number of points in the vertices array (and |
michael@0 | 1011 | corresponding texs and colors arrays if non-null) |
michael@0 | 1012 | @param vertices Array of vertices for the mesh |
michael@0 | 1013 | @param texs May be null. If not null, specifies the coordinate |
michael@0 | 1014 | in _texture_ space (not uv space) for each vertex. |
michael@0 | 1015 | @param colors May be null. If not null, specifies a color for each |
michael@0 | 1016 | vertex, to be interpolated across the triangle. |
michael@0 | 1017 | @param xmode Used if both texs and colors are present. In this |
michael@0 | 1018 | case the colors are combined with the texture using mode, |
michael@0 | 1019 | before being drawn using the paint. If mode is null, then |
michael@0 | 1020 | kModulate_Mode is used. |
michael@0 | 1021 | @param indices If not null, array of indices to reference into the |
michael@0 | 1022 | vertex (texs, colors) array. |
michael@0 | 1023 | @param indexCount number of entries in the indices array (if not null) |
michael@0 | 1024 | @param paint Specifies the shader/texture if present. |
michael@0 | 1025 | */ |
michael@0 | 1026 | virtual void drawVertices(VertexMode vmode, int vertexCount, |
michael@0 | 1027 | const SkPoint vertices[], const SkPoint texs[], |
michael@0 | 1028 | const SkColor colors[], SkXfermode* xmode, |
michael@0 | 1029 | const uint16_t indices[], int indexCount, |
michael@0 | 1030 | const SkPaint& paint); |
michael@0 | 1031 | |
michael@0 | 1032 | /** Send a blob of data to the canvas. |
michael@0 | 1033 | For canvases that draw, this call is effectively a no-op, as the data |
michael@0 | 1034 | is not parsed, but just ignored. However, this call exists for |
michael@0 | 1035 | subclasses like SkPicture's recording canvas, that can store the data |
michael@0 | 1036 | and then play it back later (via another call to drawData). |
michael@0 | 1037 | */ |
michael@0 | 1038 | virtual void drawData(const void* data, size_t length) { |
michael@0 | 1039 | // do nothing. Subclasses may do something with the data |
michael@0 | 1040 | } |
michael@0 | 1041 | |
michael@0 | 1042 | /** Add comments. beginCommentGroup/endCommentGroup open/close a new group. |
michael@0 | 1043 | Each comment added via addComment is notionally attached to its |
michael@0 | 1044 | enclosing group. Top-level comments simply belong to no group. |
michael@0 | 1045 | */ |
michael@0 | 1046 | virtual void beginCommentGroup(const char* description) { |
michael@0 | 1047 | // do nothing. Subclasses may do something |
michael@0 | 1048 | } |
michael@0 | 1049 | virtual void addComment(const char* kywd, const char* value) { |
michael@0 | 1050 | // do nothing. Subclasses may do something |
michael@0 | 1051 | } |
michael@0 | 1052 | virtual void endCommentGroup() { |
michael@0 | 1053 | // do nothing. Subclasses may do something |
michael@0 | 1054 | } |
michael@0 | 1055 | |
michael@0 | 1056 | /** |
michael@0 | 1057 | * With this call the client asserts that subsequent draw operations (up to the |
michael@0 | 1058 | * matching popCull()) are fully contained within the given bounding box. The assertion |
michael@0 | 1059 | * is not enforced, but the information might be used to quick-reject command blocks, |
michael@0 | 1060 | * so an incorrect bounding box may result in incomplete rendering. |
michael@0 | 1061 | */ |
michael@0 | 1062 | void pushCull(const SkRect& cullRect) { |
michael@0 | 1063 | ++fCullCount; |
michael@0 | 1064 | this->onPushCull(cullRect); |
michael@0 | 1065 | } |
michael@0 | 1066 | |
michael@0 | 1067 | /** |
michael@0 | 1068 | * Terminates the current culling block, and restores the previous one (if any). |
michael@0 | 1069 | */ |
michael@0 | 1070 | void popCull() { |
michael@0 | 1071 | if (fCullCount > 0) { |
michael@0 | 1072 | --fCullCount; |
michael@0 | 1073 | this->onPopCull(); |
michael@0 | 1074 | } |
michael@0 | 1075 | } |
michael@0 | 1076 | ////////////////////////////////////////////////////////////////////////// |
michael@0 | 1077 | |
michael@0 | 1078 | /** Get the current bounder object. |
michael@0 | 1079 | The bounder's reference count is unchaged. |
michael@0 | 1080 | @return the canva's bounder (or NULL). |
michael@0 | 1081 | */ |
michael@0 | 1082 | SkBounder* getBounder() const { return fBounder; } |
michael@0 | 1083 | |
michael@0 | 1084 | /** Set a new bounder (or NULL). |
michael@0 | 1085 | Pass NULL to clear any previous bounder. |
michael@0 | 1086 | As a convenience, the parameter passed is also returned. |
michael@0 | 1087 | If a previous bounder exists, its reference count is decremented. |
michael@0 | 1088 | If bounder is not NULL, its reference count is incremented. |
michael@0 | 1089 | @param bounder the new bounder (or NULL) to be installed in the canvas |
michael@0 | 1090 | @return the set bounder object |
michael@0 | 1091 | */ |
michael@0 | 1092 | virtual SkBounder* setBounder(SkBounder* bounder); |
michael@0 | 1093 | |
michael@0 | 1094 | /** Get the current filter object. The filter's reference count is not |
michael@0 | 1095 | affected. The filter is saved/restored, just like the matrix and clip. |
michael@0 | 1096 | @return the canvas' filter (or NULL). |
michael@0 | 1097 | */ |
michael@0 | 1098 | SkDrawFilter* getDrawFilter() const; |
michael@0 | 1099 | |
michael@0 | 1100 | /** Set the new filter (or NULL). Pass NULL to clear any existing filter. |
michael@0 | 1101 | As a convenience, the parameter is returned. If an existing filter |
michael@0 | 1102 | exists, its refcnt is decrement. If the new filter is not null, its |
michael@0 | 1103 | refcnt is incremented. The filter is saved/restored, just like the |
michael@0 | 1104 | matrix and clip. |
michael@0 | 1105 | @param filter the new filter (or NULL) |
michael@0 | 1106 | @return the new filter |
michael@0 | 1107 | */ |
michael@0 | 1108 | virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter); |
michael@0 | 1109 | |
michael@0 | 1110 | ////////////////////////////////////////////////////////////////////////// |
michael@0 | 1111 | |
michael@0 | 1112 | /** |
michael@0 | 1113 | * Return true if the current clip is empty (i.e. nothing will draw). |
michael@0 | 1114 | * Note: this is not always a free call, so it should not be used |
michael@0 | 1115 | * more often than necessary. However, once the canvas has computed this |
michael@0 | 1116 | * result, subsequent calls will be cheap (until the clip state changes, |
michael@0 | 1117 | * which can happen on any clip..() or restore() call. |
michael@0 | 1118 | */ |
michael@0 | 1119 | virtual bool isClipEmpty() const; |
michael@0 | 1120 | |
michael@0 | 1121 | /** |
michael@0 | 1122 | * Returns true if the current clip is just a (non-empty) rectangle. |
michael@0 | 1123 | * Returns false if the clip is empty, or if it is complex. |
michael@0 | 1124 | */ |
michael@0 | 1125 | virtual bool isClipRect() const; |
michael@0 | 1126 | |
michael@0 | 1127 | /** Return the current matrix on the canvas. |
michael@0 | 1128 | This does not account for the translate in any of the devices. |
michael@0 | 1129 | @return The current matrix on the canvas. |
michael@0 | 1130 | */ |
michael@0 | 1131 | const SkMatrix& getTotalMatrix() const; |
michael@0 | 1132 | |
michael@0 | 1133 | #ifdef SK_SUPPORT_LEGACY_GETCLIPTYPE |
michael@0 | 1134 | enum ClipType { |
michael@0 | 1135 | kEmpty_ClipType = 0, |
michael@0 | 1136 | kRect_ClipType, |
michael@0 | 1137 | kComplex_ClipType |
michael@0 | 1138 | }; |
michael@0 | 1139 | /** Returns a description of the total clip; may be cheaper than |
michael@0 | 1140 | getting the clip and querying it directly. |
michael@0 | 1141 | */ |
michael@0 | 1142 | virtual ClipType getClipType() const; |
michael@0 | 1143 | #endif |
michael@0 | 1144 | |
michael@0 | 1145 | #ifdef SK_SUPPORT_LEGACY_GETTOTALCLIP |
michael@0 | 1146 | /** DEPRECATED -- need to move this guy to private/friend |
michael@0 | 1147 | * Return the current device clip (concatenation of all clip calls). |
michael@0 | 1148 | * This does not account for the translate in any of the devices. |
michael@0 | 1149 | * @return the current device clip (concatenation of all clip calls). |
michael@0 | 1150 | */ |
michael@0 | 1151 | const SkRegion& getTotalClip() const; |
michael@0 | 1152 | #endif |
michael@0 | 1153 | |
michael@0 | 1154 | /** Return the clip stack. The clip stack stores all the individual |
michael@0 | 1155 | * clips organized by the save/restore frame in which they were |
michael@0 | 1156 | * added. |
michael@0 | 1157 | * @return the current clip stack ("list" of individual clip elements) |
michael@0 | 1158 | */ |
michael@0 | 1159 | const SkClipStack* getClipStack() const { |
michael@0 | 1160 | return &fClipStack; |
michael@0 | 1161 | } |
michael@0 | 1162 | |
michael@0 | 1163 | class ClipVisitor { |
michael@0 | 1164 | public: |
michael@0 | 1165 | virtual ~ClipVisitor(); |
michael@0 | 1166 | virtual void clipRect(const SkRect&, SkRegion::Op, bool antialias) = 0; |
michael@0 | 1167 | virtual void clipRRect(const SkRRect&, SkRegion::Op, bool antialias) = 0; |
michael@0 | 1168 | virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) = 0; |
michael@0 | 1169 | }; |
michael@0 | 1170 | |
michael@0 | 1171 | /** |
michael@0 | 1172 | * Replays the clip operations, back to front, that have been applied to |
michael@0 | 1173 | * the canvas, calling the appropriate method on the visitor for each |
michael@0 | 1174 | * clip. All clips have already been transformed into device space. |
michael@0 | 1175 | */ |
michael@0 | 1176 | void replayClips(ClipVisitor*) const; |
michael@0 | 1177 | |
michael@0 | 1178 | /////////////////////////////////////////////////////////////////////////// |
michael@0 | 1179 | |
michael@0 | 1180 | /** After calling saveLayer(), there can be any number of devices that make |
michael@0 | 1181 | up the top-most drawing area. LayerIter can be used to iterate through |
michael@0 | 1182 | those devices. Note that the iterator is only valid until the next API |
michael@0 | 1183 | call made on the canvas. Ownership of all pointers in the iterator stays |
michael@0 | 1184 | with the canvas, so none of them should be modified or deleted. |
michael@0 | 1185 | */ |
michael@0 | 1186 | class SK_API LayerIter /*: SkNoncopyable*/ { |
michael@0 | 1187 | public: |
michael@0 | 1188 | /** Initialize iterator with canvas, and set values for 1st device */ |
michael@0 | 1189 | LayerIter(SkCanvas*, bool skipEmptyClips); |
michael@0 | 1190 | ~LayerIter(); |
michael@0 | 1191 | |
michael@0 | 1192 | /** Return true if the iterator is done */ |
michael@0 | 1193 | bool done() const { return fDone; } |
michael@0 | 1194 | /** Cycle to the next device */ |
michael@0 | 1195 | void next(); |
michael@0 | 1196 | |
michael@0 | 1197 | // These reflect the current device in the iterator |
michael@0 | 1198 | |
michael@0 | 1199 | SkBaseDevice* device() const; |
michael@0 | 1200 | const SkMatrix& matrix() const; |
michael@0 | 1201 | const SkRegion& clip() const; |
michael@0 | 1202 | const SkPaint& paint() const; |
michael@0 | 1203 | int x() const; |
michael@0 | 1204 | int y() const; |
michael@0 | 1205 | |
michael@0 | 1206 | private: |
michael@0 | 1207 | // used to embed the SkDrawIter object directly in our instance, w/o |
michael@0 | 1208 | // having to expose that class def to the public. There is an assert |
michael@0 | 1209 | // in our constructor to ensure that fStorage is large enough |
michael@0 | 1210 | // (though needs to be a compile-time-assert!). We use intptr_t to work |
michael@0 | 1211 | // safely with 32 and 64 bit machines (to ensure the storage is enough) |
michael@0 | 1212 | intptr_t fStorage[32]; |
michael@0 | 1213 | class SkDrawIter* fImpl; // this points at fStorage |
michael@0 | 1214 | SkPaint fDefaultPaint; |
michael@0 | 1215 | bool fDone; |
michael@0 | 1216 | }; |
michael@0 | 1217 | |
michael@0 | 1218 | // don't call |
michael@0 | 1219 | const SkRegion& internal_private_getTotalClip() const; |
michael@0 | 1220 | // don't call |
michael@0 | 1221 | void internal_private_getTotalClipAsPath(SkPath*) const; |
michael@0 | 1222 | // don't call |
michael@0 | 1223 | GrRenderTarget* internal_private_accessTopLayerRenderTarget(); |
michael@0 | 1224 | |
michael@0 | 1225 | protected: |
michael@0 | 1226 | // default impl defers to getDevice()->newSurface(info) |
michael@0 | 1227 | virtual SkSurface* onNewSurface(const SkImageInfo&); |
michael@0 | 1228 | |
michael@0 | 1229 | // default impl defers to its device |
michael@0 | 1230 | virtual const void* onPeekPixels(SkImageInfo*, size_t* rowBytes); |
michael@0 | 1231 | virtual void* onAccessTopLayerPixels(SkImageInfo*, size_t* rowBytes); |
michael@0 | 1232 | |
michael@0 | 1233 | // Subclass save/restore notifiers. |
michael@0 | 1234 | // Overriders should call the corresponding INHERITED method up the inheritance chain. |
michael@0 | 1235 | // willSaveLayer()'s return value may suppress full layer allocation. |
michael@0 | 1236 | enum SaveLayerStrategy { |
michael@0 | 1237 | kFullLayer_SaveLayerStrategy, |
michael@0 | 1238 | kNoLayer_SaveLayerStrategy |
michael@0 | 1239 | }; |
michael@0 | 1240 | virtual void willSave(SaveFlags); |
michael@0 | 1241 | virtual SaveLayerStrategy willSaveLayer(const SkRect*, const SkPaint*, SaveFlags); |
michael@0 | 1242 | virtual void willRestore(); |
michael@0 | 1243 | |
michael@0 | 1244 | virtual void didTranslate(SkScalar, SkScalar); |
michael@0 | 1245 | virtual void didScale(SkScalar, SkScalar); |
michael@0 | 1246 | virtual void didRotate(SkScalar); |
michael@0 | 1247 | virtual void didSkew(SkScalar, SkScalar); |
michael@0 | 1248 | virtual void didConcat(const SkMatrix&); |
michael@0 | 1249 | virtual void didSetMatrix(const SkMatrix&); |
michael@0 | 1250 | |
michael@0 | 1251 | virtual void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&); |
michael@0 | 1252 | |
michael@0 | 1253 | enum ClipEdgeStyle { |
michael@0 | 1254 | kHard_ClipEdgeStyle, |
michael@0 | 1255 | kSoft_ClipEdgeStyle |
michael@0 | 1256 | }; |
michael@0 | 1257 | |
michael@0 | 1258 | virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle); |
michael@0 | 1259 | virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle); |
michael@0 | 1260 | virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle); |
michael@0 | 1261 | virtual void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op); |
michael@0 | 1262 | |
michael@0 | 1263 | // Returns the canvas to be used by DrawIter. Default implementation |
michael@0 | 1264 | // returns this. Subclasses that encapsulate an indirect canvas may |
michael@0 | 1265 | // need to overload this method. The impl must keep track of this, as it |
michael@0 | 1266 | // is not released or deleted by the caller. |
michael@0 | 1267 | virtual SkCanvas* canvasForDrawIter(); |
michael@0 | 1268 | |
michael@0 | 1269 | // Clip rectangle bounds. Called internally by saveLayer. |
michael@0 | 1270 | // returns false if the entire rectangle is entirely clipped out |
michael@0 | 1271 | // If non-NULL, The imageFilter parameter will be used to expand the clip |
michael@0 | 1272 | // and offscreen bounds for any margin required by the filter DAG. |
michael@0 | 1273 | bool clipRectBounds(const SkRect* bounds, SaveFlags flags, |
michael@0 | 1274 | SkIRect* intersection, |
michael@0 | 1275 | const SkImageFilter* imageFilter = NULL); |
michael@0 | 1276 | |
michael@0 | 1277 | // Called by child classes that override clipPath and clipRRect to only |
michael@0 | 1278 | // track fast conservative clip bounds, rather than exact clips. |
michael@0 | 1279 | void updateClipConservativelyUsingBounds(const SkRect&, SkRegion::Op, |
michael@0 | 1280 | bool inverseFilled); |
michael@0 | 1281 | |
michael@0 | 1282 | // notify our surface (if we have one) that we are about to draw, so it |
michael@0 | 1283 | // can perform copy-on-write or invalidate any cached images |
michael@0 | 1284 | void predrawNotify(); |
michael@0 | 1285 | |
michael@0 | 1286 | virtual void onPushCull(const SkRect& cullRect); |
michael@0 | 1287 | virtual void onPopCull(); |
michael@0 | 1288 | |
michael@0 | 1289 | private: |
michael@0 | 1290 | class MCRec; |
michael@0 | 1291 | |
michael@0 | 1292 | SkClipStack fClipStack; |
michael@0 | 1293 | SkDeque fMCStack; |
michael@0 | 1294 | // points to top of stack |
michael@0 | 1295 | MCRec* fMCRec; |
michael@0 | 1296 | // the first N recs that can fit here mean we won't call malloc |
michael@0 | 1297 | uint32_t fMCRecStorage[32]; |
michael@0 | 1298 | |
michael@0 | 1299 | SkBounder* fBounder; |
michael@0 | 1300 | int fSaveLayerCount; // number of successful saveLayer calls |
michael@0 | 1301 | int fCullCount; // number of active culls |
michael@0 | 1302 | |
michael@0 | 1303 | SkMetaData* fMetaData; |
michael@0 | 1304 | |
michael@0 | 1305 | SkSurface_Base* fSurfaceBase; |
michael@0 | 1306 | SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; } |
michael@0 | 1307 | void setSurfaceBase(SkSurface_Base* sb) { |
michael@0 | 1308 | fSurfaceBase = sb; |
michael@0 | 1309 | } |
michael@0 | 1310 | friend class SkSurface_Base; |
michael@0 | 1311 | friend class SkSurface_Gpu; |
michael@0 | 1312 | |
michael@0 | 1313 | bool fDeviceCMDirty; // cleared by updateDeviceCMCache() |
michael@0 | 1314 | void updateDeviceCMCache(); |
michael@0 | 1315 | |
michael@0 | 1316 | friend class SkDrawIter; // needs setupDrawForLayerDevice() |
michael@0 | 1317 | friend class AutoDrawLooper; |
michael@0 | 1318 | friend class SkLua; // needs top layer size and offset |
michael@0 | 1319 | friend class SkDeferredDevice; // needs getTopDevice() |
michael@0 | 1320 | |
michael@0 | 1321 | SkBaseDevice* createLayerDevice(const SkImageInfo&); |
michael@0 | 1322 | |
michael@0 | 1323 | SkBaseDevice* init(SkBaseDevice*); |
michael@0 | 1324 | |
michael@0 | 1325 | /** |
michael@0 | 1326 | * DEPRECATED |
michael@0 | 1327 | * |
michael@0 | 1328 | * Specify a device for this canvas to draw into. If it is not null, its |
michael@0 | 1329 | * reference count is incremented. If the canvas was already holding a |
michael@0 | 1330 | * device, its reference count is decremented. The new device is returned. |
michael@0 | 1331 | */ |
michael@0 | 1332 | SkBaseDevice* setRootDevice(SkBaseDevice* device); |
michael@0 | 1333 | |
michael@0 | 1334 | /** |
michael@0 | 1335 | * Gets the size/origin of the top level layer in global canvas coordinates. We don't want this |
michael@0 | 1336 | * to be public because it exposes decisions about layer sizes that are internal to the canvas. |
michael@0 | 1337 | */ |
michael@0 | 1338 | SkISize getTopLayerSize() const; |
michael@0 | 1339 | SkIPoint getTopLayerOrigin() const; |
michael@0 | 1340 | |
michael@0 | 1341 | // internal methods are not virtual, so they can safely be called by other |
michael@0 | 1342 | // canvas apis, without confusing subclasses (like SkPictureRecording) |
michael@0 | 1343 | void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, const SkPaint* paint); |
michael@0 | 1344 | void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, |
michael@0 | 1345 | const SkRect& dst, const SkPaint* paint, |
michael@0 | 1346 | DrawBitmapRectFlags flags); |
michael@0 | 1347 | void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, |
michael@0 | 1348 | const SkRect& dst, const SkPaint* paint); |
michael@0 | 1349 | void internalDrawPaint(const SkPaint& paint); |
michael@0 | 1350 | int internalSaveLayer(const SkRect* bounds, const SkPaint* paint, |
michael@0 | 1351 | SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy); |
michael@0 | 1352 | void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*); |
michael@0 | 1353 | |
michael@0 | 1354 | // shared by save() and saveLayer() |
michael@0 | 1355 | int internalSave(SaveFlags flags); |
michael@0 | 1356 | void internalRestore(); |
michael@0 | 1357 | static void DrawRect(const SkDraw& draw, const SkPaint& paint, |
michael@0 | 1358 | const SkRect& r, SkScalar textSize); |
michael@0 | 1359 | static void DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, |
michael@0 | 1360 | const char text[], size_t byteLength, |
michael@0 | 1361 | SkScalar x, SkScalar y); |
michael@0 | 1362 | |
michael@0 | 1363 | /* These maintain a cache of the clip bounds in local coordinates, |
michael@0 | 1364 | (converted to 2s-compliment if floats are slow). |
michael@0 | 1365 | */ |
michael@0 | 1366 | mutable SkRect fCachedLocalClipBounds; |
michael@0 | 1367 | mutable bool fCachedLocalClipBoundsDirty; |
michael@0 | 1368 | bool fAllowSoftClip; |
michael@0 | 1369 | bool fAllowSimplifyClip; |
michael@0 | 1370 | |
michael@0 | 1371 | const SkRect& getLocalClipBounds() const { |
michael@0 | 1372 | if (fCachedLocalClipBoundsDirty) { |
michael@0 | 1373 | if (!this->getClipBounds(&fCachedLocalClipBounds)) { |
michael@0 | 1374 | fCachedLocalClipBounds.setEmpty(); |
michael@0 | 1375 | } |
michael@0 | 1376 | fCachedLocalClipBoundsDirty = false; |
michael@0 | 1377 | } |
michael@0 | 1378 | return fCachedLocalClipBounds; |
michael@0 | 1379 | } |
michael@0 | 1380 | |
michael@0 | 1381 | class AutoValidateClip : ::SkNoncopyable { |
michael@0 | 1382 | public: |
michael@0 | 1383 | explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) { |
michael@0 | 1384 | fCanvas->validateClip(); |
michael@0 | 1385 | } |
michael@0 | 1386 | ~AutoValidateClip() { fCanvas->validateClip(); } |
michael@0 | 1387 | |
michael@0 | 1388 | private: |
michael@0 | 1389 | const SkCanvas* fCanvas; |
michael@0 | 1390 | }; |
michael@0 | 1391 | |
michael@0 | 1392 | #ifdef SK_DEBUG |
michael@0 | 1393 | void validateClip() const; |
michael@0 | 1394 | #else |
michael@0 | 1395 | void validateClip() const {} |
michael@0 | 1396 | #endif |
michael@0 | 1397 | |
michael@0 | 1398 | typedef SkRefCnt INHERITED; |
michael@0 | 1399 | }; |
michael@0 | 1400 | |
michael@0 | 1401 | /** Stack helper class to automatically call restoreToCount() on the canvas |
michael@0 | 1402 | when this object goes out of scope. Use this to guarantee that the canvas |
michael@0 | 1403 | is restored to a known state. |
michael@0 | 1404 | */ |
michael@0 | 1405 | class SkAutoCanvasRestore : SkNoncopyable { |
michael@0 | 1406 | public: |
michael@0 | 1407 | SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) { |
michael@0 | 1408 | if (fCanvas) { |
michael@0 | 1409 | fSaveCount = canvas->getSaveCount(); |
michael@0 | 1410 | if (doSave) { |
michael@0 | 1411 | canvas->save(); |
michael@0 | 1412 | } |
michael@0 | 1413 | } |
michael@0 | 1414 | } |
michael@0 | 1415 | ~SkAutoCanvasRestore() { |
michael@0 | 1416 | if (fCanvas) { |
michael@0 | 1417 | fCanvas->restoreToCount(fSaveCount); |
michael@0 | 1418 | } |
michael@0 | 1419 | } |
michael@0 | 1420 | |
michael@0 | 1421 | /** |
michael@0 | 1422 | * Perform the restore now, instead of waiting for the destructor. Will |
michael@0 | 1423 | * only do this once. |
michael@0 | 1424 | */ |
michael@0 | 1425 | void restore() { |
michael@0 | 1426 | if (fCanvas) { |
michael@0 | 1427 | fCanvas->restoreToCount(fSaveCount); |
michael@0 | 1428 | fCanvas = NULL; |
michael@0 | 1429 | } |
michael@0 | 1430 | } |
michael@0 | 1431 | |
michael@0 | 1432 | private: |
michael@0 | 1433 | SkCanvas* fCanvas; |
michael@0 | 1434 | int fSaveCount; |
michael@0 | 1435 | }; |
michael@0 | 1436 | #define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore) |
michael@0 | 1437 | |
michael@0 | 1438 | /** Stack helper class to automatically open and close a comment block |
michael@0 | 1439 | */ |
michael@0 | 1440 | class SkAutoCommentBlock : SkNoncopyable { |
michael@0 | 1441 | public: |
michael@0 | 1442 | SkAutoCommentBlock(SkCanvas* canvas, const char* description) { |
michael@0 | 1443 | fCanvas = canvas; |
michael@0 | 1444 | if (NULL != fCanvas) { |
michael@0 | 1445 | fCanvas->beginCommentGroup(description); |
michael@0 | 1446 | } |
michael@0 | 1447 | } |
michael@0 | 1448 | |
michael@0 | 1449 | ~SkAutoCommentBlock() { |
michael@0 | 1450 | if (NULL != fCanvas) { |
michael@0 | 1451 | fCanvas->endCommentGroup(); |
michael@0 | 1452 | } |
michael@0 | 1453 | } |
michael@0 | 1454 | |
michael@0 | 1455 | private: |
michael@0 | 1456 | SkCanvas* fCanvas; |
michael@0 | 1457 | }; |
michael@0 | 1458 | #define SkAutoCommentBlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoCommentBlock) |
michael@0 | 1459 | |
michael@0 | 1460 | /** |
michael@0 | 1461 | * If the caller wants read-only access to the pixels in a canvas, it can just |
michael@0 | 1462 | * call canvas->peekPixels(), since that is the fastest way to "peek" at the |
michael@0 | 1463 | * pixels on a raster-backed canvas. |
michael@0 | 1464 | * |
michael@0 | 1465 | * If the canvas has pixels, but they are not readily available to the CPU |
michael@0 | 1466 | * (e.g. gpu-backed), then peekPixels() will fail, but readPixels() will |
michael@0 | 1467 | * succeed (though be slower, since it will return a copy of the pixels). |
michael@0 | 1468 | * |
michael@0 | 1469 | * SkAutoROCanvasPixels encapsulates these two techniques, trying first to call |
michael@0 | 1470 | * peekPixels() (for performance), but if that fails, calling readPixels() and |
michael@0 | 1471 | * storing the copy locally. |
michael@0 | 1472 | * |
michael@0 | 1473 | * The caller must respect the restrictions associated with peekPixels(), since |
michael@0 | 1474 | * that may have been called: The returned information is invalidated if... |
michael@0 | 1475 | * - any API is called on the canvas (or its parent surface if present) |
michael@0 | 1476 | * - the canvas goes out of scope |
michael@0 | 1477 | */ |
michael@0 | 1478 | class SkAutoROCanvasPixels : SkNoncopyable { |
michael@0 | 1479 | public: |
michael@0 | 1480 | SkAutoROCanvasPixels(SkCanvas* canvas); |
michael@0 | 1481 | |
michael@0 | 1482 | // returns NULL on failure |
michael@0 | 1483 | const void* addr() const { return fAddr; } |
michael@0 | 1484 | |
michael@0 | 1485 | // undefined if addr() == NULL |
michael@0 | 1486 | size_t rowBytes() const { return fRowBytes; } |
michael@0 | 1487 | |
michael@0 | 1488 | // undefined if addr() == NULL |
michael@0 | 1489 | const SkImageInfo& info() const { return fInfo; } |
michael@0 | 1490 | |
michael@0 | 1491 | // helper that, if returns true, installs the pixels into the bitmap. Note |
michael@0 | 1492 | // that the bitmap may reference the address returned by peekPixels(), so |
michael@0 | 1493 | // the caller must respect the restrictions associated with peekPixels(). |
michael@0 | 1494 | bool asROBitmap(SkBitmap*) const; |
michael@0 | 1495 | |
michael@0 | 1496 | private: |
michael@0 | 1497 | SkBitmap fBitmap; // used if peekPixels() fails |
michael@0 | 1498 | const void* fAddr; // NULL on failure |
michael@0 | 1499 | SkImageInfo fInfo; |
michael@0 | 1500 | size_t fRowBytes; |
michael@0 | 1501 | }; |
michael@0 | 1502 | |
michael@0 | 1503 | #endif |