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 #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 
    424   skia::PlatformCanvas* platform_canvas() { return owned_canvas_.get(); }
    425   SkCanvas* sk_canvas() { return canvas_; }
    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