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 #include "ui/gfx/text_constants.h" 19 20 namespace gfx { 21 22 class Rect; 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 // Specifies the alignment for text rendered with the DrawStringRect method. 44 enum { 45 TEXT_ALIGN_LEFT = 1 << 0, 46 TEXT_ALIGN_CENTER = 1 << 1, 47 TEXT_ALIGN_RIGHT = 1 << 2, 48 49 // Specifies the text consists of multiple lines. 50 MULTI_LINE = 1 << 3, 51 52 // By default DrawStringRect does not process the prefix ('&') character 53 // specially. That is, the string "&foo" is rendered as "&foo". When 54 // rendering text from a resource that uses the prefix character for 55 // mnemonics, the prefix should be processed and can be rendered as an 56 // underline (SHOW_PREFIX), or not rendered at all (HIDE_PREFIX). 57 SHOW_PREFIX = 1 << 4, 58 HIDE_PREFIX = 1 << 5, 59 60 // Prevent ellipsizing 61 NO_ELLIPSIS = 1 << 6, 62 63 // Specifies if words can be split by new lines. 64 // This only works with MULTI_LINE. 65 CHARACTER_BREAK = 1 << 7, 66 67 // Instructs DrawStringRect() to render the text using RTL directionality. 68 // In most cases, passing this flag is not necessary because information 69 // about the text directionality is going to be embedded within the string 70 // in the form of special Unicode characters. However, we don't insert 71 // directionality characters into strings if the locale is LTR because some 72 // platforms (for example, an English Windows XP with no RTL fonts 73 // installed) don't support these characters. Thus, this flag should be 74 // used to render text using RTL directionality when the locale is LTR. 75 FORCE_RTL_DIRECTIONALITY = 1 << 8, 76 77 // Similar to FORCE_RTL_DIRECTIONALITY, but left-to-right. 78 // See FORCE_RTL_DIRECTIONALITY for details. 79 FORCE_LTR_DIRECTIONALITY = 1 << 9, 80 81 // Instructs DrawStringRect() to not use subpixel rendering. This is useful 82 // when rendering text onto a fully- or partially-transparent background 83 // that will later be blended with another image. 84 NO_SUBPIXEL_RENDERING = 1 << 10, 85 }; 86 87 // Creates an empty canvas with image_scale of 1x. 88 Canvas(); 89 90 // Creates canvas with provided DIP |size| and |image_scale|. 91 // If this canvas is not opaque, it's explicitly cleared to transparent before 92 // being returned. 93 Canvas(const Size& size, float image_scale, bool is_opaque); 94 95 // Constructs a canvas with the size and the image_scale of the provided 96 // |image_rep|, and draws the |image_rep| into it. 97 Canvas(const ImageSkiaRep& image_rep, bool is_opaque); 98 99 virtual ~Canvas(); 100 101 // Creates a Canvas backed by an |sk_canvas| with |image_scale_|. 102 // |sk_canvas| is assumed to be already scaled based on |image_scale| 103 // so no additional scaling is applied. 104 static Canvas* CreateCanvasWithoutScaling(SkCanvas* sk_canvas, 105 float image_scale); 106 107 // Recreates the backing platform canvas with DIP |size| and |image_scale_|. 108 // If the canvas is not opaque, it is explicitly cleared. 109 // This method is public so that canvas_skia_paint can recreate the platform 110 // canvas after having initialized the canvas. 111 // TODO(pkotwicz): Push the image_scale into skia::PlatformCanvas such that 112 // this method can be private. 113 void RecreateBackingCanvas(const Size& size, 114 float image_scale, 115 bool is_opaque); 116 117 // Compute the size required to draw some text with the provided fonts. 118 // Attempts to fit the text with the provided width and height. Increases 119 // height and then width as needed to make the text fit. This method 120 // supports multiple lines. On Skia only a line_height can be specified and 121 // specifying a 0 value for it will cause the default height to be used. 122 static void SizeStringInt(const base::string16& text, 123 const FontList& font_list, 124 int* width, 125 int* height, 126 int line_height, 127 int flags); 128 129 // This is same as SizeStringInt except that fractional size is returned. 130 // See comment in GetStringWidthF for its usage. 131 static void SizeStringFloat(const base::string16& text, 132 const FontList& font_list, 133 float* width, 134 float* height, 135 int line_height, 136 int flags); 137 138 // Returns the number of horizontal pixels needed to display the specified 139 // |text| with |font_list|. 140 static int GetStringWidth(const base::string16& text, 141 const FontList& font_list); 142 143 // This is same as GetStringWidth except that fractional width is returned. 144 // Use this method for the scenario that multiple string widths need to be 145 // summed up. This is because GetStringWidth returns the ceiled width and 146 // adding multiple ceiled widths could cause more precision loss for certain 147 // platform like Mac where the fractioal width is used. 148 static float GetStringWidthF(const base::string16& text, 149 const FontList& font_list); 150 151 // Returns the default text alignment to be used when drawing text on a 152 // Canvas based on the directionality of the system locale language. 153 // This function is used by Canvas::DrawStringRect when the text alignment 154 // is not specified. 155 // 156 // This function returns either Canvas::TEXT_ALIGN_LEFT or 157 // Canvas::TEXT_ALIGN_RIGHT. 158 static int DefaultCanvasTextAlignment(); 159 160 // Draws text with a 1-pixel halo around it of the given color. 161 // On Windows, it allows ClearType to be drawn to an otherwise transparent 162 // bitmap for drag images. Drag images have only 1-bit of transparency, so 163 // we don't do any fancy blurring. 164 // On Linux, text with halo is created by stroking it with 2px |halo_color| 165 // then filling it with |text_color|. 166 // On Mac, NOTIMPLEMENTED. 167 // TODO(dhollowa): Skia-native implementation is underway. Cut over to 168 // that when ready. http::/crbug.com/109946 169 void DrawStringRectWithHalo(const base::string16& text, 170 const FontList& font_list, 171 SkColor text_color, 172 SkColor halo_color, 173 const Rect& display_rect, 174 int flags); 175 176 // Extracts an ImageSkiaRep from the contents of this canvas. 177 ImageSkiaRep ExtractImageRep() const; 178 179 // Draws a dashed rectangle of the specified color. 180 void DrawDashedRect(const Rect& rect, SkColor color); 181 182 // Saves a copy of the drawing state onto a stack, operating on this copy 183 // until a balanced call to Restore() is made. 184 void Save(); 185 186 // As with Save(), except draws to a layer that is blended with the canvas 187 // at the specified alpha once Restore() is called. 188 // |layer_bounds| are the bounds of the layer relative to the current 189 // transform. 190 void SaveLayerAlpha(uint8 alpha); 191 void SaveLayerAlpha(uint8 alpha, const Rect& layer_bounds); 192 193 // Restores the drawing state after a call to Save*(). It is an error to 194 // call Restore() more times than Save*(). 195 void Restore(); 196 197 // Adds |rect| to the current clip. 198 void ClipRect(const Rect& rect); 199 200 // Adds |path| to the current clip. |do_anti_alias| is true if the clip 201 // should be antialiased. 202 void ClipPath(const SkPath& path, bool do_anti_alias); 203 204 // Returns true if the current clip is empty. 205 bool IsClipEmpty() const; 206 207 // Returns the bounds of the current clip (in local coordinates) in the 208 // |bounds| parameter, and returns true if it is non empty. 209 bool GetClipBounds(Rect* bounds); 210 211 void Translate(const Vector2d& offset); 212 213 void Scale(int x_scale, int y_scale); 214 215 // Fills the entire canvas' bitmap (restricted to current clip) with 216 // specified |color| using a transfer mode of SkXfermode::kSrcOver_Mode. 217 void DrawColor(SkColor color); 218 219 // Fills the entire canvas' bitmap (restricted to current clip) with 220 // specified |color| and |mode|. 221 void DrawColor(SkColor color, SkXfermode::Mode mode); 222 223 // Fills |rect| with |color| using a transfer mode of 224 // SkXfermode::kSrcOver_Mode. 225 void FillRect(const Rect& rect, SkColor color); 226 227 // Fills |rect| with the specified |color| and |mode|. 228 void FillRect(const Rect& rect, SkColor color, SkXfermode::Mode mode); 229 230 // Draws a single pixel rect in the specified region with the specified 231 // color, using a transfer mode of SkXfermode::kSrcOver_Mode. 232 // 233 // NOTE: if you need a single pixel line, use DrawLine. 234 void DrawRect(const Rect& rect, SkColor color); 235 236 // Draws a single pixel rect in the specified region with the specified 237 // color and transfer mode. 238 // 239 // NOTE: if you need a single pixel line, use DrawLine. 240 void DrawRect(const Rect& rect, SkColor color, SkXfermode::Mode mode); 241 242 // Draws the given rectangle with the given |paint| parameters. 243 void DrawRect(const Rect& rect, const SkPaint& paint); 244 245 // Draw the given point with the given |paint| parameters. 246 void DrawPoint(const Point& p, const SkPaint& paint); 247 248 // Draws a single pixel line with the specified color. 249 void DrawLine(const Point& p1, const Point& p2, SkColor color); 250 251 // Draws a line with the given |paint| parameters. 252 void DrawLine(const Point& p1, const Point& p2, const SkPaint& paint); 253 254 // Draws a circle with the given |paint| parameters. 255 void DrawCircle(const Point& center_point, 256 int radius, 257 const SkPaint& paint); 258 259 // Draws the given rectangle with rounded corners of |radius| using the 260 // given |paint| parameters. 261 void DrawRoundRect(const Rect& rect, int radius, const SkPaint& paint); 262 263 // Draws the given path using the given |paint| parameters. 264 void DrawPath(const SkPath& path, const SkPaint& paint); 265 266 // Draws an image with the origin at the specified location. The upper left 267 // corner of the bitmap is rendered at the specified location. 268 // Parameters are specified relative to current canvas scale not in pixels. 269 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1. 270 void DrawImageInt(const ImageSkia&, int x, int y); 271 272 // Helper for DrawImageInt(..., paint) that constructs a temporary paint and 273 // calls paint.setAlpha(alpha). 274 void DrawImageInt(const ImageSkia&, int x, int y, uint8 alpha); 275 276 // Draws an image with the origin at the specified location, using the 277 // specified paint. The upper left corner of the bitmap is rendered at the 278 // specified location. 279 // Parameters are specified relative to current canvas scale not in pixels. 280 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. 281 void DrawImageInt(const ImageSkia& image, 282 int x, 283 int y, 284 const SkPaint& paint); 285 286 // Draws a portion of an image in the specified location. The src parameters 287 // correspond to the region of the bitmap to draw in the region defined 288 // by the dest coordinates. 289 // 290 // If the width or height of the source differs from that of the destination, 291 // the image will be scaled. When scaling down, a mipmap will be generated. 292 // Set |filter| to use filtering for images, otherwise the nearest-neighbor 293 // algorithm is used for resampling. 294 // 295 // An optional custom SkPaint can be provided. 296 // Parameters are specified relative to current canvas scale not in pixels. 297 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. 298 void DrawImageInt(const ImageSkia& image, 299 int src_x, 300 int src_y, 301 int src_w, 302 int src_h, 303 int dest_x, 304 int dest_y, 305 int dest_w, 306 int dest_h, 307 bool filter); 308 void DrawImageInt(const ImageSkia& image, 309 int src_x, 310 int src_y, 311 int src_w, 312 int src_h, 313 int dest_x, 314 int dest_y, 315 int dest_w, 316 int dest_h, 317 bool filter, 318 const SkPaint& paint); 319 320 // Same as the DrawImageInt functions above. Difference being this does not 321 // do any scaling, i.e. it assumes that the source/destination/image, etc are 322 // in pixels. It does translate the destination rectangle to ensure that the 323 // image is displayed at the correct pixel coordinates. 324 void DrawImageIntInPixel(const ImageSkia& image, 325 int src_x, 326 int src_y, 327 int src_w, 328 int src_h, 329 int dest_x, 330 int dest_y, 331 int dest_w, 332 int dest_h, 333 bool filter, 334 const SkPaint& paint); 335 336 // Draws an |image| with the top left corner at |x| and |y|, clipped to 337 // |path|. 338 // Parameters are specified relative to current canvas scale not in pixels. 339 // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1. 340 void DrawImageInPath(const ImageSkia& image, 341 int x, 342 int y, 343 const SkPath& path, 344 const SkPaint& paint); 345 346 // Draws text with the specified color, fonts and location. The text is 347 // aligned to the left, vertically centered, clipped to the region. If the 348 // text is too big, it is truncated and '...' is added to the end. 349 void DrawStringRect(const base::string16& text, 350 const FontList& font_list, 351 SkColor color, 352 const Rect& display_rect); 353 354 // Draws text with the specified color, fonts and location. The last argument 355 // specifies flags for how the text should be rendered. It can be one of 356 // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT. 357 void DrawStringRectWithFlags(const base::string16& text, 358 const FontList& font_list, 359 SkColor color, 360 const Rect& display_rect, 361 int flags); 362 363 // Similar to above DrawStringRect method but with text shadows support. 364 // Currently it's only implemented for canvas skia. Specifying a 0 line_height 365 // will cause the default height to be used. 366 void DrawStringRectWithShadows(const base::string16& text, 367 const FontList& font_list, 368 SkColor color, 369 const Rect& text_bounds, 370 int line_height, 371 int flags, 372 const ShadowValues& shadows); 373 374 // Draws a dotted gray rectangle used for focus purposes. 375 void DrawFocusRect(const Rect& rect); 376 377 // Draws a |rect| in the specified region with the specified |color| with a 378 // with of one logical pixel which might be more device pixels. 379 void DrawSolidFocusRect(const Rect& rect, SkColor color); 380 381 // Tiles the image in the specified region. 382 // Parameters are specified relative to current canvas scale not in pixels. 383 // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1. 384 void TileImageInt(const ImageSkia& image, 385 int x, 386 int y, 387 int w, 388 int h); 389 void TileImageInt(const ImageSkia& image, 390 int src_x, 391 int src_y, 392 int dest_x, 393 int dest_y, 394 int w, 395 int h); 396 void TileImageInt(const ImageSkia& image, 397 int src_x, 398 int src_y, 399 float tile_scale_x, 400 float tile_scale_y, 401 int dest_x, 402 int dest_y, 403 int w, 404 int h); 405 406 // Returns a native drawing context for platform specific drawing routines to 407 // use. Must be balanced by a call to EndPlatformPaint(). 408 NativeDrawingContext BeginPlatformPaint(); 409 410 // Signifies the end of platform drawing using the native drawing context 411 // returned by BeginPlatformPaint(). 412 void EndPlatformPaint(); 413 414 // Apply transformation on the canvas. 415 void Transform(const Transform& transform); 416 417 // Draws the given string with a fade gradient at the end. 418 void DrawFadedString(const base::string16& text, 419 const FontList& font_list, 420 SkColor color, 421 const Rect& display_rect, 422 int flags); 423 platform_canvas()424 skia::PlatformCanvas* platform_canvas() { return owned_canvas_.get(); } sk_canvas()425 SkCanvas* sk_canvas() { return canvas_; } image_scale()426 float image_scale() const { return image_scale_; } 427 428 private: 429 Canvas(SkCanvas* canvas, float image_scale); 430 431 // Test whether the provided rectangle intersects the current clip rect. 432 bool IntersectsClipRectInt(int x, int y, int w, int h); 433 bool IntersectsClipRect(const Rect& rect); 434 435 // Helper for the DrawImageInt functions declared above. The |pixel| 436 // parameter if true indicates that the bounds and the image are to 437 // be assumed to be in pixels, i.e. no scaling needs to be performed. 438 void DrawImageIntHelper(const ImageSkia& image, 439 int src_x, 440 int src_y, 441 int src_w, 442 int src_h, 443 int dest_x, 444 int dest_y, 445 int dest_w, 446 int dest_h, 447 bool filter, 448 const SkPaint& paint, 449 float image_scale, 450 bool pixel); 451 452 // The device scale factor at which drawing on this canvas occurs. 453 // An additional scale can be applied via Canvas::Scale(). However, 454 // Canvas::Scale() does not affect |image_scale_|. 455 float image_scale_; 456 457 skia::RefPtr<skia::PlatformCanvas> owned_canvas_; 458 SkCanvas* canvas_; 459 460 DISALLOW_COPY_AND_ASSIGN(Canvas); 461 }; 462 463 } // namespace gfx 464 465 #endif // UI_GFX_CANVAS_H_ 466