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"
28 // Canvas is a SkCanvas wrapper that provides a number of methods for
29 // common operations used throughout an application built using ui/gfx.
31 // All methods that take integer arguments (as is used throughout views)
32 // end with Int. If you need to use methods provided by SkCanvas, you'll
33 // need to do a conversion. In particular you'll need to use |SkIntToScalar()|,
34 // or if converting from a scalar to an integer |SkScalarRound()|.
36 // A handful of methods in this class are overloaded providing an additional
37 // argument of type SkXfermode::Mode. SkXfermode::Mode specifies how the
38 // source and destination colors are combined. Unless otherwise specified,
39 // the variant that does not take a SkXfermode::Mode uses a transfer mode
41 class GFX_EXPORT Canvas {
43 enum TruncateFadeMode {
48 // Specifies the alignment for text rendered with the DrawStringInt method.
50 TEXT_ALIGN_LEFT = 1 << 0,
51 TEXT_ALIGN_CENTER = 1 << 1,
52 TEXT_ALIGN_RIGHT = 1 << 2,
54 // Specifies the text consists of multiple lines.
57 // By default DrawStringInt does not process the prefix ('&') character
58 // specially. That is, the string "&foo" is rendered as "&foo". When
59 // rendering text from a resource that uses the prefix character for
60 // mnemonics, the prefix should be processed and can be rendered as an
61 // underline (SHOW_PREFIX), or not rendered at all (HIDE_PREFIX).
65 // Prevent ellipsizing
68 // Specifies if words can be split by new lines.
69 // This only works with MULTI_LINE.
70 CHARACTER_BREAK = 1 << 7,
72 // Instructs DrawStringInt() to render the text using RTL directionality.
73 // In most cases, passing this flag is not necessary because information
74 // about the text directionality is going to be embedded within the string
75 // in the form of special Unicode characters. However, we don't insert
76 // directionality characters into strings if the locale is LTR because some
77 // platforms (for example, an English Windows XP with no RTL fonts
78 // installed) don't support these characters. Thus, this flag should be
79 // used to render text using RTL directionality when the locale is LTR.
80 FORCE_RTL_DIRECTIONALITY = 1 << 8,
82 // Similar to FORCE_RTL_DIRECTIONALITY, but left-to-right.
83 // See FORCE_RTL_DIRECTIONALITY for details.
84 FORCE_LTR_DIRECTIONALITY = 1 << 9,
86 // Instructs DrawStringInt() to not use subpixel rendering. This is useful
87 // when rendering text onto a fully- or partially-transparent background
88 // that will later be blended with another image.
89 NO_SUBPIXEL_RENDERING = 1 << 10,
92 // Creates an empty canvas with image_scale of 1x.
95 // Creates canvas with provided DIP |size| and |image_scale|.
96 // If this canvas is not opaque, it's explicitly cleared to transparent before
98 Canvas(const Size& size, float image_scale, bool is_opaque);
100 // Constructs a canvas with the size and the image_scale of the provided
101 // |image_rep|, and draws the |image_rep| into it.
102 Canvas(const ImageSkiaRep& image_rep, bool is_opaque);
106 // Creates a Canvas backed by an |sk_canvas| with |image_scale_|.
107 // |sk_canvas| is assumed to be already scaled based on |image_scale|
108 // so no additional scaling is applied.
109 static Canvas* CreateCanvasWithoutScaling(SkCanvas* sk_canvas,
112 // Recreates the backing platform canvas with DIP |size| and |image_scale_|.
113 // If the canvas is not opaque, it is explicitly cleared.
114 // This method is public so that canvas_skia_paint can recreate the platform
115 // canvas after having initialized the canvas.
116 // TODO(pkotwicz): Push the image_scale into skia::PlatformCanvas such that
117 // this method can be private.
118 void RecreateBackingCanvas(const Size& size,
122 // Compute the size required to draw some text with the provided fonts.
123 // Attempts to fit the text with the provided width and height. Increases
124 // height and then width as needed to make the text fit. This method
125 // supports multiple lines. On Skia only a line_height can be specified and
126 // specifying a 0 value for it will cause the default height to be used.
127 static void SizeStringInt(const base::string16& text,
128 const FontList& font_list,
133 // Obsolete version. Use the above version which takes FontList.
134 static void SizeStringInt(const base::string16& text,
141 // This is same as SizeStringInt except that fractional size is returned.
142 // See comment in GetStringWidthF for its usage.
143 static void SizeStringFloat(const base::string16& text,
144 const FontList& font_list,
150 // Returns the number of horizontal pixels needed to display the specified
151 // |text| with |font_list|.
152 static int GetStringWidth(const base::string16& text,
153 const FontList& font_list);
154 // Obsolete version. Use the above version which takes FontList.
155 static int GetStringWidth(const base::string16& text, const Font& font);
157 // This is same as GetStringWidth except that fractional width is returned.
158 // Use this method for the scenario that multiple string widths need to be
159 // summed up. This is because GetStringWidth returns the ceiled width and
160 // adding multiple ceiled widths could cause more precision loss for certain
161 // platform like Mac where the fractioal width is used.
162 static float GetStringWidthF(const base::string16& text,
163 const FontList& font_list);
165 // Returns the default text alignment to be used when drawing text on a
166 // Canvas based on the directionality of the system locale language.
167 // This function is used by Canvas::DrawStringInt when the text alignment
170 // This function returns either Canvas::TEXT_ALIGN_LEFT or
171 // Canvas::TEXT_ALIGN_RIGHT.
172 static int DefaultCanvasTextAlignment();
174 // Draws text with a 1-pixel halo around it of the given color.
175 // On Windows, it allows ClearType to be drawn to an otherwise transparent
176 // bitmap for drag images. Drag images have only 1-bit of transparency, so
177 // we don't do any fancy blurring.
178 // On Linux, text with halo is created by stroking it with 2px |halo_color|
179 // then filling it with |text_color|.
180 // On Mac, NOTIMPLEMENTED.
181 // TODO(dhollowa): Skia-native implementation is underway. Cut over to
182 // that when ready. http::/crbug.com/109946
183 void DrawStringRectWithHalo(const base::string16& text,
184 const FontList& font_list,
187 const Rect& display_rect,
189 // Obsolete version. Use the above version which takes FontList.
190 void DrawStringWithHalo(const base::string16& text,
200 // Extracts an ImageSkiaRep from the contents of this canvas.
201 ImageSkiaRep ExtractImageRep() const;
203 // Draws a dashed rectangle of the specified color.
204 void DrawDashedRect(const Rect& rect, SkColor color);
206 // Saves a copy of the drawing state onto a stack, operating on this copy
207 // until a balanced call to Restore() is made.
210 // As with Save(), except draws to a layer that is blended with the canvas
211 // at the specified alpha once Restore() is called.
212 // |layer_bounds| are the bounds of the layer relative to the current
214 void SaveLayerAlpha(uint8 alpha);
215 void SaveLayerAlpha(uint8 alpha, const Rect& layer_bounds);
217 // Restores the drawing state after a call to Save*(). It is an error to
218 // call Restore() more times than Save*().
221 // Adds |rect| to the current clip. Returns true if the resulting clip is
223 bool ClipRect(const Rect& rect);
225 // Adds |path| to the current clip. Returns true if the resulting clip is
227 bool ClipPath(const SkPath& path);
229 // Returns the bounds of the current clip (in local coordinates) in the
230 // |bounds| parameter, and returns true if it is non empty.
231 bool GetClipBounds(Rect* bounds);
233 void Translate(const Vector2d& offset);
235 void Scale(int x_scale, int y_scale);
237 // Fills the entire canvas' bitmap (restricted to current clip) with
238 // specified |color| using a transfer mode of SkXfermode::kSrcOver_Mode.
239 void DrawColor(SkColor color);
241 // Fills the entire canvas' bitmap (restricted to current clip) with
242 // specified |color| and |mode|.
243 void DrawColor(SkColor color, SkXfermode::Mode mode);
245 // Fills |rect| with |color| using a transfer mode of
246 // SkXfermode::kSrcOver_Mode.
247 void FillRect(const Rect& rect, SkColor color);
249 // Fills |rect| with the specified |color| and |mode|.
250 void FillRect(const Rect& rect, SkColor color, SkXfermode::Mode mode);
252 // Draws a single pixel rect in the specified region with the specified
253 // color, using a transfer mode of SkXfermode::kSrcOver_Mode.
255 // NOTE: if you need a single pixel line, use DrawLine.
256 void DrawRect(const Rect& rect, SkColor color);
258 // Draws a single pixel rect in the specified region with the specified
259 // color and transfer mode.
261 // NOTE: if you need a single pixel line, use DrawLine.
262 void DrawRect(const Rect& rect, SkColor color, SkXfermode::Mode mode);
264 // Draws the given rectangle with the given |paint| parameters.
265 void DrawRect(const Rect& rect, const SkPaint& paint);
267 // Draw the given point with the given |paint| parameters.
268 void DrawPoint(const Point& p, const SkPaint& paint);
270 // Draws a single pixel line with the specified color.
271 void DrawLine(const Point& p1, const Point& p2, SkColor color);
273 // Draws a line with the given |paint| parameters.
274 void DrawLine(const Point& p1, const Point& p2, const SkPaint& paint);
276 // Draws a circle with the given |paint| parameters.
277 void DrawCircle(const Point& center_point,
279 const SkPaint& paint);
281 // Draws the given rectangle with rounded corners of |radius| using the
282 // given |paint| parameters.
283 void DrawRoundRect(const Rect& rect, int radius, const SkPaint& paint);
285 // Draws the given path using the given |paint| parameters.
286 void DrawPath(const SkPath& path, const SkPaint& paint);
288 // Draws an image with the origin at the specified location. The upper left
289 // corner of the bitmap is rendered at the specified location.
290 // Parameters are specified relative to current canvas scale not in pixels.
291 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1.
292 void DrawImageInt(const ImageSkia&, int x, int y);
294 // Helper for DrawImageInt(..., paint) that constructs a temporary paint and
295 // calls paint.setAlpha(alpha).
296 void DrawImageInt(const ImageSkia&, int x, int y, uint8 alpha);
298 // Draws an image with the origin at the specified location, using the
299 // specified paint. The upper left corner of the bitmap is rendered at the
300 // specified location.
301 // Parameters are specified relative to current canvas scale not in pixels.
302 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
303 void DrawImageInt(const ImageSkia& image,
306 const SkPaint& paint);
308 // Draws a portion of an image in the specified location. The src parameters
309 // correspond to the region of the bitmap to draw in the region defined
310 // by the dest coordinates.
312 // If the width or height of the source differs from that of the destination,
313 // the image will be scaled. When scaling down, a mipmap will be generated.
314 // Set |filter| to use filtering for images, otherwise the nearest-neighbor
315 // algorithm is used for resampling.
317 // An optional custom SkPaint can be provided.
318 // Parameters are specified relative to current canvas scale not in pixels.
319 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
320 void DrawImageInt(const ImageSkia& image,
330 void DrawImageInt(const ImageSkia& image,
340 const SkPaint& paint);
342 // Draws an |image| with the top left corner at |x| and |y|, clipped to
344 // Parameters are specified relative to current canvas scale not in pixels.
345 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1.
346 void DrawImageInPath(const ImageSkia& image,
350 const SkPaint& paint);
352 // Draws text with the specified color, fonts and location. The text is
353 // aligned to the left, vertically centered, clipped to the region. If the
354 // text is too big, it is truncated and '...' is added to the end.
355 void DrawStringRect(const base::string16& text,
356 const FontList& font_list,
358 const Rect& display_rect);
359 // Obsolete versions. Use the above versions which take FontList.
360 void DrawStringInt(const base::string16& text,
367 void DrawStringInt(const base::string16& text,
370 const Rect& display_rect);
372 // Draws text with the specified color, fonts and location. The last argument
373 // specifies flags for how the text should be rendered. It can be one of
374 // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT.
375 void DrawStringRectWithFlags(const base::string16& text,
376 const FontList& font_list,
378 const Rect& display_rect,
380 // Obsolete version. Use the above version which takes FontList.
381 void DrawStringInt(const base::string16& text,
390 // Similar to above DrawStringInt method but with text shadows support.
391 // Currently it's only implemented for canvas skia. Specifying a 0 line_height
392 // will cause the default height to be used.
393 void DrawStringRectWithShadows(const base::string16& text,
394 const FontList& font_list,
396 const Rect& text_bounds,
399 const ShadowValues& shadows);
400 // Obsolete version. Use the above version which takes FontList.
401 void DrawStringWithShadows(const base::string16& text,
404 const Rect& text_bounds,
407 const ShadowValues& shadows);
409 // Draws a dotted gray rectangle used for focus purposes.
410 void DrawFocusRect(const Rect& rect);
412 // Tiles the image in the specified region.
413 // Parameters are specified relative to current canvas scale not in pixels.
414 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
415 void TileImageInt(const ImageSkia& image,
420 void TileImageInt(const ImageSkia& image,
427 void TileImageInt(const ImageSkia& image,
437 // Returns a native drawing context for platform specific drawing routines to
438 // use. Must be balanced by a call to EndPlatformPaint().
439 NativeDrawingContext BeginPlatformPaint();
441 // Signifies the end of platform drawing using the native drawing context
442 // returned by BeginPlatformPaint().
443 void EndPlatformPaint();
445 // Apply transformation on the canvas.
446 void Transform(const Transform& transform);
448 // Draws the given string with the beginning or the end using a fade gradient.
449 void DrawFadeTruncatingStringRect(
450 const base::string16& text,
451 TruncateFadeMode truncate_mode,
452 const FontList& font_list,
454 const Rect& display_rect);
455 void DrawFadeTruncatingStringRectWithFlags(
456 const base::string16& text,
457 TruncateFadeMode truncate_mode,
458 const FontList& font_list,
460 const Rect& display_rect,
463 skia::PlatformCanvas* platform_canvas() const { return owned_canvas_.get(); }
464 SkCanvas* sk_canvas() const { return canvas_; }
465 float image_scale() const { return image_scale_; }
468 Canvas(SkCanvas* canvas, float image_scale);
470 // Test whether the provided rectangle intersects the current clip rect.
471 bool IntersectsClipRectInt(int x, int y, int w, int h);
472 bool IntersectsClipRect(const Rect& rect);
474 // Returns the image rep which best matches the canvas |image_scale_|.
475 // Returns a null image rep if |image| contains no image reps.
476 // Builds mip map for returned image rep if necessary.
478 // An optional additional user defined scale can be provided.
479 const ImageSkiaRep& GetImageRepToPaint(const ImageSkia& image) const;
480 const ImageSkiaRep& GetImageRepToPaint(
481 const ImageSkia& image,
482 float user_defined_scale_factor_x,
483 float user_defined_scale_factor_y) const;
485 // The device scale factor at which drawing on this canvas occurs.
486 // An additional scale can be applied via Canvas::Scale(). However,
487 // Canvas::Scale() does not affect |image_scale_|.
490 skia::RefPtr<skia::PlatformCanvas> owned_canvas_;
493 DISALLOW_COPY_AND_ASSIGN(Canvas);
498 #endif // UI_GFX_CANVAS_H_