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