Home | History | Annotate | Download | only in gfx
      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