1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef UI_GFX_CANVAS_H_
6 #define UI_GFX_CANVAS_H_
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string16.h"
13 #include "skia/ext/platform_canvas.h"
14 #include "skia/ext/refptr.h"
15 #include "ui/gfx/image/image_skia.h"
16 #include "ui/gfx/native_widget_types.h"
17 #include "ui/gfx/shadow_value.h"
27 // Canvas is a SkCanvas wrapper that provides a number of methods for
28 // common operations used throughout an application built using ui/gfx.
30 // All methods that take integer arguments (as is used throughout views)
31 // end with Int. If you need to use methods provided by SkCanvas, you'll
32 // need to do a conversion. In particular you'll need to use |SkIntToScalar()|,
33 // or if converting from a scalar to an integer |SkScalarRound()|.
35 // A handful of methods in this class are overloaded providing an additional
36 // argument of type SkXfermode::Mode. SkXfermode::Mode specifies how the
37 // source and destination colors are combined. Unless otherwise specified,
38 // the variant that does not take a SkXfermode::Mode uses a transfer mode
40 class GFX_EXPORT Canvas
{
42 enum TruncateFadeMode
{
47 // Specifies the alignment for text rendered with the DrawStringRect method.
49 TEXT_ALIGN_LEFT
= 1 << 0,
50 TEXT_ALIGN_CENTER
= 1 << 1,
51 TEXT_ALIGN_RIGHT
= 1 << 2,
53 // Specifies the text consists of multiple lines.
56 // By default DrawStringRect does not process the prefix ('&') character
57 // specially. That is, the string "&foo" is rendered as "&foo". When
58 // rendering text from a resource that uses the prefix character for
59 // mnemonics, the prefix should be processed and can be rendered as an
60 // underline (SHOW_PREFIX), or not rendered at all (HIDE_PREFIX).
64 // Prevent ellipsizing
67 // Specifies if words can be split by new lines.
68 // This only works with MULTI_LINE.
69 CHARACTER_BREAK
= 1 << 7,
71 // Instructs DrawStringRect() to render the text using RTL directionality.
72 // In most cases, passing this flag is not necessary because information
73 // about the text directionality is going to be embedded within the string
74 // in the form of special Unicode characters. However, we don't insert
75 // directionality characters into strings if the locale is LTR because some
76 // platforms (for example, an English Windows XP with no RTL fonts
77 // installed) don't support these characters. Thus, this flag should be
78 // used to render text using RTL directionality when the locale is LTR.
79 FORCE_RTL_DIRECTIONALITY
= 1 << 8,
81 // Similar to FORCE_RTL_DIRECTIONALITY, but left-to-right.
82 // See FORCE_RTL_DIRECTIONALITY for details.
83 FORCE_LTR_DIRECTIONALITY
= 1 << 9,
85 // Instructs DrawStringRect() to not use subpixel rendering. This is useful
86 // when rendering text onto a fully- or partially-transparent background
87 // that will later be blended with another image.
88 NO_SUBPIXEL_RENDERING
= 1 << 10,
91 // Creates an empty canvas with image_scale of 1x.
94 // Creates canvas with provided DIP |size| and |image_scale|.
95 // If this canvas is not opaque, it's explicitly cleared to transparent before
97 Canvas(const Size
& size
, float image_scale
, bool is_opaque
);
99 // Constructs a canvas with the size and the image_scale of the provided
100 // |image_rep|, and draws the |image_rep| into it.
101 Canvas(const ImageSkiaRep
& image_rep
, bool is_opaque
);
105 // Creates a Canvas backed by an |sk_canvas| with |image_scale_|.
106 // |sk_canvas| is assumed to be already scaled based on |image_scale|
107 // so no additional scaling is applied.
108 static Canvas
* CreateCanvasWithoutScaling(SkCanvas
* sk_canvas
,
111 // Recreates the backing platform canvas with DIP |size| and |image_scale_|.
112 // If the canvas is not opaque, it is explicitly cleared.
113 // This method is public so that canvas_skia_paint can recreate the platform
114 // canvas after having initialized the canvas.
115 // TODO(pkotwicz): Push the image_scale into skia::PlatformCanvas such that
116 // this method can be private.
117 void RecreateBackingCanvas(const Size
& size
,
121 // Compute the size required to draw some text with the provided fonts.
122 // Attempts to fit the text with the provided width and height. Increases
123 // height and then width as needed to make the text fit. This method
124 // supports multiple lines. On Skia only a line_height can be specified and
125 // specifying a 0 value for it will cause the default height to be used.
126 static void SizeStringInt(const base::string16
& text
,
127 const FontList
& font_list
,
133 // This is same as SizeStringInt except that fractional size is returned.
134 // See comment in GetStringWidthF for its usage.
135 static void SizeStringFloat(const base::string16
& text
,
136 const FontList
& font_list
,
142 // Returns the number of horizontal pixels needed to display the specified
143 // |text| with |font_list|.
144 static int GetStringWidth(const base::string16
& text
,
145 const FontList
& font_list
);
147 // This is same as GetStringWidth except that fractional width is returned.
148 // Use this method for the scenario that multiple string widths need to be
149 // summed up. This is because GetStringWidth returns the ceiled width and
150 // adding multiple ceiled widths could cause more precision loss for certain
151 // platform like Mac where the fractioal width is used.
152 static float GetStringWidthF(const base::string16
& text
,
153 const FontList
& font_list
);
155 // Returns the default text alignment to be used when drawing text on a
156 // Canvas based on the directionality of the system locale language.
157 // This function is used by Canvas::DrawStringRect when the text alignment
160 // This function returns either Canvas::TEXT_ALIGN_LEFT or
161 // Canvas::TEXT_ALIGN_RIGHT.
162 static int DefaultCanvasTextAlignment();
164 // Draws text with a 1-pixel halo around it of the given color.
165 // On Windows, it allows ClearType to be drawn to an otherwise transparent
166 // bitmap for drag images. Drag images have only 1-bit of transparency, so
167 // we don't do any fancy blurring.
168 // On Linux, text with halo is created by stroking it with 2px |halo_color|
169 // then filling it with |text_color|.
170 // On Mac, NOTIMPLEMENTED.
171 // TODO(dhollowa): Skia-native implementation is underway. Cut over to
172 // that when ready. http::/crbug.com/109946
173 void DrawStringRectWithHalo(const base::string16
& text
,
174 const FontList
& font_list
,
177 const Rect
& display_rect
,
180 // Extracts an ImageSkiaRep from the contents of this canvas.
181 ImageSkiaRep
ExtractImageRep() const;
183 // Draws a dashed rectangle of the specified color.
184 void DrawDashedRect(const Rect
& rect
, SkColor color
);
186 // Saves a copy of the drawing state onto a stack, operating on this copy
187 // until a balanced call to Restore() is made.
190 // As with Save(), except draws to a layer that is blended with the canvas
191 // at the specified alpha once Restore() is called.
192 // |layer_bounds| are the bounds of the layer relative to the current
194 void SaveLayerAlpha(uint8 alpha
);
195 void SaveLayerAlpha(uint8 alpha
, const Rect
& layer_bounds
);
197 // Restores the drawing state after a call to Save*(). It is an error to
198 // call Restore() more times than Save*().
201 // Adds |rect| to the current clip.
202 void ClipRect(const Rect
& rect
);
204 // Adds |path| to the current clip.
205 void ClipPath(const SkPath
& path
);
207 // Returns true if the current clip is empty.
208 bool IsClipEmpty() const;
210 // Returns the bounds of the current clip (in local coordinates) in the
211 // |bounds| parameter, and returns true if it is non empty.
212 bool GetClipBounds(Rect
* bounds
);
214 void Translate(const Vector2d
& offset
);
216 void Scale(int x_scale
, int y_scale
);
218 // Fills the entire canvas' bitmap (restricted to current clip) with
219 // specified |color| using a transfer mode of SkXfermode::kSrcOver_Mode.
220 void DrawColor(SkColor color
);
222 // Fills the entire canvas' bitmap (restricted to current clip) with
223 // specified |color| and |mode|.
224 void DrawColor(SkColor color
, SkXfermode::Mode mode
);
226 // Fills |rect| with |color| using a transfer mode of
227 // SkXfermode::kSrcOver_Mode.
228 void FillRect(const Rect
& rect
, SkColor color
);
230 // Fills |rect| with the specified |color| and |mode|.
231 void FillRect(const Rect
& rect
, SkColor color
, SkXfermode::Mode mode
);
233 // Draws a single pixel rect in the specified region with the specified
234 // color, using a transfer mode of SkXfermode::kSrcOver_Mode.
236 // NOTE: if you need a single pixel line, use DrawLine.
237 void DrawRect(const Rect
& rect
, SkColor color
);
239 // Draws a single pixel rect in the specified region with the specified
240 // color and transfer mode.
242 // NOTE: if you need a single pixel line, use DrawLine.
243 void DrawRect(const Rect
& rect
, SkColor color
, SkXfermode::Mode mode
);
245 // Draws the given rectangle with the given |paint| parameters.
246 void DrawRect(const Rect
& rect
, const SkPaint
& paint
);
248 // Draw the given point with the given |paint| parameters.
249 void DrawPoint(const Point
& p
, const SkPaint
& paint
);
251 // Draws a single pixel line with the specified color.
252 void DrawLine(const Point
& p1
, const Point
& p2
, SkColor color
);
254 // Draws a line with the given |paint| parameters.
255 void DrawLine(const Point
& p1
, const Point
& p2
, const SkPaint
& paint
);
257 // Draws a circle with the given |paint| parameters.
258 void DrawCircle(const Point
& center_point
,
260 const SkPaint
& paint
);
262 // Draws the given rectangle with rounded corners of |radius| using the
263 // given |paint| parameters.
264 void DrawRoundRect(const Rect
& rect
, int radius
, const SkPaint
& paint
);
266 // Draws the given path using the given |paint| parameters.
267 void DrawPath(const SkPath
& path
, const SkPaint
& paint
);
269 // Draws an image with the origin at the specified location. The upper left
270 // corner of the bitmap is rendered at the specified location.
271 // Parameters are specified relative to current canvas scale not in pixels.
272 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1.
273 void DrawImageInt(const ImageSkia
&, int x
, int y
);
275 // Helper for DrawImageInt(..., paint) that constructs a temporary paint and
276 // calls paint.setAlpha(alpha).
277 void DrawImageInt(const ImageSkia
&, int x
, int y
, uint8 alpha
);
279 // Draws an image with the origin at the specified location, using the
280 // specified paint. The upper left corner of the bitmap is rendered at the
281 // specified location.
282 // Parameters are specified relative to current canvas scale not in pixels.
283 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
284 void DrawImageInt(const ImageSkia
& image
,
287 const SkPaint
& paint
);
289 // Draws a portion of an image in the specified location. The src parameters
290 // correspond to the region of the bitmap to draw in the region defined
291 // by the dest coordinates.
293 // If the width or height of the source differs from that of the destination,
294 // the image will be scaled. When scaling down, a mipmap will be generated.
295 // Set |filter| to use filtering for images, otherwise the nearest-neighbor
296 // algorithm is used for resampling.
298 // An optional custom SkPaint can be provided.
299 // Parameters are specified relative to current canvas scale not in pixels.
300 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
301 void DrawImageInt(const ImageSkia
& image
,
311 void DrawImageInt(const ImageSkia
& image
,
321 const SkPaint
& paint
);
323 // Same as the DrawImageInt functions above. Difference being this does not
324 // do any scaling, i.e. it assumes that the source/destination/image, etc are
325 // in pixels. It does translate the destination rectangle to ensure that the
326 // image is displayed at the correct pixel coordinates.
327 void DrawImageIntInPixel(const ImageSkia
& image
,
337 const SkPaint
& paint
);
339 // Draws an |image| with the top left corner at |x| and |y|, clipped to
341 // Parameters are specified relative to current canvas scale not in pixels.
342 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1.
343 void DrawImageInPath(const ImageSkia
& image
,
347 const SkPaint
& paint
);
349 // Draws text with the specified color, fonts and location. The text is
350 // aligned to the left, vertically centered, clipped to the region. If the
351 // text is too big, it is truncated and '...' is added to the end.
352 void DrawStringRect(const base::string16
& text
,
353 const FontList
& font_list
,
355 const Rect
& display_rect
);
357 // Draws text with the specified color, fonts and location. The last argument
358 // specifies flags for how the text should be rendered. It can be one of
359 // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT.
360 void DrawStringRectWithFlags(const base::string16
& text
,
361 const FontList
& font_list
,
363 const Rect
& display_rect
,
366 // Similar to above DrawStringRect method but with text shadows support.
367 // Currently it's only implemented for canvas skia. Specifying a 0 line_height
368 // will cause the default height to be used.
369 void DrawStringRectWithShadows(const base::string16
& text
,
370 const FontList
& font_list
,
372 const Rect
& text_bounds
,
375 const ShadowValues
& shadows
);
377 // Draws a dotted gray rectangle used for focus purposes.
378 void DrawFocusRect(const Rect
& rect
);
380 // Draws a |rect| in the specified region with the specified |color| with a
381 // with of one logical pixel which might be more device pixels.
382 void DrawSolidFocusRect(const Rect
& rect
, SkColor color
);
384 // Tiles the image in the specified region.
385 // Parameters are specified relative to current canvas scale not in pixels.
386 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
387 void TileImageInt(const ImageSkia
& image
,
392 void TileImageInt(const ImageSkia
& image
,
399 void TileImageInt(const ImageSkia
& image
,
409 // Returns a native drawing context for platform specific drawing routines to
410 // use. Must be balanced by a call to EndPlatformPaint().
411 NativeDrawingContext
BeginPlatformPaint();
413 // Signifies the end of platform drawing using the native drawing context
414 // returned by BeginPlatformPaint().
415 void EndPlatformPaint();
417 // Apply transformation on the canvas.
418 void Transform(const Transform
& transform
);
420 // Draws the given string with the beginning or the end using a fade gradient.
421 void DrawFadeTruncatingStringRect(
422 const base::string16
& text
,
423 TruncateFadeMode truncate_mode
,
424 const FontList
& font_list
,
426 const Rect
& display_rect
);
427 void DrawFadeTruncatingStringRectWithFlags(
428 const base::string16
& text
,
429 TruncateFadeMode truncate_mode
,
430 const FontList
& font_list
,
432 const Rect
& display_rect
,
435 skia::PlatformCanvas
* platform_canvas() const { return owned_canvas_
.get(); }
436 SkCanvas
* sk_canvas() const { return canvas_
; }
437 float image_scale() const { return image_scale_
; }
440 Canvas(SkCanvas
* canvas
, float image_scale
);
442 // Test whether the provided rectangle intersects the current clip rect.
443 bool IntersectsClipRectInt(int x
, int y
, int w
, int h
);
444 bool IntersectsClipRect(const Rect
& rect
);
446 // Returns the image rep which best matches the canvas |image_scale_|.
447 // Returns a null image rep if |image| contains no image reps.
448 // Builds mip map for returned image rep if necessary.
450 // An optional additional user defined scale can be provided.
451 const ImageSkiaRep
& GetImageRepToPaint(const ImageSkia
& image
) const;
452 const ImageSkiaRep
& GetImageRepToPaint(
453 const ImageSkia
& image
,
455 float user_defined_scale_factor_x
,
456 float user_defined_scale_factor_y
) const;
458 // Helper for the DrawImageInt functions declared above. The |pixel|
459 // parameter if true indicates that the bounds and the image are to
460 // be assumed to be in pixels, i.e. no scaling needs to be performed.
461 void DrawImageIntHelper(const ImageSkia
& image
,
471 const SkPaint
& paint
,
475 // The device scale factor at which drawing on this canvas occurs.
476 // An additional scale can be applied via Canvas::Scale(). However,
477 // Canvas::Scale() does not affect |image_scale_|.
480 skia::RefPtr
<skia::PlatformCanvas
> owned_canvas_
;
483 DISALLOW_COPY_AND_ASSIGN(Canvas
);
488 #endif // UI_GFX_CANVAS_H_