canvas.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. #ifndef UI_GFX_CANVAS_H_
  5. #define UI_GFX_CANVAS_H_
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "base/memory/raw_ptr.h"
  11. #include "cc/paint/paint_canvas.h"
  12. #include "cc/paint/paint_flags.h"
  13. #include "cc/paint/skia_paint_canvas.h"
  14. #include "cc/paint/skottie_color_map.h"
  15. #include "cc/paint/skottie_frame_data.h"
  16. #include "cc/paint/skottie_text_property_value.h"
  17. #include "third_party/abseil-cpp/absl/types/optional.h"
  18. #include "ui/gfx/image/image_skia.h"
  19. #include "ui/gfx/native_widget_types.h"
  20. #include "ui/gfx/text_constants.h"
  21. namespace cc {
  22. class SkottieWrapper;
  23. } // namespace cc
  24. namespace gfx {
  25. class Rect;
  26. class RectF;
  27. class FontList;
  28. class Point;
  29. class PointF;
  30. class Size;
  31. class Transform;
  32. class Vector2d;
  33. // Canvas is a PaintCanvas wrapper that provides a number of methods for
  34. // common operations used throughout an application built using ui/gfx.
  35. //
  36. // All methods that take integer arguments (as is used throughout views)
  37. // end with Int. If you need to use methods provided by PaintCanvas, you'll
  38. // need to do a conversion. In particular you'll need to use |SkIntToScalar()|,
  39. // or if converting from a scalar to an integer |SkScalarRound()|.
  40. //
  41. // A handful of methods in this class are overloaded providing an additional
  42. // argument of type SkBlendMode. SkBlendMode specifies how the
  43. // source and destination colors are combined. Unless otherwise specified,
  44. // the variant that does not take a SkBlendMode uses a transfer mode
  45. // of kSrcOver_Mode.
  46. class GFX_EXPORT Canvas {
  47. public:
  48. enum {
  49. // Specifies the alignment for text rendered with the DrawStringRect method.
  50. TEXT_ALIGN_LEFT = 1 << 0,
  51. TEXT_ALIGN_CENTER = 1 << 1,
  52. TEXT_ALIGN_RIGHT = 1 << 2,
  53. TEXT_ALIGN_TO_HEAD = 1 << 3,
  54. // Specifies the text consists of multiple lines.
  55. MULTI_LINE = 1 << 4,
  56. // By default DrawStringRect does not process the prefix ('&') character
  57. // specially. That is, the string "&foo" is rendered as "&foo". When
  58. // rendering text from a resource that uses the prefix character for
  59. // mnemonics, the prefix should be processed and can be rendered as an
  60. // underline (SHOW_PREFIX), or not rendered at all (HIDE_PREFIX).
  61. SHOW_PREFIX = 1 << 5,
  62. HIDE_PREFIX = 1 << 6,
  63. // Prevent ellipsizing
  64. NO_ELLIPSIS = 1 << 7,
  65. // Specifies if words can be split by new lines.
  66. // This only works with MULTI_LINE.
  67. CHARACTER_BREAKABLE = 1 << 8,
  68. // Instructs DrawStringRect() to not use subpixel rendering. This is useful
  69. // when rendering text onto a fully- or partially-transparent background
  70. // that will later be blended with another image.
  71. NO_SUBPIXEL_RENDERING = 1 << 9,
  72. };
  73. // Creates an empty canvas with image_scale of 1x.
  74. Canvas();
  75. // Creates canvas with provided DIP |size| and |image_scale|.
  76. // If this canvas is not opaque, it's explicitly cleared to transparent before
  77. // being returned.
  78. Canvas(const Size& size, float image_scale, bool is_opaque);
  79. // Creates a Canvas backed by an |sk_canvas| with |image_scale_|.
  80. // |sk_canvas| is assumed to be already scaled based on |image_scale|
  81. // so no additional scaling is applied.
  82. // Note: the caller must ensure that sk_canvas outlives this object, or until
  83. // RecreateBackingCanvas is called.
  84. Canvas(cc::PaintCanvas* sk_canvas, float image_scale);
  85. Canvas(const Canvas&) = delete;
  86. Canvas& operator=(const Canvas&) = delete;
  87. virtual ~Canvas();
  88. // Recreates the backing platform canvas with DIP |size| and |image_scale_|.
  89. // If the canvas is not opaque, it is explicitly cleared.
  90. // TODO(pkotwicz): Push the image_scale into skia::PlatformCanvas such that
  91. // this method can be private.
  92. void RecreateBackingCanvas(const Size& size,
  93. float image_scale,
  94. bool is_opaque);
  95. // Compute the size required to draw some text with the provided fonts.
  96. // Attempts to fit the text with the provided width and height. Increases
  97. // height and then width as needed to make the text fit. This method
  98. // supports multiple lines. On Skia only a line_height can be specified and
  99. // specifying a 0 value for it will cause the default height to be used.
  100. static void SizeStringInt(const std::u16string& text,
  101. const FontList& font_list,
  102. int* width,
  103. int* height,
  104. int line_height,
  105. int flags);
  106. // This is same as SizeStringInt except that fractional size is returned.
  107. // See comment in GetStringWidthF for its usage.
  108. static void SizeStringFloat(const std::u16string& text,
  109. const FontList& font_list,
  110. float* width,
  111. float* height,
  112. int line_height,
  113. int flags);
  114. // Returns the number of horizontal pixels needed to display the specified
  115. // |text| with |font_list|.
  116. static int GetStringWidth(const std::u16string& text,
  117. const FontList& font_list);
  118. // This is same as GetStringWidth except that fractional width is returned.
  119. // Use this method for the scenario that multiple string widths need to be
  120. // summed up. This is because GetStringWidth returns the ceiled width and
  121. // adding multiple ceiled widths could cause more precision loss for certain
  122. // platform like Mac where the fractional width is used.
  123. static float GetStringWidthF(const std::u16string& text,
  124. const FontList& font_list);
  125. // Returns the default text alignment to be used when drawing text on a
  126. // Canvas based on the directionality of the system locale language.
  127. // This function is used by Canvas::DrawStringRect when the text alignment
  128. // is not specified.
  129. //
  130. // This function returns either Canvas::TEXT_ALIGN_LEFT or
  131. // Canvas::TEXT_ALIGN_RIGHT.
  132. static int DefaultCanvasTextAlignment();
  133. // Unscales by the image scale factor (aka device scale factor), and returns
  134. // that factor. This is useful when callers want to draw directly in the
  135. // native scale.
  136. float UndoDeviceScaleFactor();
  137. // Saves a copy of the drawing state onto a stack, operating on this copy
  138. // until a balanced call to Restore() is made.
  139. void Save();
  140. // As with Save(), except draws to a layer that is blended with the canvas
  141. // at the specified alpha once Restore() is called.
  142. // |layer_bounds| are the bounds of the layer relative to the current
  143. // transform.
  144. void SaveLayerAlpha(uint8_t alpha);
  145. void SaveLayerAlpha(uint8_t alpha, const Rect& layer_bounds);
  146. // Like SaveLayerAlpha but draws the layer with an arbitrary set of
  147. // PaintFlags once Restore() is called.
  148. void SaveLayerWithFlags(const cc::PaintFlags& flags);
  149. // Restores the drawing state after a call to Save*(). It is an error to
  150. // call Restore() more times than Save*().
  151. void Restore();
  152. // Applies |rect| to the current clip using the specified region |op|.
  153. void ClipRect(const Rect& rect, SkClipOp op = SkClipOp::kIntersect);
  154. void ClipRect(const RectF& rect, SkClipOp op = SkClipOp::kIntersect);
  155. // Adds |path| to the current clip. |do_anti_alias| is true if the clip
  156. // should be antialiased.
  157. void ClipPath(const SkPath& path, bool do_anti_alias);
  158. // Returns the bounds of the current clip (in local coordinates) in the
  159. // |bounds| parameter, and returns true if it is non empty.
  160. bool GetClipBounds(Rect* bounds);
  161. void Translate(const Vector2d& offset);
  162. void Scale(float x_scale, float y_scale);
  163. // Fills the entire canvas' bitmap (restricted to current clip) with
  164. // specified |color| using a transfer mode of SkBlendMode::kSrcOver.
  165. void DrawColor(SkColor color);
  166. // Fills the entire canvas' bitmap (restricted to current clip) with
  167. // specified |color| and |mode|.
  168. void DrawColor(SkColor color, SkBlendMode mode);
  169. // Fills |rect| with |color| using a transfer mode of
  170. // SkBlendMode::kSrcOver.
  171. void FillRect(const Rect& rect, SkColor color);
  172. // Fills |rect| with the specified |color| and |mode|.
  173. void FillRect(const Rect& rect, SkColor color, SkBlendMode mode);
  174. // Draws a single pixel rect in the specified region with the specified
  175. // color, using a transfer mode of SkBlendMode::kSrcOver.
  176. //
  177. // NOTE: if you need a single pixel line, use DrawLine.
  178. void DrawRect(const RectF& rect, SkColor color);
  179. // Draws a single pixel rect in the specified region with the specified
  180. // color and transfer mode.
  181. //
  182. // NOTE: if you need a single pixel line, use DrawLine.
  183. void DrawRect(const RectF& rect, SkColor color, SkBlendMode mode);
  184. // Draws the given rectangle with the given |flags| parameters.
  185. // DEPRECATED in favor of the RectF version below.
  186. // TODO(funkysidd): Remove this (http://crbug.com/553726)
  187. void DrawRect(const Rect& rect, const cc::PaintFlags& flags);
  188. // Draws the given rectangle with the given |flags| parameters.
  189. void DrawRect(const RectF& rect, const cc::PaintFlags& flags);
  190. // Draws a single pixel line with the specified color.
  191. // DEPRECATED in favor of the RectF version below.
  192. // TODO(funkysidd): Remove this (http://crbug.com/553726)
  193. void DrawLine(const Point& p1, const Point& p2, SkColor color);
  194. // Draws a single dip line with the specified color.
  195. void DrawLine(const PointF& p1, const PointF& p2, SkColor color);
  196. // Draws a line with the given |flags| parameters.
  197. // DEPRECATED in favor of the RectF version below.
  198. // TODO(funkysidd): Remove this (http://crbug.com/553726)
  199. void DrawLine(const Point& p1, const Point& p2, const cc::PaintFlags& flags);
  200. // Draws a line with the given |flags| parameters.
  201. void DrawLine(const PointF& p1,
  202. const PointF& p2,
  203. const cc::PaintFlags& flags);
  204. // Draws a line that's a single DIP. At fractional scale factors, this is
  205. // floored to the nearest integral number of pixels.
  206. void DrawSharpLine(PointF p1, PointF p2, SkColor color);
  207. // As above, but draws a single pixel at all scale factors.
  208. void Draw1pxLine(PointF p1, PointF p2, SkColor color);
  209. // Draws a circle with the given |flags| parameters.
  210. // DEPRECATED in favor of the RectF version below.
  211. // TODO(funkysidd): Remove this (http://crbug.com/553726)
  212. void DrawCircle(const Point& center_point,
  213. int radius,
  214. const cc::PaintFlags& flags);
  215. // Draws a circle with the given |flags| parameters.
  216. void DrawCircle(const PointF& center_point,
  217. float radius,
  218. const cc::PaintFlags& flags);
  219. // Draws the given rectangle with rounded corners of |radius| using the
  220. // given |flags| parameters. DEPRECATED in favor of the RectF version below.
  221. // TODO(mgiuca): Remove this (http://crbug.com/553726).
  222. void DrawRoundRect(const Rect& rect, int radius, const cc::PaintFlags& flags);
  223. // Draws the given rectangle with rounded corners of |radius| using the
  224. // given |flags| parameters.
  225. void DrawRoundRect(const RectF& rect,
  226. float radius,
  227. const cc::PaintFlags& flags);
  228. // Draws the given path using the given |flags| parameters.
  229. void DrawPath(const SkPath& path, const cc::PaintFlags& flags);
  230. // Draws an image with the origin at the specified location. The upper left
  231. // corner of the bitmap is rendered at the specified location.
  232. // Parameters are specified relative to current canvas scale not in pixels.
  233. // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1.
  234. void DrawImageInt(const ImageSkia&, int x, int y);
  235. // Helper for DrawImageInt(..., flags) that constructs a temporary flags and
  236. // calls flags.setAlpha(alpha).
  237. void DrawImageInt(const ImageSkia&, int x, int y, uint8_t alpha);
  238. // Draws an image with the origin at the specified location, using the
  239. // specified flags. The upper left corner of the bitmap is rendered at the
  240. // specified location.
  241. // Parameters are specified relative to current canvas scale not in pixels.
  242. // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
  243. void DrawImageInt(const ImageSkia& image,
  244. int x,
  245. int y,
  246. const cc::PaintFlags& flags);
  247. // Draws a portion of an image in the specified location. The src parameters
  248. // correspond to the region of the bitmap to draw in the region defined
  249. // by the dest coordinates.
  250. //
  251. // If the width or height of the source differs from that of the destination,
  252. // the image will be scaled. When scaling down, a mipmap will be generated.
  253. // Set |filter| to use filtering for images, otherwise the nearest-neighbor
  254. // algorithm is used for resampling.
  255. //
  256. // An optional custom cc::PaintFlags can be provided.
  257. // Parameters are specified relative to current canvas scale not in pixels.
  258. // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
  259. void DrawImageInt(const ImageSkia& image,
  260. int src_x,
  261. int src_y,
  262. int src_w,
  263. int src_h,
  264. int dest_x,
  265. int dest_y,
  266. int dest_w,
  267. int dest_h,
  268. bool filter);
  269. void DrawImageInt(const ImageSkia& image,
  270. int src_x,
  271. int src_y,
  272. int src_w,
  273. int src_h,
  274. int dest_x,
  275. int dest_y,
  276. int dest_w,
  277. int dest_h,
  278. bool filter,
  279. const cc::PaintFlags& flags);
  280. // Same as the DrawImageInt functions above. Difference being this does not
  281. // do any scaling, i.e. it does not scale the output by the device scale
  282. // factor (the internal image_scale_). It takes an ImageSkiaRep instead of
  283. // an ImageSkia as the caller chooses the exact scale/pixel representation to
  284. // use, which will not be scaled while drawing it into the canvas.
  285. void DrawImageIntInPixel(const ImageSkiaRep& image_rep,
  286. int dest_x,
  287. int dest_y,
  288. int dest_w,
  289. int dest_h,
  290. bool filter,
  291. const cc::PaintFlags& flags);
  292. // Draws an |image| with the top left corner at |x| and |y|, clipped to
  293. // |path|.
  294. // Parameters are specified relative to current canvas scale not in pixels.
  295. // Thus, x is 2 pixels if canvas scale = 2 & |x| = 1.
  296. void DrawImageInPath(const ImageSkia& image,
  297. int x,
  298. int y,
  299. const SkPath& path,
  300. const cc::PaintFlags& flags);
  301. // Draws the frame of the |skottie| animation specified by the normalized time
  302. // instant t [0->first frame .. 1->last frame] onto the region corresponded by
  303. // |dst| in the canvas. |images| is a map from asset id to the corresponding
  304. // image to use when rendering this frame; it may be empty if this animation
  305. // frame does not contain any images in it.
  306. void DrawSkottie(scoped_refptr<cc::SkottieWrapper> skottie,
  307. const Rect& dst,
  308. float t,
  309. cc::SkottieFrameDataMap images,
  310. const cc::SkottieColorMap& color_map,
  311. cc::SkottieTextPropertyValueMap text_map);
  312. // Draws text with the specified color, fonts and location. The text is
  313. // aligned to the left, vertically centered, clipped to the region. If the
  314. // text is too big, it is truncated and '...' is added to the end.
  315. void DrawStringRect(const std::u16string& text,
  316. const FontList& font_list,
  317. SkColor color,
  318. const Rect& display_rect);
  319. // Draws text with the specified color, fonts and location. The last argument
  320. // specifies flags for how the text should be rendered. It can be one of
  321. // TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT or TEXT_ALIGN_LEFT.
  322. void DrawStringRectWithFlags(const std::u16string& text,
  323. const FontList& font_list,
  324. SkColor color,
  325. const Rect& display_rect,
  326. int flags);
  327. // Draws a |rect| in the specified region with the specified |color|. The
  328. // width of the stroke is |thickness| dip, but the actual pixel width will be
  329. // floored to ensure an integral value.
  330. void DrawSolidFocusRect(RectF rect, SkColor color, int thickness);
  331. // Tiles the image in the specified region.
  332. // Parameters are specified relative to current canvas scale not in pixels.
  333. // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
  334. void TileImageInt(const ImageSkia& image,
  335. int x,
  336. int y,
  337. int w,
  338. int h);
  339. void TileImageInt(const ImageSkia& image,
  340. int src_x,
  341. int src_y,
  342. int dest_x,
  343. int dest_y,
  344. int w,
  345. int h,
  346. float tile_scale = 1.0f,
  347. SkTileMode tile_mode_x = SkTileMode::kRepeat,
  348. SkTileMode tile_mode_y = SkTileMode::kRepeat,
  349. cc::PaintFlags* flags = nullptr);
  350. // Helper for TileImageInt(). Initializes |flags| for tiling |image| with the
  351. // given parameters. Returns false if the provided image does not have a
  352. // representation for the current scale.
  353. bool InitPaintFlagsForTiling(const ImageSkia& image,
  354. int src_x,
  355. int src_y,
  356. float tile_scale_x,
  357. float tile_scale_y,
  358. int dest_x,
  359. int dest_y,
  360. SkTileMode tile_mode_x,
  361. SkTileMode tile_mode_y,
  362. cc::PaintFlags* flags);
  363. // Apply transformation on the canvas.
  364. void Transform(const Transform& transform);
  365. // Note that writing to this bitmap will modify pixels stored in this canvas.
  366. SkBitmap GetBitmap() const;
  367. // TODO(enne): rename sk_canvas members and interface.
  368. cc::PaintCanvas* sk_canvas() { return canvas_; }
  369. float image_scale() const { return image_scale_; }
  370. private:
  371. // Tests whether the provided rectangle intersects the current clip rect.
  372. bool IntersectsClipRect(const SkRect& rect);
  373. // Helper for the DrawImageInt functions declared above. The
  374. // |remove_image_scale| parameter indicates if the scale of the |image_rep|
  375. // should be removed when drawing the image, to avoid double-scaling it.
  376. void DrawImageIntHelper(const ImageSkiaRep& image_rep,
  377. int src_x,
  378. int src_y,
  379. int src_w,
  380. int src_h,
  381. int dest_x,
  382. int dest_y,
  383. int dest_w,
  384. int dest_h,
  385. bool filter,
  386. const cc::PaintFlags& flags,
  387. bool remove_image_scale);
  388. cc::PaintCanvas* CreateOwnedCanvas(const Size& size, bool is_opaque);
  389. // The device scale factor at which drawing on this canvas occurs.
  390. // An additional scale can be applied via Canvas::Scale(). However,
  391. // Canvas::Scale() does not affect |image_scale_|.
  392. float image_scale_;
  393. // canvas_ is our active canvas object. Sometimes we are also the owner,
  394. // in which case bitmap_ and owned_canvas_ will be set. Other times we are
  395. // just borrowing someone else's canvas, in which case canvas_ will point
  396. // there but bitmap_ and owned_canvas_ will not exist.
  397. absl::optional<SkBitmap> bitmap_;
  398. absl::optional<cc::SkiaPaintCanvas> owned_canvas_;
  399. raw_ptr<cc::PaintCanvas> canvas_;
  400. };
  401. } // namespace gfx
  402. #endif // UI_GFX_CANVAS_H_