1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkCanvas_DEFINED 18 #define SkCanvas_DEFINED 19 20 #include "SkTypes.h" 21 #include "SkBitmap.h" 22 #include "SkDeque.h" 23 #include "SkPaint.h" 24 #include "SkRefCnt.h" 25 #include "SkPorterDuff.h" 26 #include "SkPath.h" 27 #include "SkRegion.h" 28 #include "SkScalarCompare.h" 29 30 class SkBounder; 31 class SkDevice; 32 class SkDraw; 33 class SkDrawFilter; 34 class SkPicture; 35 36 /** \class SkCanvas 37 38 A Canvas encapsulates all of the state about drawing into a device (bitmap). 39 This includes a reference to the device itself, and a stack of matrix/clip 40 values. For any given draw call (e.g. drawRect), the geometry of the object 41 being drawn is transformed by the concatenation of all the matrices in the 42 stack. The transformed geometry is clipped by the intersection of all of 43 the clips in the stack. 44 45 While the Canvas holds the state of the drawing device, the state (style) 46 of the object being drawn is held by the Paint, which is provided as a 47 parameter to each of the draw() methods. The Paint holds attributes such as 48 color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns), 49 etc. 50 */ 51 class SkCanvas : public SkRefCnt { 52 public: 53 /** Construct a canvas with the specified bitmap to draw into. 54 @param bitmap Specifies a bitmap for the canvas to draw into. Its 55 structure are copied to the canvas. 56 */ 57 explicit SkCanvas(const SkBitmap& bitmap); 58 /** Construct a canvas with the specified device to draw into. 59 @param device Specifies a device for the canvas to draw into. The 60 device may be null. 61 */ 62 explicit SkCanvas(SkDevice* device = NULL); 63 virtual ~SkCanvas(); 64 65 /////////////////////////////////////////////////////////////////////////// 66 67 /** If this subclass of SkCanvas supports GL viewports, return true and set 68 size (if not null) to the size of the viewport. If it is not supported, 69 ignore vp and return false. 70 */ 71 virtual bool getViewport(SkIPoint* size) const; 72 73 /** If this subclass of SkCanvas supports GL viewports, return true and set 74 the viewport to the specified x and y dimensions. If it is not 75 supported, ignore x and y and return false. 76 */ 77 virtual bool setViewport(int x, int y); 78 79 /** Return the canvas' device object, which may be null. The device holds 80 the bitmap of the pixels that the canvas draws into. The reference count 81 of the returned device is not changed by this call. 82 */ 83 SkDevice* getDevice() const; 84 85 /** Specify a device for this canvas to draw into. If it is not null, its 86 reference count is incremented. If the canvas was already holding a 87 device, its reference count is decremented. The new device is returned. 88 */ 89 SkDevice* setDevice(SkDevice* device); 90 91 /** Specify a bitmap for the canvas to draw into. This is a help method for 92 setDevice(), and it creates a device for the bitmap by calling 93 createDevice(). The structure of the bitmap is copied into the device. 94 */ 95 virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap); 96 97 /////////////////////////////////////////////////////////////////////////// 98 99 enum SaveFlags { 100 /** save the matrix state, restoring it on restore() */ 101 kMatrix_SaveFlag = 0x01, 102 /** save the clip state, restoring it on restore() */ 103 kClip_SaveFlag = 0x02, 104 /** the layer needs to support per-pixel alpha */ 105 kHasAlphaLayer_SaveFlag = 0x04, 106 /** the layer needs to support 8-bits per color component */ 107 kFullColorLayer_SaveFlag = 0x08, 108 /** the layer should clip against the bounds argument */ 109 kClipToLayer_SaveFlag = 0x10, 110 111 // helper masks for common choices 112 kMatrixClip_SaveFlag = 0x03, 113 kARGB_NoClipLayer_SaveFlag = 0x0F, 114 kARGB_ClipLayer_SaveFlag = 0x1F 115 }; 116 117 /** This call saves the current matrix and clip information, and pushes a 118 copy onto a private stack. Subsequent calls to translate, scale, 119 rotate, skew, concat or clipRect, clipPath all operate on this copy. 120 When the balancing call to restore() is made, this copy is deleted and 121 the previous matrix/clip state is restored. 122 @return The value to pass to restoreToCount() to balance this save() 123 */ 124 virtual int save(SaveFlags flags = kMatrixClip_SaveFlag); 125 126 /** This behaves the same as save(), but in addition it allocates an 127 offscreen bitmap. All drawing calls are directed there, and only when 128 the balancing call to restore() is made is that offscreen transfered to 129 the canvas (or the previous layer). Subsequent calls to translate, 130 scale, rotate, skew, concat or clipRect, clipPath all operate on this 131 copy. When the balancing call to restore() is made, this copy is deleted 132 and the previous matrix/clip state is restored. 133 @param bounds (may be null) the maximum size the offscreen bitmap needs 134 to be (in local coordinates) 135 @param paint (may be null) This is copied, and is applied to the 136 offscreen when restore() is called 137 @param flags LayerFlags 138 @return The value to pass to restoreToCount() to balance this save() 139 */ 140 virtual int saveLayer(const SkRect* bounds, const SkPaint* paint, 141 SaveFlags flags = kARGB_ClipLayer_SaveFlag); 142 143 /** This behaves the same as save(), but in addition it allocates an 144 offscreen bitmap. All drawing calls are directed there, and only when 145 the balancing call to restore() is made is that offscreen transfered to 146 the canvas (or the previous layer). Subsequent calls to translate, 147 scale, rotate, skew, concat or clipRect, clipPath all operate on this 148 copy. When the balancing call to restore() is made, this copy is deleted 149 and the previous matrix/clip state is restored. 150 @param bounds (may be null) the maximum size the offscreen bitmap needs 151 to be (in local coordinates) 152 @param alpha This is applied to the offscreen when restore() is called. 153 @param flags LayerFlags 154 @return The value to pass to restoreToCount() to balance this save() 155 */ 156 int saveLayerAlpha(const SkRect* bounds, U8CPU alpha, 157 SaveFlags flags = kARGB_ClipLayer_SaveFlag); 158 159 /** This call balances a previous call to save(), and is used to remove all 160 modifications to the matrix/clip state since the last save call. It is 161 an error to call restore() more times than save() was called. 162 */ 163 virtual void restore(); 164 165 /** Returns the number of matrix/clip states on the SkCanvas' private stack. 166 This will equal # save() calls - # restore() calls. 167 */ 168 int getSaveCount() const; 169 170 /** Efficient way to pop any calls to save() that happened after the save 171 count reached saveCount. It is an error for saveCount to be less than 172 getSaveCount() 173 @param saveCount The number of save() levels to restore from 174 */ 175 void restoreToCount(int saveCount); 176 177 /** Preconcat the current matrix with the specified translation 178 @param dx The distance to translate in X 179 @param dy The distance to translate in Y 180 returns true if the operation succeeded (e.g. did not overflow) 181 */ 182 virtual bool translate(SkScalar dx, SkScalar dy); 183 184 /** Preconcat the current matrix with the specified scale. 185 @param sx The amount to scale in X 186 @param sy The amount to scale in Y 187 returns true if the operation succeeded (e.g. did not overflow) 188 */ 189 virtual bool scale(SkScalar sx, SkScalar sy); 190 191 /** Preconcat the current matrix with the specified rotation. 192 @param degrees The amount to rotate, in degrees 193 returns true if the operation succeeded (e.g. did not overflow) 194 */ 195 virtual bool rotate(SkScalar degrees); 196 197 /** Preconcat the current matrix with the specified skew. 198 @param sx The amount to skew in X 199 @param sy The amount to skew in Y 200 returns true if the operation succeeded (e.g. did not overflow) 201 */ 202 virtual bool skew(SkScalar sx, SkScalar sy); 203 204 /** Preconcat the current matrix with the specified matrix. 205 @param matrix The matrix to preconcatenate with the current matrix 206 @return true if the operation succeeded (e.g. did not overflow) 207 */ 208 virtual bool concat(const SkMatrix& matrix); 209 210 /** Replace the current matrix with a copy of the specified matrix. 211 @param matrix The matrix that will be copied into the current matrix. 212 */ 213 virtual void setMatrix(const SkMatrix& matrix); 214 215 /** Helper for setMatrix(identity). Sets the current matrix to identity. 216 */ 217 void resetMatrix(); 218 219 /** Modify the current clip with the specified rectangle. 220 @param rect The rect to intersect with the current clip 221 @param op The region op to apply to the current clip 222 @return true if the canvas' clip is non-empty 223 */ 224 virtual bool clipRect(const SkRect& rect, 225 SkRegion::Op op = SkRegion::kIntersect_Op); 226 227 /** Modify the current clip with the specified path. 228 @param path The path to apply to the current clip 229 @param op The region op to apply to the current clip 230 @return true if the canvas' new clip is non-empty 231 */ 232 virtual bool clipPath(const SkPath& path, 233 SkRegion::Op op = SkRegion::kIntersect_Op); 234 235 /** Modify the current clip with the specified region. Note that unlike 236 clipRect() and clipPath() which transform their arguments by the current 237 matrix, clipRegion() assumes its argument is already in device 238 coordinates, and so no transformation is performed. 239 @param deviceRgn The region to apply to the current clip 240 @param op The region op to apply to the current clip 241 @return true if the canvas' new clip is non-empty 242 */ 243 virtual bool clipRegion(const SkRegion& deviceRgn, 244 SkRegion::Op op = SkRegion::kIntersect_Op); 245 246 /** Helper for clipRegion(rgn, kReplace_Op). Sets the current clip to the 247 specified region. This does not intersect or in any other way account 248 for the existing clip region. 249 @param deviceRgn The region to copy into the current clip. 250 @return true if the new clip region is non-empty 251 */ setClipRegion(const SkRegion & deviceRgn)252 bool setClipRegion(const SkRegion& deviceRgn) { 253 return this->clipRegion(deviceRgn, SkRegion::kReplace_Op); 254 } 255 256 /** Enum describing how to treat edges when performing quick-reject tests 257 of a geometry against the current clip. Treating them as antialiased 258 (kAA_EdgeType) will take into account the extra pixels that may be drawn 259 if the edge does not lie exactly on a device pixel boundary (after being 260 transformed by the current matrix). 261 */ 262 enum EdgeType { 263 /** Treat the edges as B&W (not antialiased) for the purposes of testing 264 against the current clip 265 */ 266 kBW_EdgeType, 267 /** Treat the edges as antialiased for the purposes of testing 268 against the current clip 269 */ 270 kAA_EdgeType 271 }; 272 273 /** Return true if the specified rectangle, after being transformed by the 274 current matrix, would lie completely outside of the current clip. Call 275 this to check if an area you intend to draw into is clipped out (and 276 therefore you can skip making the draw calls). 277 @param rect the rect to compare with the current clip 278 @param et specifies how to treat the edges (see EdgeType) 279 @return true if the rect (transformed by the canvas' matrix) does not 280 intersect with the canvas' clip 281 */ 282 bool quickReject(const SkRect& rect, EdgeType et) const; 283 284 /** Return true if the specified path, after being transformed by the 285 current matrix, would lie completely outside of the current clip. Call 286 this to check if an area you intend to draw into is clipped out (and 287 therefore you can skip making the draw calls). Note, for speed it may 288 return false even if the path itself might not intersect the clip 289 (i.e. the bounds of the path intersects, but the path does not). 290 @param path The path to compare with the current clip 291 @param et specifies how to treat the edges (see EdgeType) 292 @return true if the path (transformed by the canvas' matrix) does not 293 intersect with the canvas' clip 294 */ 295 bool quickReject(const SkPath& path, EdgeType et) const; 296 297 /** Return true if the horizontal band specified by top and bottom is 298 completely clipped out. This is a conservative calculation, meaning 299 that it is possible that if the method returns false, the band may still 300 in fact be clipped out, but the converse is not true. If this method 301 returns true, then the band is guaranteed to be clipped out. 302 @param top The top of the horizontal band to compare with the clip 303 @param bottom The bottom of the horizontal and to compare with the clip 304 @return true if the horizontal band is completely clipped out (i.e. does 305 not intersect the current clip) 306 */ 307 bool quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const; 308 309 /** Return the bounds of the current clip (in local coordinates) in the 310 bounds parameter, and return true if it is non-empty. This can be useful 311 in a way similar to quickReject, in that it tells you that drawing 312 outside of these bounds will be clipped out. 313 */ 314 bool getClipBounds(SkRect* bounds, EdgeType et = kAA_EdgeType) const; 315 316 /** Fill the entire canvas' bitmap (restricted to the current clip) with the 317 specified ARGB color, using the specified PorterDuff mode. 318 @param a the alpha component (0..255) of the color to fill the canvas 319 @param r the red component (0..255) of the color to fill the canvas 320 @param g the green component (0..255) of the color to fill the canvas 321 @param b the blue component (0..255) of the color to fill the canvas 322 @param mode the mode to apply the color in (defaults to SrcOver) 323 */ 324 void drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, 325 SkPorterDuff::Mode mode = SkPorterDuff::kSrcOver_Mode); 326 327 /** Fill the entire canvas' bitmap (restricted to the current clip) with the 328 specified color and porter-duff xfermode. 329 @param color the color to draw with 330 @param mode the mode to apply the color in (defaults to SrcOver) 331 */ 332 void drawColor(SkColor color, 333 SkPorterDuff::Mode mode = SkPorterDuff::kSrcOver_Mode); 334 335 /** Fill the entire canvas' bitmap (restricted to the current clip) with the 336 specified paint. 337 @param paint The paint used to fill the canvas 338 */ 339 virtual void drawPaint(const SkPaint& paint); 340 341 enum PointMode { 342 /** drawPoints draws each point separately */ 343 kPoints_PointMode, 344 /** drawPoints draws each pair of points as a line segment */ 345 kLines_PointMode, 346 /** drawPoints draws the array of points as a polygon */ 347 kPolygon_PointMode 348 }; 349 350 /** Draw a series of points, interpreted based on the PointMode mode. For 351 all modes, the count parameter is interpreted as the total number of 352 points. For kLine mode, count/2 line segments are drawn. 353 For kPoint mode, each point is drawn centered at its coordinate, and its 354 size is specified by the paint's stroke-width. It draws as a square, 355 unless the paint's cap-type is round, in which the points are drawn as 356 circles. 357 For kLine mode, each pair of points is drawn as a line segment, 358 respecting the paint's settings for cap/join/width. 359 For kPolygon mode, the entire array is drawn as a series of connected 360 line segments. 361 Note that, while similar, kLine and kPolygon modes draw slightly 362 differently than the equivalent path built with a series of moveto, 363 lineto calls, in that the path will draw all of its contours at once, 364 with no interactions if contours intersect each other (think XOR 365 xfermode). drawPoints always draws each element one at a time. 366 @param mode PointMode specifying how to draw the array of points. 367 @param count The number of points in the array 368 @param pts Array of points to draw 369 @param paint The paint used to draw the points 370 */ 371 virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], 372 const SkPaint& paint); 373 374 /** Helper method for drawing a single point. See drawPoints() for a more 375 details. 376 */ 377 void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint); 378 379 /** Draws a single pixel in the specified color. 380 @param x The X coordinate of which pixel to draw 381 @param y The Y coordiante of which pixel to draw 382 @param color The color to draw 383 */ 384 void drawPoint(SkScalar x, SkScalar y, SkColor color); 385 386 /** Draw a line segment with the specified start and stop x,y coordinates, 387 using the specified paint. NOTE: since a line is always "framed", the 388 paint's Style is ignored. 389 @param x0 The x-coordinate of the start point of the line 390 @param y0 The y-coordinate of the start point of the line 391 @param x1 The x-coordinate of the end point of the line 392 @param y1 The y-coordinate of the end point of the line 393 @param paint The paint used to draw the line 394 */ 395 void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, 396 const SkPaint& paint); 397 398 /** Draw the specified rectangle using the specified paint. The rectangle 399 will be filled or stroked based on the Style in the paint. 400 @param rect The rect to be drawn 401 @param paint The paint used to draw the rect 402 */ 403 virtual void drawRect(const SkRect& rect, const SkPaint& paint); 404 405 /** Draw the specified rectangle using the specified paint. The rectangle 406 will be filled or framed based on the Style in the paint. 407 @param rect The rect to be drawn 408 @param paint The paint used to draw the rect 409 */ drawIRect(const SkIRect & rect,const SkPaint & paint)410 void drawIRect(const SkIRect& rect, const SkPaint& paint) 411 { 412 SkRect r; 413 r.set(rect); // promotes the ints to scalars 414 this->drawRect(r, paint); 415 } 416 417 /** Draw the specified rectangle using the specified paint. The rectangle 418 will be filled or framed based on the Style in the paint. 419 @param left The left side of the rectangle to be drawn 420 @param top The top side of the rectangle to be drawn 421 @param right The right side of the rectangle to be drawn 422 @param bottom The bottom side of the rectangle to be drawn 423 @param paint The paint used to draw the rect 424 */ 425 void drawRectCoords(SkScalar left, SkScalar top, SkScalar right, 426 SkScalar bottom, const SkPaint& paint); 427 428 /** Draw the specified oval using the specified paint. The oval will be 429 filled or framed based on the Style in the paint. 430 @param oval The rectangle bounds of the oval to be drawn 431 @param paint The paint used to draw the oval 432 */ 433 void drawOval(const SkRect& oval, const SkPaint&); 434 435 /** Draw the specified circle using the specified paint. If radius is <= 0, 436 then nothing will be drawn. The circle will be filled 437 or framed based on the Style in the paint. 438 @param cx The x-coordinate of the center of the cirle to be drawn 439 @param cy The y-coordinate of the center of the cirle to be drawn 440 @param radius The radius of the cirle to be drawn 441 @param paint The paint used to draw the circle 442 */ 443 void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, 444 const SkPaint& paint); 445 446 /** Draw the specified arc, which will be scaled to fit inside the 447 specified oval. If the sweep angle is >= 360, then the oval is drawn 448 completely. Note that this differs slightly from SkPath::arcTo, which 449 treats the sweep angle mod 360. 450 @param oval The bounds of oval used to define the shape of the arc 451 @param startAngle Starting angle (in degrees) where the arc begins 452 @param sweepAngle Sweep angle (in degrees) measured clockwise 453 @param useCenter true means include the center of the oval. For filling 454 this will draw a wedge. False means just use the arc. 455 @param paint The paint used to draw the arc 456 */ 457 void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 458 bool useCenter, const SkPaint& paint); 459 460 /** Draw the specified round-rect using the specified paint. The round-rect 461 will be filled or framed based on the Style in the paint. 462 @param rect The rectangular bounds of the roundRect to be drawn 463 @param rx The x-radius of the oval used to round the corners 464 @param ry The y-radius of the oval used to round the corners 465 @param paint The paint used to draw the roundRect 466 */ 467 void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 468 const SkPaint& paint); 469 470 /** Draw the specified path using the specified paint. The path will be 471 filled or framed based on the Style in the paint. 472 @param path The path to be drawn 473 @param paint The paint used to draw the path 474 */ 475 virtual void drawPath(const SkPath& path, const SkPaint& paint); 476 477 /** Draw the specified bitmap, with its top/left corner at (x,y), using the 478 specified paint, transformed by the current matrix. Note: if the paint 479 contains a maskfilter that generates a mask which extends beyond the 480 bitmap's original width/height, then the bitmap will be drawn as if it 481 were in a Shader with CLAMP mode. Thus the color outside of the original 482 width/height will be the edge color replicated. 483 @param bitmap The bitmap to be drawn 484 @param left The position of the left side of the bitmap being drawn 485 @param top The position of the top side of the bitmap being drawn 486 @param paint The paint used to draw the bitmap, or NULL 487 */ 488 virtual void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top, 489 const SkPaint* paint = NULL); 490 491 /** Draw the specified bitmap, with the specified matrix applied (before the 492 canvas' matrix is applied). 493 @param bitmap The bitmap to be drawn 494 @param src Optional: specify the subset of the bitmap to be drawn 495 @param dst The destination rectangle where the scaled/translated 496 image will be drawn 497 @param paint The paint used to draw the bitmap, or NULL 498 */ 499 virtual void drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src, 500 const SkRect& dst, const SkPaint* paint = NULL); 501 502 virtual void drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& m, 503 const SkPaint* paint = NULL); 504 505 /** Draw the specified bitmap, with its top/left corner at (x,y), 506 NOT transformed by the current matrix. Note: if the paint 507 contains a maskfilter that generates a mask which extends beyond the 508 bitmap's original width/height, then the bitmap will be drawn as if it 509 were in a Shader with CLAMP mode. Thus the color outside of the original 510 width/height will be the edge color replicated. 511 @param bitmap The bitmap to be drawn 512 @param left The position of the left side of the bitmap being drawn 513 @param top The position of the top side of the bitmap being drawn 514 @param paint The paint used to draw the bitmap, or NULL 515 */ 516 virtual void drawSprite(const SkBitmap& bitmap, int left, int top, 517 const SkPaint* paint = NULL); 518 519 /** Draw the text, with origin at (x,y), using the specified paint. 520 The origin is interpreted based on the Align setting in the paint. 521 @param text The text to be drawn 522 @param byteLength The number of bytes to read from the text parameter 523 @param x The x-coordinate of the origin of the text being drawn 524 @param y The y-coordinate of the origin of the text being drawn 525 @param paint The paint used for the text (e.g. color, size, style) 526 */ 527 virtual void drawText(const void* text, size_t byteLength, SkScalar x, 528 SkScalar y, const SkPaint& paint); 529 530 /** Draw the text, with each character/glyph origin specified by the pos[] 531 array. The origin is interpreted by the Align setting in the paint. 532 @param text The text to be drawn 533 @param byteLength The number of bytes to read from the text parameter 534 @param pos Array of positions, used to position each character 535 @param paint The paint used for the text (e.g. color, size, style) 536 */ 537 virtual void drawPosText(const void* text, size_t byteLength, 538 const SkPoint pos[], const SkPaint& paint); 539 540 /** Draw the text, with each character/glyph origin specified by the x 541 coordinate taken from the xpos[] array, and the y from the constY param. 542 The origin is interpreted by the Align setting in the paint. 543 @param text The text to be drawn 544 @param byteLength The number of bytes to read from the text parameter 545 @param xpos Array of x-positions, used to position each character 546 @param constY The shared Y coordinate for all of the positions 547 @param paint The paint used for the text (e.g. color, size, style) 548 */ 549 virtual void drawPosTextH(const void* text, size_t byteLength, 550 const SkScalar xpos[], SkScalar constY, 551 const SkPaint& paint); 552 553 /** Draw the text, with origin at (x,y), using the specified paint, along 554 the specified path. The paint's Align setting determins where along the 555 path to start the text. 556 @param text The text to be drawn 557 @param byteLength The number of bytes to read from the text parameter 558 @param path The path the text should follow for its baseline 559 @param hOffset The distance along the path to add to the text's 560 starting position 561 @param vOffset The distance above(-) or below(+) the path to 562 position the text 563 @param paint The paint used for the text 564 */ 565 void drawTextOnPathHV(const void* text, size_t byteLength, 566 const SkPath& path, SkScalar hOffset, 567 SkScalar vOffset, const SkPaint& paint); 568 569 /** Draw the text, with origin at (x,y), using the specified paint, along 570 the specified path. The paint's Align setting determins where along the 571 path to start the text. 572 @param text The text to be drawn 573 @param byteLength The number of bytes to read from the text parameter 574 @param path The path the text should follow for its baseline 575 @param matrix (may be null) Applied to the text before it is 576 mapped onto the path 577 @param paint The paint used for the text 578 */ 579 virtual void drawTextOnPath(const void* text, size_t byteLength, 580 const SkPath& path, const SkMatrix* matrix, 581 const SkPaint& paint); 582 583 /** Draw the picture into this canvas. This method effective brackets the 584 playback of the picture's draw calls with save/restore, so the state 585 of this canvas will be unchanged after this call. This contrasts with 586 the more immediate method SkPicture::draw(), which does not bracket 587 the canvas with save/restore, thus the canvas may be left in a changed 588 state after the call. 589 @param picture The recorded drawing commands to playback into this 590 canvas. 591 */ 592 virtual void drawPicture(SkPicture& picture); 593 594 enum VertexMode { 595 kTriangles_VertexMode, 596 kTriangleStrip_VertexMode, 597 kTriangleFan_VertexMode 598 }; 599 600 /** Draw the array of vertices, interpreted as triangles (based on mode). 601 @param vmode How to interpret the array of vertices 602 @param vertexCount The number of points in the vertices array (and 603 corresponding texs and colors arrays if non-null) 604 @param vertices Array of vertices for the mesh 605 @param texs May be null. If not null, specifies the coordinate 606 in texture space for each vertex. 607 @param colors May be null. If not null, specifies a color for each 608 vertex, to be interpolated across the triangle. 609 @param xmode Used if both texs and colors are present. In this 610 case the colors are combined with the texture using mode, 611 before being drawn using the paint. If mode is null, then 612 the porter-duff MULTIPLY mode is used. 613 @param indices If not null, array of indices to reference into the 614 vertex (texs, colors) array. 615 @param indexCount number of entries in the indices array (if not null) 616 @param paint Specifies the shader/texture if present. 617 */ 618 virtual void drawVertices(VertexMode vmode, int vertexCount, 619 const SkPoint vertices[], const SkPoint texs[], 620 const SkColor colors[], SkXfermode* xmode, 621 const uint16_t indices[], int indexCount, 622 const SkPaint& paint); 623 624 ////////////////////////////////////////////////////////////////////////// 625 626 /** Get the current bounder object. 627 The bounder's reference count is unchaged. 628 @return the canva's bounder (or NULL). 629 */ getBounder()630 SkBounder* getBounder() const { return fBounder; } 631 632 /** Set a new bounder (or NULL). 633 Pass NULL to clear any previous bounder. 634 As a convenience, the parameter passed is also returned. 635 If a previous bounder exists, its reference count is decremented. 636 If bounder is not NULL, its reference count is incremented. 637 @param bounder the new bounder (or NULL) to be installed in the canvas 638 @return the set bounder object 639 */ 640 virtual SkBounder* setBounder(SkBounder* bounder); 641 642 /** Get the current filter object. The filter's reference count is not 643 affected. The filter is part of the state this is affected by 644 save/restore. 645 @return the canvas' filter (or NULL). 646 */ 647 SkDrawFilter* getDrawFilter() const; 648 649 /** Set the new filter (or NULL). Pass NULL to clear any existing filter. 650 As a convenience, the parameter is returned. If an existing filter 651 exists, its refcnt is decrement. If the new filter is not null, its 652 refcnt is incremented. The filter is part of the state this is affected 653 by save/restore. 654 @param filter the new filter (or NULL) 655 @return the new filter 656 */ 657 virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter); 658 659 ////////////////////////////////////////////////////////////////////////// 660 661 /** Return the current matrix on the canvas. 662 This does not account for the translate in any of the devices. 663 @return The current matrix on the canvas. 664 */ 665 const SkMatrix& getTotalMatrix() const; 666 667 /** Return the current device clip (concatenation of all clip calls). 668 This does not account for the translate in any of the devices. 669 @return the current device clip (concatenation of all clip calls). 670 */ 671 const SkRegion& getTotalClip() const; 672 673 /** May be overridden by subclasses. This returns a compatible device 674 for this canvas, with the specified config/width/height. If isOpaque 675 is true, then the underlying bitmap is optimized to assume that every 676 pixel will be drawn to, and thus it does not need to clear the alpha 677 channel ahead of time (assuming the specified config supports per-pixel 678 alpha.) If isOpaque is false, then the bitmap should clear its alpha 679 channel. 680 */ 681 virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, 682 bool isOpaque, bool isForLayer); 683 684 /////////////////////////////////////////////////////////////////////////// 685 686 /** After calling saveLayer(), there can be any number of devices that make 687 up the top-most drawing area. LayerIter can be used to iterate through 688 those devices. Note that the iterator is only valid until the next API 689 call made on the canvas. Ownership of all pointers in the iterator stays 690 with the canvas, so none of them should be modified or deleted. 691 */ 692 class LayerIter /*: SkNoncopyable*/ { 693 public: 694 /** Initialize iterator with canvas, and set values for 1st device */ 695 LayerIter(SkCanvas*, bool skipEmptyClips); 696 ~LayerIter(); 697 698 /** Return true if the iterator is done */ done()699 bool done() const { return fDone; } 700 /** Cycle to the next device */ 701 void next(); 702 703 // These reflect the current device in the iterator 704 705 SkDevice* device() const; 706 const SkMatrix& matrix() const; 707 const SkRegion& clip() const; 708 const SkPaint& paint() const; 709 int x() const; 710 int y() const; 711 712 private: 713 // used to embed the SkDrawIter object directly in our instance, w/o 714 // having to expose that class def to the public. There is an assert 715 // in our constructor to ensure that fStorage is large enough 716 // (though needs to be a compile-time-assert!). We use intptr_t to work 717 // safely with 32 and 64 bit machines (to ensure the storage is enough) 718 intptr_t fStorage[12]; 719 class SkDrawIter* fImpl; // this points at fStorage 720 SkPaint fDefaultPaint; 721 bool fDone; 722 }; 723 724 protected: 725 // all of the drawBitmap variants call this guy 726 virtual void commonDrawBitmap(const SkBitmap&, const SkMatrix& m, 727 const SkPaint& paint); 728 729 private: 730 class MCRec; 731 732 SkDeque fMCStack; 733 // points to top of stack 734 MCRec* fMCRec; 735 // the first N recs that can fit here mean we won't call malloc 736 uint32_t fMCRecStorage[32]; 737 738 SkBounder* fBounder; 739 740 void prepareForDeviceDraw(SkDevice*); 741 742 bool fDeviceCMDirty; // cleared by updateDeviceCMCache() 743 void updateDeviceCMCache(); 744 745 friend class SkDrawIter; // needs setupDrawForLayerDevice() 746 747 SkDevice* init(SkDevice*); 748 void internalDrawBitmap(const SkBitmap&, const SkMatrix& m, 749 const SkPaint* paint); 750 void drawDevice(SkDevice*, int x, int y, const SkPaint*); 751 // shared by save() and saveLayer() 752 int internalSave(SaveFlags flags); 753 void internalRestore(); 754 755 /* These maintain a cache of the clip bounds in local coordinates, 756 (converted to 2s-compliment if floats are slow). 757 */ 758 mutable SkRectCompareType fLocalBoundsCompareType; 759 mutable bool fLocalBoundsCompareTypeDirty; 760 getLocalClipBoundsCompareType()761 const SkRectCompareType& getLocalClipBoundsCompareType() const { 762 if (fLocalBoundsCompareTypeDirty) { 763 this->computeLocalClipBoundsCompareType(); 764 fLocalBoundsCompareTypeDirty = false; 765 } 766 return fLocalBoundsCompareType; 767 } 768 void computeLocalClipBoundsCompareType() const; 769 }; 770 771 /** Stack helper class to automatically call restoreToCount() on the canvas 772 when this object goes out of scope. Use this to guarantee that the canvas 773 is restored to a known state. 774 */ 775 class SkAutoCanvasRestore : SkNoncopyable { 776 public: SkAutoCanvasRestore(SkCanvas * canvas,bool doSave)777 SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas) { 778 SkASSERT(canvas); 779 fSaveCount = canvas->getSaveCount(); 780 if (doSave) { 781 canvas->save(); 782 } 783 } ~SkAutoCanvasRestore()784 ~SkAutoCanvasRestore() { 785 fCanvas->restoreToCount(fSaveCount); 786 } 787 788 private: 789 SkCanvas* fCanvas; 790 int fSaveCount; 791 }; 792 793 #endif 794 795