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 // Applies std::round to the start and end values of the given RangeF.
29 GFX_EXPORT Range
RoundRangeF(const RangeF
& range_f
);
31 struct GFX_EXPORT TextRunHarfBuzz
{
35 // Returns the index of the first glyph that corresponds to the character at
37 size_t CharToGlyph(size_t pos
) const;
39 // Returns the corresponding glyph range of the given character range.
40 // |range| is in text-space (0 corresponds to |GetDisplayText()[0]|). Returned
41 // value is in run-space (0 corresponds to the first glyph in the run).
42 Range
CharRangeToGlyphRange(const Range
& range
) const;
44 // Returns the number of missing glyphs in the shaped text run.
45 size_t CountMissingGlyphs() const;
47 // Writes the character and glyph ranges of the cluster containing |pos|.
48 void GetClusterAt(size_t pos
, Range
* chars
, Range
* glyphs
) const;
50 // Returns the grapheme bounds at |text_index|. Handles multi-grapheme glyphs.
51 RangeF
GetGraphemeBounds(base::i18n::BreakIterator
* grapheme_iterator
,
54 // Returns whether the given shaped run contains any missing glyphs.
55 bool HasMissingGlyphs() const;
58 float preceding_run_widths
;
64 scoped_ptr
<uint16
[]> glyphs
;
65 scoped_ptr
<SkPoint
[]> positions
;
66 std::vector
<uint32
> glyph_to_char
;
70 skia::RefPtr
<SkTypeface
> skia_face
;
71 FontRenderParams render_params
;
81 DISALLOW_COPY_AND_ASSIGN(TextRunHarfBuzz
);
84 // Manages the list of TextRunHarfBuzz and its logical <-> visual index mapping.
90 size_t size() const { return runs_
.size(); }
92 // Converts the index between logical and visual index.
93 size_t visual_to_logical(size_t index
) const {
94 return visual_to_logical_
[index
];
96 size_t logical_to_visual(size_t index
) const {
97 return logical_to_visual_
[index
];
100 const ScopedVector
<TextRunHarfBuzz
>& runs() const { return runs_
; }
102 // Adds the new |run| to the run list.
103 void add(TextRunHarfBuzz
* run
) { runs_
.push_back(run
); }
105 // Reset the run list.
108 // Initialize the index mapping.
111 // Precomputes the offsets for all runs.
112 void ComputePrecedingRunWidths();
114 // Get the total width of runs, as if they were shown on one line.
115 // Do not use this when multiline is enabled.
116 float width() const { return width_
; }
119 // Text runs in logical order.
120 ScopedVector
<TextRunHarfBuzz
> runs_
;
122 // Maps visual run indices to logical run indices and vice versa.
123 std::vector
<int32_t> visual_to_logical_
;
124 std::vector
<int32_t> logical_to_visual_
;
128 DISALLOW_COPY_AND_ASSIGN(TextRunList
);
131 } // namespace internal
133 class GFX_EXPORT RenderTextHarfBuzz
: public RenderText
{
135 RenderTextHarfBuzz();
136 ~RenderTextHarfBuzz() override
;
139 scoped_ptr
<RenderText
> CreateInstanceOfSameType() const override
;
140 bool MultilineSupported() const override
;
141 const base::string16
& GetDisplayText() override
;
142 Size
GetStringSize() override
;
143 SizeF
GetStringSizeF() override
;
144 SelectionModel
FindCursorPosition(const Point
& point
) override
;
145 std::vector
<FontSpan
> GetFontSpansForTesting() override
;
146 Range
GetGlyphBounds(size_t index
) override
;
150 int GetDisplayTextBaseline() override
;
151 SelectionModel
AdjacentCharSelectionModel(
152 const SelectionModel
& selection
,
153 VisualCursorDirection direction
) override
;
154 SelectionModel
AdjacentWordSelectionModel(
155 const SelectionModel
& selection
,
156 VisualCursorDirection direction
) override
;
157 std::vector
<Rect
> GetSubstringBounds(const Range
& range
) override
;
158 size_t TextIndexToDisplayIndex(size_t index
) override
;
159 size_t DisplayIndexToTextIndex(size_t index
) override
;
160 bool IsValidCursorIndex(size_t index
) override
;
161 void OnLayoutTextAttributeChanged(bool text_changed
) override
;
162 void OnDisplayTextAttributeChanged() override
;
163 void EnsureLayout() override
;
164 void DrawVisualText(Canvas
* canvas
) override
;
167 friend class RenderTextTest
;
168 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_HorizontalAlignment
);
169 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_NormalWidth
);
170 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, Multiline_WordWrapBehavior
);
171 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_RunDirection
);
172 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_HorizontalPositions
);
173 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
,
174 HarfBuzz_TextPositionWithFractionalSize
);
175 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_BreakRunsByUnicodeBlocks
);
176 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_BreakRunsByEmoji
);
177 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_SubglyphGraphemeCases
);
178 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_SubglyphGraphemePartition
);
179 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_NonExistentFont
);
180 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_UniscribeFallback
);
181 FRIEND_TEST_ALL_PREFIXES(RenderTextTest
, HarfBuzz_UnicodeFallback
);
183 // Specify the width of a glyph for test. The width of glyphs is very
184 // platform-dependent and environment-dependent. Otherwise multiline test
185 // will become really flaky.
186 void set_glyph_width_for_test(float test_width
) {
187 glyph_width_for_test_
= test_width
;
190 // The actual implementation of the text drawing.
191 void DrawVisualTextInternal(internal::SkiaTextRenderer
* renderer
);
193 // Return the run index that contains the argument; or the length of the
194 // |runs_| vector if argument exceeds the text length or width.
195 size_t GetRunContainingCaret(const SelectionModel
& caret
);
196 size_t GetRunContainingXCoord(float x
, float* offset
) const;
198 // Given a |run|, returns the SelectionModel that contains the logical first
199 // or last caret position inside (not at a boundary of) the run.
200 // The returned value represents a cursor/caret position without a selection.
201 SelectionModel
FirstSelectionModelInsideRun(
202 const internal::TextRunHarfBuzz
* run
);
203 SelectionModel
LastSelectionModelInsideRun(
204 const internal::TextRunHarfBuzz
* run
);
206 // Break the text into logical runs and populate the visual <-> logical maps
207 // into |run_list_out|.
208 void ItemizeTextToRuns(const base::string16
& string
,
209 internal::TextRunList
* run_list_out
);
211 // Helper method for ShapeRun() that calls ShapeRunWithFont() with |text|,
212 // |run|, |family|, and |render_params|, returning true if the family provides
213 // all the glyphs needed for |run|, and false otherwise. Additionally updates
214 // |best_family|, |best_render_params|, and |best_missing_glyphs| if |family|
215 // has fewer than |best_missing_glyphs| missing glyphs.
216 bool CompareFamily(const base::string16
& text
,
217 const std::string
& family
,
218 const gfx::FontRenderParams
& render_params
,
219 internal::TextRunHarfBuzz
* run
,
220 std::string
* best_family
,
221 gfx::FontRenderParams
* best_render_params
,
222 size_t* best_missing_glyphs
);
224 // Shape the glyphs of all runs in |run_list| using |text|.
225 void ShapeRunList(const base::string16
& text
,
226 internal::TextRunList
* run_list
);
228 // Shape the glyphs needed for the |run| within the |text|.
229 void ShapeRun(const base::string16
& text
,
230 internal::TextRunHarfBuzz
* run
);
231 bool ShapeRunWithFont(const base::string16
& text
,
232 const std::string
& font_family
,
233 const FontRenderParams
& params
,
234 internal::TextRunHarfBuzz
* run
);
236 // Makes sure that text runs for layout text are shaped.
237 void EnsureLayoutRunList();
239 // ICU grapheme iterator for the layout text. Can be NULL in case of an error.
240 base::i18n::BreakIterator
* GetGraphemeIterator();
242 // Returns the current run list, |display_run_list_| if the text is
243 // elided, or |layout_run_list_| otherwise.
244 internal::TextRunList
* GetRunList();
245 const internal::TextRunList
* GetRunList() const;
247 // Text run list for |layout_text_| and |display_text_|.
248 // |display_run_list_| is created only when the text is elided.
249 internal::TextRunList layout_run_list_
;
250 scoped_ptr
<internal::TextRunList
> display_run_list_
;
252 bool update_layout_run_list_
: 1;
253 bool update_display_run_list_
: 1;
254 bool update_grapheme_iterator_
: 1;
255 bool update_display_text_
: 1;
257 // ICU grapheme iterator for the layout text. Use GetGraphemeIterator()
258 // to access the iterator.
259 scoped_ptr
<base::i18n::BreakIterator
> grapheme_iterator_
;
261 // The total size of the layouted text.
264 // Fixed width of glyphs. This should only be set in test environments.
265 float glyph_width_for_test_
;
267 DISALLOW_COPY_AND_ASSIGN(RenderTextHarfBuzz
);
272 #endif // UI_GFX_RENDER_TEXT_HARFBUZZ_H_