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 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