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 FontList; 24 class Point; 25 class Size; 26 class Transform; 27 28 // Canvas is a SkCanvas wrapper that provides a number of methods for 29 // common operations used throughout an application built using ui/gfx. 30 // 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()|. 35 // 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 40 // of kSrcOver_Mode. 41 class GFX_EXPORT Canvas { 42 public: 43 enum TruncateFadeMode { 44 TruncateFadeTail, 45 TruncateFadeHead, 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 image_scale of 1x. 93 Canvas(); 94 95 // Creates canvas with provided DIP |size| and |image_scale|. 96 // If this canvas is not opaque, it's explicitly cleared to transparent before 97 // being returned. 98 Canvas(const Size& size, float image_scale, bool is_opaque); 99 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); 103 104 virtual ~Canvas(); 105 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, 110 float image_scale); 111 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, 119 float image_scale, 120 bool is_opaque); 121 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, 129 int* width, 130 int* height, 131 int line_height, 132 int flags); 133 // Obsolete version. Use the above version which takes FontList. 134 static void SizeStringInt(const base::string16& text, 135 const Font& font, 136 int* width, 137 int* height, 138 int line_height, 139 int flags); 140 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, 145 float* width, 146 float* height, 147 int line_height, 148 int flags); 149 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); 156 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); 164 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 168 // is not specified. 169 // 170 // This function returns either Canvas::TEXT_ALIGN_LEFT or 171 // Canvas::TEXT_ALIGN_RIGHT. 172 static int DefaultCanvasTextAlignment(); 173 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, 185 SkColor text_color, 186 SkColor halo_color, 187 const Rect& display_rect, 188 int flags); 189 // Obsolete version. Use the above version which takes FontList. 190 void DrawStringWithHalo(const base::string16& text, 191 const Font& font, 192 SkColor text_color, 193 SkColor halo_color, 194 int x, 195 int y, 196 int w, 197 int h, 198 int flags); 199 200 // Extracts an ImageSkiaRep from the contents of this canvas. 201 ImageSkiaRep ExtractImageRep() const; 202 203 // Draws a dashed rectangle of the specified color. 204 void DrawDashedRect(const Rect& rect, SkColor color); 205 206 // Saves a copy of the drawing state onto a stack, operating on this copy 207 // until a balanced call to Restore() is made. 208 void Save(); 209 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 213 // transform. 214 void SaveLayerAlpha(uint8 alpha); 215 void SaveLayerAlpha(uint8 alpha, const Rect& layer_bounds); 216 217 // Restores the drawing state after a call to Save*(). It is an error to 218 // call Restore() more times than Save*(). 219 void Restore(); 220 221 // Adds |rect| to the current clip. Returns true if the resulting clip is 222 // non-empty. 223 bool ClipRect(const Rect& rect); 224 225 // Adds |path| to the current clip. Returns true if the resulting clip is 226 // non-empty. 227 bool ClipPath(const SkPath& path); 228 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); 232 233 void Translate(const Vector2d& offset); 234 235 void Scale(int x_scale, int y_scale); 236 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); 240 241 // Fills the entire canvas' bitmap (restricted to current clip) with 242 // specified |color| and |mode|. 243 void DrawColor(SkColor color, SkXfermode::Mode mode); 244 245 // Fills |rect| with |color| using a transfer mode of 246 // SkXfermode::kSrcOver_Mode. 247 void FillRect(const Rect& rect, SkColor color); 248 249 // Fills |rect| with the specified |color| and |mode|. 250 void FillRect(const Rect& rect, SkColor color, SkXfermode::Mode mode); 251 252 // Draws a single pixel rect in the specified region with the specified 253 // color, using a transfer mode of SkXfermode::kSrcOver_Mode. 254 // 255 // NOTE: if you need a single pixel line, use DrawLine. 256 void DrawRect(const Rect& rect, SkColor color); 257 258 // Draws a single pixel rect in the specified region with the specified 259 // color and transfer mode. 260 // 261 // NOTE: if you need a single pixel line, use DrawLine. 262 void DrawRect(const Rect& rect, SkColor color, SkXfermode::Mode mode); 263 264 // Draws the given rectangle with the given |paint| parameters. 265 void DrawRect(const Rect& rect, const SkPaint& paint); 266 267 // Draw the given point with the given |paint| parameters. 268 void DrawPoint(const Point& p, const SkPaint& paint); 269 270 // Draws a single pixel line with the specified color. 271 void DrawLine(const Point& p1, const Point& p2, SkColor color); 272 273 // Draws a line with the given |paint| parameters. 274 void DrawLine(const Point& p1, const Point& p2, const SkPaint& paint); 275 276 // Draws a circle with the given |paint| parameters. 277 void DrawCircle(const Point& center_point, 278 int radius, 279 const SkPaint& paint); 280 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); 284 285 // Draws the given path using the given |paint| parameters. 286 void DrawPath(const SkPath& path, const SkPaint& paint); 287 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); 293 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); 297 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, 304 int x, 305 int y, 306 const SkPaint& paint); 307 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. 311 // 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. 316 // 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, 321 int src_x, 322 int src_y, 323 int src_w, 324 int src_h, 325 int dest_x, 326 int dest_y, 327 int dest_w, 328 int dest_h, 329 bool filter); 330 void DrawImageInt(const ImageSkia& image, 331 int src_x, 332 int src_y, 333 int src_w, 334 int src_h, 335 int dest_x, 336 int dest_y, 337 int dest_w, 338 int dest_h, 339 bool filter, 340 const SkPaint& paint); 341 342 // Draws an |image| with the top left corner at |x| and |y|, clipped to 343 // |path|. 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, 347 int x, 348 int y, 349 const SkPath& path, 350 const SkPaint& paint); 351 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, 357 SkColor color, 358 const Rect& display_rect); 359 // Obsolete versions. Use the above versions which take FontList. 360 void DrawStringInt(const base::string16& text, 361 const Font& font, 362 SkColor color, 363 int x, 364 int y, 365 int w, 366 int h); 367 void DrawStringInt(const base::string16& text, 368 const Font& font, 369 SkColor color, 370 const Rect& display_rect); 371 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, 377 SkColor color, 378 const Rect& display_rect, 379 int flags); 380 // Obsolete version. Use the above version which takes FontList. 381 void DrawStringInt(const base::string16& text, 382 const Font& font, 383 SkColor color, 384 int x, 385 int y, 386 int w, 387 int h, 388 int flags); 389 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, 395 SkColor color, 396 const Rect& text_bounds, 397 int line_height, 398 int flags, 399 const ShadowValues& shadows); 400 // Obsolete version. Use the above version which takes FontList. 401 void DrawStringWithShadows(const base::string16& text, 402 const Font& font, 403 SkColor color, 404 const Rect& text_bounds, 405 int line_height, 406 int flags, 407 const ShadowValues& shadows); 408 409 // Draws a dotted gray rectangle used for focus purposes. 410 void DrawFocusRect(const Rect& rect); 411 412 // Draws a |rect| in the specified region with the specified |color| with a 413 // with of one logical pixel which might be more device pixels. 414 void DrawSolidFocusRect(const Rect& rect, SkColor color); 415 416 // Tiles the image in the specified region. 417 // Parameters are specified relative to current canvas scale not in pixels. 418 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. 419 void TileImageInt(const ImageSkia& image, 420 int x, 421 int y, 422 int w, 423 int h); 424 void TileImageInt(const ImageSkia& image, 425 int src_x, 426 int src_y, 427 int dest_x, 428 int dest_y, 429 int w, 430 int h); 431 void TileImageInt(const ImageSkia& image, 432 int src_x, 433 int src_y, 434 float tile_scale_x, 435 float tile_scale_y, 436 int dest_x, 437 int dest_y, 438 int w, 439 int h); 440 441 // Returns a native drawing context for platform specific drawing routines to 442 // use. Must be balanced by a call to EndPlatformPaint(). 443 NativeDrawingContext BeginPlatformPaint(); 444 445 // Signifies the end of platform drawing using the native drawing context 446 // returned by BeginPlatformPaint(). 447 void EndPlatformPaint(); 448 449 // Apply transformation on the canvas. 450 void Transform(const Transform& transform); 451 452 // Draws the given string with the beginning or the end using a fade gradient. 453 void DrawFadeTruncatingStringRect( 454 const base::string16& text, 455 TruncateFadeMode truncate_mode, 456 const FontList& font_list, 457 SkColor color, 458 const Rect& display_rect); 459 void DrawFadeTruncatingStringRectWithFlags( 460 const base::string16& text, 461 TruncateFadeMode truncate_mode, 462 const FontList& font_list, 463 SkColor color, 464 const Rect& display_rect, 465 int flags); 466 467 skia::PlatformCanvas* platform_canvas() const { return owned_canvas_.get(); } 468 SkCanvas* sk_canvas() const { return canvas_; } 469 float image_scale() const { return image_scale_; } 470 471 private: 472 Canvas(SkCanvas* canvas, float image_scale); 473 474 // Test whether the provided rectangle intersects the current clip rect. 475 bool IntersectsClipRectInt(int x, int y, int w, int h); 476 bool IntersectsClipRect(const Rect& rect); 477 478 // Returns the image rep which best matches the canvas |image_scale_|. 479 // Returns a null image rep if |image| contains no image reps. 480 // Builds mip map for returned image rep if necessary. 481 // 482 // An optional additional user defined scale can be provided. 483 const ImageSkiaRep& GetImageRepToPaint(const ImageSkia& image) const; 484 const ImageSkiaRep& GetImageRepToPaint( 485 const ImageSkia& image, 486 float user_defined_scale_factor_x, 487 float user_defined_scale_factor_y) const; 488 489 // The device scale factor at which drawing on this canvas occurs. 490 // An additional scale can be applied via Canvas::Scale(). However, 491 // Canvas::Scale() does not affect |image_scale_|. 492 float image_scale_; 493 494 skia::RefPtr<skia::PlatformCanvas> owned_canvas_; 495 SkCanvas* canvas_; 496 497 DISALLOW_COPY_AND_ASSIGN(Canvas); 498 }; 499 500 } // namespace gfx 501 502 #endif // UI_GFX_CANVAS_H_ 503