render_text_harfbuzz.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Copyright 2014 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_RENDER_TEXT_HARFBUZZ_H_
  5. #define UI_GFX_RENDER_TEXT_HARFBUZZ_H_
  6. #include <hb.h>
  7. #include <stddef.h>
  8. #include <stdint.h>
  9. #include <limits>
  10. #include <memory>
  11. #include <string>
  12. #include <unordered_map>
  13. #include <utility>
  14. #include <vector>
  15. #include "third_party/icu/source/common/unicode/ubidi.h"
  16. #include "third_party/icu/source/common/unicode/uscript.h"
  17. #include "ui/gfx/render_text.h"
  18. namespace gfx {
  19. class Range;
  20. class RangeF;
  21. class RenderTextHarfBuzz;
  22. namespace internal {
  23. struct GFX_EXPORT TextRunHarfBuzz {
  24. // Construct the run with |template_font| since determining the details of a
  25. // default-constructed gfx::Font is expensive, but it will always be replaced.
  26. explicit TextRunHarfBuzz(const Font& template_font);
  27. TextRunHarfBuzz(const TextRunHarfBuzz&) = delete;
  28. TextRunHarfBuzz& operator=(const TextRunHarfBuzz&) = delete;
  29. ~TextRunHarfBuzz();
  30. // Returns the corresponding glyph range of the given character range.
  31. // |range| is in text-space (0 corresponds to |GetDisplayText()[0]|). Returned
  32. // value is in run-space (0 corresponds to the first glyph in the run).
  33. Range CharRangeToGlyphRange(const Range& range) const;
  34. // Returns the number of missing glyphs in the shaped text run.
  35. size_t CountMissingGlyphs() const;
  36. // Writes the character and glyph ranges of the cluster containing |pos|.
  37. void GetClusterAt(size_t pos, Range* chars, Range* glyphs) const;
  38. // Returns the grapheme bounds at |text_index|. Handles multi-grapheme glyphs.
  39. // Returned value is the horizontal pixel span in text-space (assumes all runs
  40. // are on the same line). The returned range is never reversed.
  41. RangeF GetGraphemeBounds(RenderTextHarfBuzz* render_text,
  42. size_t text_index) const;
  43. // Returns the horizontal span of the given |char_range| handling grapheme
  44. // boundaries within glyphs. This is a wrapper around one or more calls to
  45. // GetGraphemeBounds(), returning a range in the same coordinate space.
  46. RangeF GetGraphemeSpanForCharRange(RenderTextHarfBuzz* render_text,
  47. const Range& char_range) const;
  48. // Returns the glyph width for the given character range. |char_range| is in
  49. // text-space (0 corresponds to |GetDisplayText()[0]|).
  50. SkScalar GetGlyphWidthForCharRange(const Range& char_range) const;
  51. // Font parameters that may be common to multiple text runs within a text run
  52. // list.
  53. struct GFX_EXPORT FontParams {
  54. // The default constructor for Font is expensive, so always require that a
  55. // Font be provided.
  56. explicit FontParams(const Font& template_font);
  57. ~FontParams();
  58. FontParams(const FontParams& other);
  59. FontParams& operator=(const FontParams& other);
  60. bool operator==(const FontParams& other) const;
  61. // Populates |render_params|, |font_size| and |baseline_offset| based on
  62. // |font|.
  63. void ComputeRenderParamsFontSizeAndBaselineOffset();
  64. // Populates |font|, |skia_face|, and |render_params|. Returns false if
  65. // |skia_face| is nullptr. Takes |font|'s family name and rematches this
  66. // family and the run's weight and style properties to find a new font.
  67. bool SetRenderParamsRematchFont(const Font& font,
  68. const FontRenderParams& render_params);
  69. // Populates |font|, |skia_face|, and |render_params|. Returns false if
  70. // |skia_face| is nullptr. Does not perform rematching but extracts an
  71. // SkTypeface from the underlying PlatformFont of font. Use this method when
  72. // configuring the |TextRunHarfBuzz| for shaping with fallback fonts, where
  73. // it is important to keep the underlying font handle of platform font and
  74. // not perform rematching as in |SetRenderParamsRematchFont|.
  75. bool SetRenderParamsOverrideSkiaFaceFromFont(
  76. const Font& font,
  77. const FontRenderParams& render_params);
  78. struct Hash {
  79. size_t operator()(const FontParams& key) const;
  80. };
  81. Font font;
  82. sk_sp<SkTypeface> skia_face;
  83. FontRenderParams render_params;
  84. Font::Weight weight = Font::Weight::NORMAL;
  85. int font_size = 0;
  86. int baseline_offset = 0;
  87. int baseline_type = 0;
  88. bool italic = false;
  89. bool strike = false;
  90. bool underline = false;
  91. bool heavy_underline = false;
  92. bool is_rtl = false;
  93. UBiDiLevel level = 0;
  94. UScriptCode script = USCRIPT_INVALID_CODE;
  95. };
  96. // Parameters that are set by ShapeRunWithFont.
  97. struct GFX_EXPORT ShapeOutput {
  98. ShapeOutput();
  99. ~ShapeOutput();
  100. ShapeOutput(const ShapeOutput& other);
  101. ShapeOutput& operator=(const ShapeOutput& other);
  102. ShapeOutput(ShapeOutput&& other);
  103. ShapeOutput& operator=(ShapeOutput&& other);
  104. float width = 0.0;
  105. std::vector<uint16_t> glyphs;
  106. std::vector<SkPoint> positions;
  107. // Note that in the context of TextRunHarfBuzz, |glyph_to_char| is indexed
  108. // based off of the full string (so it is in the same domain as
  109. // TextRunHarfBuzz::range).
  110. std::vector<uint32_t> glyph_to_char;
  111. size_t glyph_count = 0;
  112. size_t missing_glyph_count = std::numeric_limits<size_t>::max();
  113. };
  114. // If |new_shape.missing_glyph_count| is less than that of |shape|, set
  115. // |font_params| and |shape| to the specified values.
  116. void UpdateFontParamsAndShape(const FontParams& new_font_params,
  117. const ShapeOutput& new_shape);
  118. Range range;
  119. FontParams font_params;
  120. ShapeOutput shape;
  121. float preceding_run_widths = 0.0;
  122. };
  123. // Manages the list of TextRunHarfBuzz and its logical <-> visual index mapping.
  124. class TextRunList {
  125. public:
  126. TextRunList();
  127. TextRunList(const TextRunList&) = delete;
  128. TextRunList& operator=(const TextRunList&) = delete;
  129. ~TextRunList();
  130. size_t size() const { return runs_.size(); }
  131. // Converts the index between logical and visual index.
  132. size_t visual_to_logical(size_t index) const {
  133. return visual_to_logical_[index];
  134. }
  135. size_t logical_to_visual(size_t index) const {
  136. return logical_to_visual_[index];
  137. }
  138. const std::vector<std::unique_ptr<TextRunHarfBuzz>>& runs() const {
  139. return runs_;
  140. }
  141. // Adds the new |run| to the run list.
  142. void Add(std::unique_ptr<TextRunHarfBuzz> run) {
  143. runs_.push_back(std::move(run));
  144. }
  145. // Reset the run list.
  146. void Reset();
  147. // Initialize the index mapping.
  148. void InitIndexMap();
  149. // Precomputes the offsets for all runs.
  150. void ComputePrecedingRunWidths();
  151. // Get the total width of runs, as if they were shown on one line.
  152. // Do not use this when multiline is enabled.
  153. float width() const { return width_; }
  154. // Get the run index applicable to |position| (at or preceeding |position|).
  155. size_t GetRunIndexAt(size_t position) const;
  156. private:
  157. // Text runs in logical order.
  158. std::vector<std::unique_ptr<TextRunHarfBuzz>> runs_;
  159. // Maps visual run indices to logical run indices and vice versa.
  160. std::vector<int32_t> visual_to_logical_;
  161. std::vector<int32_t> logical_to_visual_;
  162. float width_;
  163. };
  164. } // namespace internal
  165. class GFX_EXPORT RenderTextHarfBuzz : public RenderText {
  166. public:
  167. RenderTextHarfBuzz();
  168. RenderTextHarfBuzz(const RenderTextHarfBuzz&) = delete;
  169. RenderTextHarfBuzz& operator=(const RenderTextHarfBuzz&) = delete;
  170. ~RenderTextHarfBuzz() override;
  171. // RenderText:
  172. const std::u16string& GetDisplayText() override;
  173. SizeF GetStringSizeF() override;
  174. SizeF GetLineSizeF(const SelectionModel& caret) override;
  175. std::vector<Rect> GetSubstringBounds(const Range& range) override;
  176. RangeF GetCursorSpan(const Range& text_range) override;
  177. size_t GetLineContainingCaret(const SelectionModel& caret) override;
  178. protected:
  179. // RenderText:
  180. SelectionModel AdjacentCharSelectionModel(
  181. const SelectionModel& selection,
  182. VisualCursorDirection direction) override;
  183. SelectionModel AdjacentWordSelectionModel(
  184. const SelectionModel& selection,
  185. VisualCursorDirection direction) override;
  186. SelectionModel AdjacentLineSelectionModel(
  187. const SelectionModel& selection,
  188. VisualCursorDirection direction) override;
  189. void OnLayoutTextAttributeChanged(bool text_changed) override;
  190. void OnDisplayTextAttributeChanged() override;
  191. void EnsureLayout() override;
  192. void DrawVisualText(internal::SkiaTextRenderer* renderer,
  193. const std::vector<Range>& selections) override;
  194. private:
  195. friend class test::RenderTextTestApi;
  196. friend class RenderTextTest;
  197. // Return the run index that contains the argument; or the length of the
  198. // |runs_| vector if argument exceeds the text length or width.
  199. size_t GetRunContainingCaret(const SelectionModel& caret);
  200. // Given a |run|, returns the SelectionModel that contains the logical first
  201. // or last caret position inside (not at a boundary of) the run.
  202. // The returned value represents a cursor/caret position without a selection.
  203. SelectionModel FirstSelectionModelInsideRun(
  204. const internal::TextRunHarfBuzz* run);
  205. SelectionModel LastSelectionModelInsideRun(
  206. const internal::TextRunHarfBuzz* run);
  207. using CommonizedRunsMap =
  208. std::unordered_map<internal::TextRunHarfBuzz::FontParams,
  209. std::vector<internal::TextRunHarfBuzz*>,
  210. internal::TextRunHarfBuzz::FontParams::Hash>;
  211. // Break the text into logical runs in |out_run_list|. Populate
  212. // |out_commonized_run_map| such that each run is present in the vector
  213. // corresponding to its FontParams.
  214. void ItemizeTextToRuns(const std::u16string& string,
  215. internal::TextRunList* out_run_list,
  216. CommonizedRunsMap* out_commonized_run_map);
  217. // Shape the glyphs needed for each run in |runs| within |text|. This method
  218. // will apply a number of fonts to |base_font_params| and assign to each
  219. // run's FontParams and ShapeOutput the parameters and resulting shape that
  220. // had the smallest number of missing glyphs.
  221. void ShapeRuns(const std::u16string& text,
  222. const internal::TextRunHarfBuzz::FontParams& base_font_params,
  223. std::vector<internal::TextRunHarfBuzz*> runs);
  224. // Shape the glyphs for |in_out_runs| within |text| using the parameters
  225. // specified by |font_params|. If, for any run in |*in_out_runs|, the
  226. // resulting shaping has fewer missing glyphs than the existing shape, then
  227. // write |font_params| and the resulting ShapeOutput to that run. Remove all
  228. // runs with no missing glyphs from |in_out_runs| (the caller, ShapeRuns, will
  229. // terminate when no runs with missing glyphs remain).
  230. void ShapeRunsWithFont(
  231. const std::u16string& text,
  232. const internal::TextRunHarfBuzz::FontParams& font_params,
  233. std::vector<internal::TextRunHarfBuzz*>* in_out_runs);
  234. // Itemize |text| into runs in |out_run_list|, shape the runs, and populate
  235. // |out_run_list|'s visual <-> logical maps.
  236. void ItemizeAndShapeText(const std::u16string& text,
  237. internal::TextRunList* out_run_list);
  238. // Makes sure that text runs for layout text are shaped.
  239. void EnsureLayoutRunList();
  240. // Returns whether the display range is still a valid range after the eliding
  241. // pass.
  242. bool IsValidDisplayRange(Range display_range);
  243. // RenderText:
  244. internal::TextRunList* GetRunList() override;
  245. const internal::TextRunList* GetRunList() const override;
  246. bool GetDecoratedTextForRange(const Range& range,
  247. DecoratedText* decorated_text) override;
  248. // Text run list for |layout_text_| and |display_text_|.
  249. // |display_run_list_| is created only when the text is elided.
  250. internal::TextRunList layout_run_list_;
  251. std::unique_ptr<internal::TextRunList> display_run_list_;
  252. bool update_layout_run_list_ : 1;
  253. bool update_display_run_list_ : 1;
  254. bool update_display_text_ : 1;
  255. // The device scale factor for which the text was laid out.
  256. float device_scale_factor_ = 1.0f;
  257. // The total size of the layouted text.
  258. SizeF total_size_;
  259. // The process application locale used to configure text rendering.
  260. std::string locale_;
  261. };
  262. } // namespace gfx
  263. #endif // UI_GFX_RENDER_TEXT_HARFBUZZ_H_