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. 4 5 #ifndef UI_GFX_CANVAS_H_ 6 #define UI_GFX_CANVAS_H_ 7 8 #include <vector> 9 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" 18 19 namespace gfx { 20 21 class Rect; 22 class Font; 23 class Point; 24 class Size; 25 class Transform; 26 27 // Canvas is a SkCanvas wrapper that provides a number of methods for 28 // common operations used throughout an application built using ui/gfx. 29 // 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()|. 34 // 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 39 // of kSrcOver_Mode. 40 class UI_EXPORT Canvas { 41 public: 42 enum TruncateFadeMode { 43 TruncateFadeTail, 44 TruncateFadeHead, 45 TruncateFadeHeadAndTail, 46 }; 47 48 // Specifies the alignment for text rendered with the DrawStringInt method. 49 enum { 50 TEXT_ALIGN_LEFT = 1 << 0, 51 TEXT_ALIGN_CENTER = 1 << 1, 52 TEXT_ALIGN_RIGHT = 1 << 2, 53 54 // Specifies the text consists of multiple lines. 55 MULTI_LINE = 1 << 3, 56 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). 62 SHOW_PREFIX = 1 << 4, 63 HIDE_PREFIX = 1 << 5, 64 65 // Prevent ellipsizing 66 NO_ELLIPSIS = 1 << 6, 67 68 // Specifies if words can be split by new lines. 69 // This only works with MULTI_LINE. 70 CHARACTER_BREAK = 1 << 7, 71 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, 81 82 // Similar to FORCE_RTL_DIRECTIONALITY, but left-to-right. 83 // See FORCE_RTL_DIRECTIONALITY for details. 84 FORCE_LTR_DIRECTIONALITY = 1 << 9, 85 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, 90 }; 91 92 // Creates an empty canvas with scale factor of 1x. 93 Canvas(); 94 95 // Creates canvas with provided DIP |size| and |scale_factor|. 96 // If this canvas is not opaque, it's explicitly cleared to transparent before 97 // being returned. 98 Canvas(const gfx::Size& size, 99 ui::ScaleFactor scale_factor, 100 bool is_opaque); 101 102 // Constructs a canvas with the size and the scale factor of the 103 // provided |image_rep|, and draws the |image_rep| into it. 104 Canvas(const gfx::ImageSkiaRep& image_rep, bool is_opaque); 105 106 virtual ~Canvas(); 107 108 // Creates a gfx::Canvas backed by an |sk_canvas| with |scale_factor|. 109 // |sk_canvas| is assumed to be already scaled based on |scale_factor| 110 // so no additional scaling is applied. 111 static Canvas* CreateCanvasWithoutScaling(SkCanvas* sk_canvas, 112 ui::ScaleFactor scale_factor); 113 114 // Recreates the backing platform canvas with DIP |size| and |scale_factor|. 115 // If the canvas is not opaque, it is explicitly cleared. 116 // This method is public so that canvas_skia_paint can recreate the platform 117 // canvas after having initialized the canvas. 118 // TODO(pkotwicz): Push the scale factor into skia::PlatformCanvas such that 119 // this method can be private. 120 void RecreateBackingCanvas(const gfx::Size& size, 121 ui::ScaleFactor scale_factor, 122 bool is_opaque); 123 124 // Compute the size required to draw some text with the provided font. 125 // Attempts to fit the text with the provided width and height. Increases 126 // height and then width as needed to make the text fit. This method 127 // supports multiple lines. On Skia only a line_height can be specified and 128 // specifying a 0 value for it will cause the default height to be used. 129 static void SizeStringInt(const base::string16& text, 130 const gfx::Font& font, 131 int* width, int* height, 132 int line_height, 133 int flags); 134 135 // Returns the number of horizontal pixels needed to display the specified 136 // |text| with |font|. 137 static int GetStringWidth(const base::string16& text, const gfx::Font& font); 138 139 // Returns the default text alignment to be used when drawing text on a 140 // gfx::Canvas based on the directionality of the system locale language. 141 // This function is used by gfx::Canvas::DrawStringInt when the text alignment 142 // is not specified. 143 // 144 // This function returns either gfx::Canvas::TEXT_ALIGN_LEFT or 145 // gfx::Canvas::TEXT_ALIGN_RIGHT. 146 static int DefaultCanvasTextAlignment(); 147 148 // Draws text with a 1-pixel halo around it of the given color. 149 // On Windows, it allows ClearType to be drawn to an otherwise transparenct 150 // bitmap for drag images. Drag images have only 1-bit of transparency, so 151 // we don't do any fancy blurring. 152 // On Linux, text with halo is created by stroking it with 2px |halo_color| 153 // then filling it with |text_color|. 154 // On Mac, NOTIMPLEMENTED. 155 // TODO(dhollowa): Skia-native implementation is underway. Cut over to 156 // that when ready. http::/crbug.com/109946 157 void DrawStringWithHalo(const base::string16& text, 158 const gfx::Font& font, 159 SkColor text_color, 160 SkColor halo_color, 161 int x, int y, int w, int h, 162 int flags); 163 164 // Extracts an ImageSkiaRep from the contents of this canvas. 165 gfx::ImageSkiaRep ExtractImageRep() const; 166 167 // Draws a dashed rectangle of the specified color. 168 void DrawDashedRect(const gfx::Rect& rect, SkColor color); 169 170 // Saves a copy of the drawing state onto a stack, operating on this copy 171 // until a balanced call to Restore() is made. 172 void Save(); 173 174 // As with Save(), except draws to a layer that is blended with the canvas 175 // at the specified alpha once Restore() is called. 176 // |layer_bounds| are the bounds of the layer relative to the current 177 // transform. 178 void SaveLayerAlpha(uint8 alpha); 179 void SaveLayerAlpha(uint8 alpha, const gfx::Rect& layer_bounds); 180 181 // Restores the drawing state after a call to Save*(). It is an error to 182 // call Restore() more times than Save*(). 183 void Restore(); 184 185 // Adds |rect| to the current clip. Returns true if the resulting clip is 186 // non-empty. 187 bool ClipRect(const gfx::Rect& rect); 188 189 // Adds |path| to the current clip. Returns true if the resulting clip is 190 // non-empty. 191 bool ClipPath(const SkPath& path); 192 193 // Returns the bounds of the current clip (in local coordinates) in the 194 // |bounds| parameter, and returns true if it is non empty. 195 bool GetClipBounds(gfx::Rect* bounds); 196 197 void Translate(const gfx::Vector2d& offset); 198 199 void Scale(int x_scale, int y_scale); 200 201 // Fills the entire canvas' bitmap (restricted to current clip) with 202 // specified |color| using a transfer mode of SkXfermode::kSrcOver_Mode. 203 void DrawColor(SkColor color); 204 205 // Fills the entire canvas' bitmap (restricted to current clip) with 206 // specified |color| and |mode|. 207 void DrawColor(SkColor color, SkXfermode::Mode mode); 208 209 // Fills |rect| with |color| using a transfer mode of 210 // SkXfermode::kSrcOver_Mode. 211 void FillRect(const gfx::Rect& rect, SkColor color); 212 213 // Fills |rect| with the specified |color| and |mode|. 214 void FillRect(const gfx::Rect& rect, SkColor color, SkXfermode::Mode mode); 215 216 // Draws a single pixel rect in the specified region with the specified 217 // color, using a transfer mode of SkXfermode::kSrcOver_Mode. 218 // 219 // NOTE: if you need a single pixel line, use DrawLine. 220 void DrawRect(const gfx::Rect& rect, SkColor color); 221 222 // Draws a single pixel rect in the specified region with the specified 223 // color and transfer mode. 224 // 225 // NOTE: if you need a single pixel line, use DrawLine. 226 void DrawRect(const gfx::Rect& rect, SkColor color, SkXfermode::Mode mode); 227 228 // Draws the given rectangle with the given |paint| parameters. 229 void DrawRect(const gfx::Rect& rect, const SkPaint& paint); 230 231 // Draw the given point with the given |paint| parameters. 232 void DrawPoint(const gfx::Point& p, const SkPaint& paint); 233 234 // Draws a single pixel line with the specified color. 235 void DrawLine(const gfx::Point& p1, const gfx::Point& p2, SkColor color); 236 237 // Draws a line with the given |paint| parameters. 238 void DrawLine(const gfx::Point& p1, 239 const gfx::Point& p2, 240 const SkPaint& paint); 241 242 // Draws a circle with the given |paint| parameters. 243 void DrawCircle(const gfx::Point& center_point, 244 int radius, 245 const SkPaint& paint); 246 247 // Draws the given rectangle with rounded corners of |radius| using the 248 // given |paint| parameters. 249 void DrawRoundRect(const gfx::Rect& rect, int radius, const SkPaint& paint); 250 251 // Draws the given path using the given |paint| parameters. 252 void DrawPath(const SkPath& path, const SkPaint& paint); 253 254 // Draws an image with the origin at the specified location. The upper left 255 // corner of the bitmap is rendered at the specified location. 256 // Parameters are specified relative to current canvas scale not in pixels. 257 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1. 258 void DrawImageInt(const gfx::ImageSkia&, int x, int y); 259 260 // Helper for DrawImageInt(..., paint) that constructs a temporary paint and 261 // calls paint.setAlpha(alpha). 262 void DrawImageInt(const gfx::ImageSkia&, int x, int y, uint8 alpha); 263 264 // Draws an image with the origin at the specified location, using the 265 // specified paint. The upper left corner of the bitmap is rendered at the 266 // specified location. 267 // Parameters are specified relative to current canvas scale not in pixels. 268 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. 269 void DrawImageInt(const gfx::ImageSkia& image, 270 int x, int y, 271 const SkPaint& paint); 272 273 // Draws a portion of an image in the specified location. The src parameters 274 // correspond to the region of the bitmap to draw in the region defined 275 // by the dest coordinates. 276 // 277 // If the width or height of the source differs from that of the destination, 278 // the image will be scaled. When scaling down, a mipmap will be generated. 279 // Set |filter| to use filtering for images, otherwise the nearest-neighbor 280 // algorithm is used for resampling. 281 // 282 // An optional custom SkPaint can be provided. 283 // Parameters are specified relative to current canvas scale not in pixels. 284 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. 285 void DrawImageInt(const gfx::ImageSkia& image, 286 int src_x, int src_y, int src_w, int src_h, 287 int dest_x, int dest_y, int dest_w, int dest_h, 288 bool filter); 289 void DrawImageInt(const gfx::ImageSkia& image, 290 int src_x, int src_y, int src_w, int src_h, 291 int dest_x, int dest_y, int dest_w, int dest_h, 292 bool filter, 293 const SkPaint& paint); 294 295 // Draws an |image| with the top left corner at |x| and |y|, clipped to 296 // |path|. 297 // Parameters are specified relative to current canvas scale not in pixels. 298 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1. 299 void DrawImageInPath(const gfx::ImageSkia& image, 300 int x, 301 int y, 302 const SkPath& path, 303 const SkPaint& paint); 304 305 // Draws text with the specified color, font and location. The text is 306 // aligned to the left, vertically centered, clipped to the region. If the 307 // text is too big, it is truncated and '...' is added to the end. 308 void DrawStringInt(const base::string16& text, 309 const gfx::Font& font, 310 SkColor color, 311 int x, int y, int w, int h); 312 void DrawStringInt(const base::string16& text, 313 const gfx::Font& font, 314 SkColor color, 315 const gfx::Rect& display_rect); 316 317 // Draws text with the specified color, font and location. The last argument 318 // specifies flags for how the text should be rendered. It can be one of 319 // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT. 320 void DrawStringInt(const base::string16& text, 321 const gfx::Font& font, 322 SkColor color, 323 int x, int y, int w, int h, 324 int flags); 325 326 // Similar to above DrawStringInt method but with text shadows support. 327 // Currently it's only implemented for canvas skia. Specifying a 0 line_height 328 // will cause the default height to be used. 329 void DrawStringWithShadows(const base::string16& text, 330 const gfx::Font& font, 331 SkColor color, 332 const gfx::Rect& text_bounds, 333 int line_height, 334 int flags, 335 const ShadowValues& shadows); 336 337 // Draws a dotted gray rectangle used for focus purposes. 338 void DrawFocusRect(const gfx::Rect& rect); 339 340 // Tiles the image in the specified region. 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 TileImageInt(const gfx::ImageSkia& image, 344 int x, int y, int w, int h); 345 void TileImageInt(const gfx::ImageSkia& image, 346 int src_x, int src_y, 347 int dest_x, int dest_y, int w, int h); 348 void TileImageInt(const gfx::ImageSkia& image, 349 int src_x, int src_y, 350 float tile_scale_x, float tile_scale_y, 351 int dest_x, int dest_y, int w, int h); 352 353 // Returns a native drawing context for platform specific drawing routines to 354 // use. Must be balanced by a call to EndPlatformPaint(). 355 NativeDrawingContext BeginPlatformPaint(); 356 357 // Signifies the end of platform drawing using the native drawing context 358 // returned by BeginPlatformPaint(). 359 void EndPlatformPaint(); 360 361 // Apply transformation on the canvas. 362 void Transform(const gfx::Transform& transform); 363 364 // Draws the given string with the beginning and/or the end using a fade 365 // gradient. When truncating the head 366 // |desired_characters_to_truncate_from_head| specifies the maximum number of 367 // characters that can be truncated. 368 void DrawFadeTruncatingString( 369 const base::string16& text, 370 TruncateFadeMode truncate_mode, 371 size_t desired_characters_to_truncate_from_head, 372 const gfx::Font& font, 373 SkColor color, 374 const gfx::Rect& display_rect); 375 376 skia::PlatformCanvas* platform_canvas() const { return owned_canvas_.get(); } 377 SkCanvas* sk_canvas() const { return canvas_; } 378 ui::ScaleFactor scale_factor() const { return scale_factor_; } 379 380 private: 381 Canvas(SkCanvas* canvas, ui::ScaleFactor scale_factor); 382 383 // Test whether the provided rectangle intersects the current clip rect. 384 bool IntersectsClipRectInt(int x, int y, int w, int h); 385 bool IntersectsClipRect(const gfx::Rect& rect); 386 387 // Returns the image rep which best matches the canvas |scale_factor_|. 388 // Returns a null image rep if |image| contains no image reps. 389 // Builds mip map for returned image rep if necessary. 390 // 391 // An optional additional user defined scale can be provided. 392 const gfx::ImageSkiaRep& GetImageRepToPaint( 393 const gfx::ImageSkia& image) const; 394 const gfx::ImageSkiaRep& GetImageRepToPaint( 395 const gfx::ImageSkia& image, 396 float user_defined_scale_factor_x, 397 float user_defined_scale_factor_y) const; 398 399 // The device scale factor at which drawing on this canvas occurs. 400 // An additional scale can be applied via Canvas::Scale(). However, 401 // Canvas::Scale() does not affect |scale_factor_|. 402 ui::ScaleFactor scale_factor_; 403 404 skia::RefPtr<skia::PlatformCanvas> owned_canvas_; 405 SkCanvas* canvas_; 406 407 DISALLOW_COPY_AND_ASSIGN(Canvas); 408 }; 409 410 } // namespace gfx 411 412 #endif // UI_GFX_CANVAS_H_ 413