• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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