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.
5 #ifndef UI_GFX_RENDER_TEXT_HARFBUZZ_H_
6 #define UI_GFX_RENDER_TEXT_HARFBUZZ_H_
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/scoped_vector.h"
10 #include "third_party/harfbuzz-ng/src/hb.h"
11 #include "third_party/icu/source/common/unicode/ubidi.h"
12 #include "third_party/icu/source/common/unicode/uscript.h"
13 #include "ui/gfx/render_text.h"
28 struct GFX_EXPORT TextRunHarfBuzz
{
32 // Returns the index of the first glyph that corresponds to the character at
34 size_t CharToGlyph(size_t pos
) const;
36 // Returns the corresponding glyph range of the given character range.
37 // |range| is in text-space (0 corresponds to |GetDisplayText()[0]|). Returned
38 // value is in run-space (0 corresponds to the first glyph in the run).
39 Range
CharRangeToGlyphRange(const Range
& range
) const;
41 // Returns the number of missing glyphs in the shaped text run.
42 size_t CountMissingGlyphs() const;
44 // Writes the character and glyph ranges of the cluster containing |pos|.
45 void GetClusterAt(size_t pos
, Range
* chars
, Range
* glyphs
) const;
47 // Returns the grapheme bounds at |text_index|. Handles multi-grapheme glyphs.
48 RangeF
GetGraphemeBounds(base::i18n::BreakIterator
* grapheme_iterator
,
51 // Returns whether the given shaped run contains any missing glyphs.
52 bool HasMissingGlyphs() const;
54 // Returns the glyph width for the given character range. |char_range| is in
55 // text-space (0 corresponds to |GetDisplayText()[0]|).
56 SkScalar
GetGlyphWidthForCharRange(const Range
& char_range
) const;
59 float preceding_run_widths
;
65 scoped_ptr
<uint16
[]> glyphs
;
66 scoped_ptr
<SkPoint
[]> positions
;
67 std::vector
<uint32
> glyph_to_char
;
71 skia::RefPtr
<SkTypeface
> skia_face
;
72 FontRenderParams render_params
;
82 DISALLOW_COPY_AND_ASSIGN(TextRunHarfBuzz
);
85 // Manages the list of TextRunHarfBuzz and its logical <-> visual index mapping.
91 size_t size() const { return runs_
.size(); }
93 // Converts the index between logical and visual index.
94 size_t visual_to_logical(size_t index
) const {
95 return visual_to_logical_
[index
];
97 size_t logical_to_visual(size_t index
) const {
98 return logical_to_visual_
[index
];
101 const ScopedVector
<TextRunHarfBuzz
>& runs() const { return runs_
; }
103 // Adds the new |run| to the run list.
104 void add(TextRunHarfBuzz
* run
) { runs_
.push_back(run
); }
106 // Reset the run list.
109 // Initialize the index mapping.
112 // Precomputes the offsets for all runs.
113 void ComputePrecedingRunWidths();
115 // Get the total width of runs, as if they were shown on one line.
116 // Do not use this when multiline is enabled.
117 float width() const { return width_
; }
119 // Get the run index applicable to |position| (at or preceeding |position|).
120 size_t GetRunIndexAt(size_t position
) const;
123 // Text runs in logical order.
124 ScopedVector
<TextRunHarfBuzz
> runs_
;
126 // Maps visual run indices to logical run indices and vice versa.
127 std::vector
<int32_t> visual_to_logical_
;
128 std::vector
<int32_t> logical_to_visual_
;
132 DISALLOW_COPY_AND_ASSIGN(TextRunList
);
135 } // namespace internal
137 class GFX_EXPORT RenderTextHarfBuzz
: public RenderText
{
139 RenderTextHarfBuzz();
140 ~RenderTextHarfBuzz() override
;
143 scoped_ptr
<RenderText
> CreateInstanceOfSameType() const override
;
144 bool MultilineSupported() const override
;
145 const base::string16
& GetDisplayText() override
;
146 Size
GetStringSize() override
;
147 SizeF
GetStringSizeF() override
;
148 SelectionModel
FindCursorPosition(const Point
& point
) override
;
149 std::vector
<FontSpan
> GetFontSpansForTesting() override
;
150 Range
GetGlyphBounds(size_t index
) override
;
154 int GetDisplayTextBaseline() override
;
155 SelectionModel
AdjacentCharSelectionModel(
156 const SelectionModel
& selection
,
157 VisualCursorDirection direction
) override
;
158 SelectionModel
AdjacentWordSelectionModel(
159 const SelectionModel
& selection
,
160 VisualCursorDirection direction
) override
;
161 std::vector
<Rect
> GetSubstringBounds(const Range
& range
) override
;
162 size_t TextIndexToDisplayIndex(size_t index
) override
;
163 size_t DisplayIndexToTextIndex(size_t index
) override
;
164 bool IsValidCursorIndex(size_t index
) override
;
165 void OnLayoutTextAttributeChanged(bool text_changed
) override
;
166 void OnDisplayTextAttributeChanged() override
;
167 void EnsureLayout() override
;
168 void DrawVisualText(Canvas
* canvas
) override
;
171 friend class RenderTextTest
;
172 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_HorizontalAlignment
);
173 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_NormalWidth
);
174 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_WordWrapBehavior
);
175 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_RunDirection
);
176 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_HorizontalPositions
);
177 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
,
178 HarfBuzz_TextPositionWithFractionalSize
);
179 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_BreakRunsByUnicodeBlocks
);
180 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_BreakRunsByEmoji
);
181 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_SubglyphGraphemeCases
);
182 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_SubglyphGraphemePartition
);
183 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_NonExistentFont
);
184 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_UniscribeFallback
);
185 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_UnicodeFallback
);
186 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_LineBreakerBehavior
);
187 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
,
188 Multiline_SurrogatePairsOrCombiningChars
);
189 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_ZeroWidthChars
);
191 // Specify the width of a glyph for test. The width of glyphs is very
192 // platform-dependent and environment-dependent. Otherwise multiline test
193 // will become really flaky.
194 void set_glyph_width_for_test(float test_width
) {
195 glyph_width_for_test_
= test_width
;
198 // The actual implementation of the text drawing.
199 void DrawVisualTextInternal(internal::SkiaTextRenderer
* renderer
);
201 // Return the run index that contains the argument; or the length of the
202 // |runs_| vector if argument exceeds the text length or width.
203 size_t GetRunContainingCaret(const SelectionModel
& caret
);
204 size_t GetRunContainingXCoord(float x
, float* offset
) const;
206 // Given a |run|, returns the SelectionModel that contains the logical first
207 // or last caret position inside (not at a boundary of) the run.
208 // The returned value represents a cursor/caret position without a selection.
209 SelectionModel
FirstSelectionModelInsideRun(
210 const internal::TextRunHarfBuzz
* run
);
211 SelectionModel
LastSelectionModelInsideRun(
212 const internal::TextRunHarfBuzz
* run
);
214 // Break the text into logical runs and populate the visual <-> logical maps
215 // into |run_list_out|.
216 void ItemizeTextToRuns(const base::string16
& string
,
217 internal::TextRunList
* run_list_out
);
219 // Helper method for ShapeRun() that calls ShapeRunWithFont() with |text|,
220 // |run|, |family|, and |render_params|, returning true if the family provides
221 // all the glyphs needed for |run|, and false otherwise. Additionally updates
222 // |best_family|, |best_render_params|, and |best_missing_glyphs| if |family|
223 // has fewer than |best_missing_glyphs| missing glyphs.
224 bool CompareFamily(const base::string16
& text
,
225 const std::string
& family
,
226 const gfx::FontRenderParams
& render_params
,
227 internal::TextRunHarfBuzz
* run
,
228 std::string
* best_family
,
229 gfx::FontRenderParams
* best_render_params
,
230 size_t* best_missing_glyphs
);
232 // Shape the glyphs of all runs in |run_list| using |text|.
233 void ShapeRunList(const base::string16
& text
,
234 internal::TextRunList
* run_list
);
236 // Shape the glyphs needed for the |run| within the |text|.
237 void ShapeRun(const base::string16
& text
,
238 internal::TextRunHarfBuzz
* run
);
239 bool ShapeRunWithFont(const base::string16
& text
,
240 const std::string
& font_family
,
241 const FontRenderParams
& params
,
242 internal::TextRunHarfBuzz
* run
);
244 // Makes sure that text runs for layout text are shaped.
245 void EnsureLayoutRunList();
247 // ICU grapheme iterator for the layout text. Can be NULL in case of an error.
248 base::i18n::BreakIterator
* GetGraphemeIterator();
250 // Returns the current run list, |display_run_list_| if the text is
251 // elided, or |layout_run_list_| otherwise.
252 internal::TextRunList
* GetRunList();
253 const internal::TextRunList
* GetRunList() const;
255 // Text run list for |layout_text_| and |display_text_|.
256 // |display_run_list_| is created only when the text is elided.
257 internal::TextRunList layout_run_list_
;
258 scoped_ptr
<internal::TextRunList
> display_run_list_
;
260 bool update_layout_run_list_
: 1;
261 bool update_display_run_list_
: 1;
262 bool update_grapheme_iterator_
: 1;
263 bool update_display_text_
: 1;
265 // ICU grapheme iterator for the layout text. Use GetGraphemeIterator()
266 // to access the iterator.
267 scoped_ptr
<base::i18n::BreakIterator
> grapheme_iterator_
;
269 // The total size of the layouted text.
272 // Fixed width of glyphs. This should only be set in test environments.
273 float glyph_width_for_test_
;
275 DISALLOW_COPY_AND_ASSIGN(RenderTextHarfBuzz
);
280 #endif // UI_GFX_RENDER_TEXT_HARFBUZZ_H_