gfx/skia/trunk/include/core/SkCanvas.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

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

mercurial