• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #ifndef UI_GFX_RENDER_TEXT_HARFBUZZ_H_
6 #define UI_GFX_RENDER_TEXT_HARFBUZZ_H_
7 
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"
14 
15 namespace base {
16 namespace i18n {
17 class BreakIterator;
18 }
19 }
20 
21 namespace gfx {
22 
23 namespace internal {
24 
25 struct GFX_EXPORT TextRunHarfBuzz {
26   TextRunHarfBuzz();
27   ~TextRunHarfBuzz();
28 
29   // Returns the index of the first glyph that corresponds to the character at
30   // |pos|.
31   size_t CharToGlyph(size_t pos) const;
32 
33   // Returns the corresponding glyph range of the given character range.
34   // |range| is in text-space (0 corresponds to |GetLayoutText()[0]|). Returned
35   // value is in run-space (0 corresponds to the first glyph in the run).
36   Range CharRangeToGlyphRange(const Range& range) const;
37 
38   // Returns the number of missing glyphs in the shaped text run.
39   size_t CountMissingGlyphs() const;
40 
41   // Writes the character and glyph ranges of the cluster containing |pos|.
42   void GetClusterAt(size_t pos, Range* chars, Range* glyphs) const;
43 
44   // Returns the grapheme bounds at |text_index|. Handles multi-grapheme glyphs.
45   Range GetGraphemeBounds(base::i18n::BreakIterator* grapheme_iterator,
46                           size_t text_index);
47 
48   // Returns whether the given shaped run contains any missing glyphs.
49   bool HasMissingGlyphs() const;
50 
51   float width;
52   float preceding_run_widths;
53   Range range;
54   bool is_rtl;
55   UBiDiLevel level;
56   UScriptCode script;
57 
58   scoped_ptr<uint16[]> glyphs;
59   scoped_ptr<SkPoint[]> positions;
60   std::vector<uint32> glyph_to_char;
61   size_t glyph_count;
62 
63   skia::RefPtr<SkTypeface> skia_face;
64   FontRenderParams render_params;
65   int font_size;
66   int font_style;
67   bool strike;
68   bool diagonal_strike;
69   bool underline;
70 
71  private:
72   DISALLOW_COPY_AND_ASSIGN(TextRunHarfBuzz);
73 };
74 
75 }  // namespace internal
76 
77 class GFX_EXPORT RenderTextHarfBuzz : public RenderText {
78  public:
79   RenderTextHarfBuzz();
80   virtual ~RenderTextHarfBuzz();
81 
82   // Overridden from RenderText.
83   virtual Size GetStringSize() OVERRIDE;
84   virtual SizeF GetStringSizeF() OVERRIDE;
85   virtual SelectionModel FindCursorPosition(const Point& point) OVERRIDE;
86   virtual std::vector<FontSpan> GetFontSpansForTesting() OVERRIDE;
87   virtual Range GetGlyphBounds(size_t index) OVERRIDE;
88 
89  protected:
90   // Overridden from RenderText.
91   virtual int GetLayoutTextBaseline() OVERRIDE;
92   virtual SelectionModel AdjacentCharSelectionModel(
93       const SelectionModel& selection,
94       VisualCursorDirection direction) OVERRIDE;
95   virtual SelectionModel AdjacentWordSelectionModel(
96       const SelectionModel& selection,
97       VisualCursorDirection direction) OVERRIDE;
98   virtual std::vector<Rect> GetSubstringBounds(const Range& range) OVERRIDE;
99   virtual size_t TextIndexToLayoutIndex(size_t index) const OVERRIDE;
100   virtual size_t LayoutIndexToTextIndex(size_t index) const OVERRIDE;
101   virtual bool IsValidCursorIndex(size_t index) OVERRIDE;
102   virtual void ResetLayout() OVERRIDE;
103   virtual void EnsureLayout() OVERRIDE;
104   virtual void DrawVisualText(Canvas* canvas) OVERRIDE;
105 
106  private:
107   friend class RenderTextTest;
108   FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_RunDirection);
109   FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_BreakRunsByUnicodeBlocks);
110   FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_SubglyphGraphemeCases);
111   FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_SubglyphGraphemePartition);
112   FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_NonExistentFont);
113 
114   // Return the run index that contains the argument; or the length of the
115   // |runs_| vector if argument exceeds the text length or width.
116   size_t GetRunContainingCaret(const SelectionModel& caret) const;
117   size_t GetRunContainingXCoord(int x, int* offset) const;
118 
119   // Given a |run|, returns the SelectionModel that contains the logical first
120   // or last caret position inside (not at a boundary of) the run.
121   // The returned value represents a cursor/caret position without a selection.
122   SelectionModel FirstSelectionModelInsideRun(
123       const internal::TextRunHarfBuzz* run);
124   SelectionModel LastSelectionModelInsideRun(
125       const internal::TextRunHarfBuzz* run);
126 
127   // Break the text into logical runs and populate the visual <-> logical maps.
128   void ItemizeText();
129 
130   // Shape the glyphs needed for the text |run|.
131   void ShapeRun(internal::TextRunHarfBuzz* run);
132   bool ShapeRunWithFont(internal::TextRunHarfBuzz* run,
133                         const std::string& font);
134 
135   // Text runs in logical order.
136   ScopedVector<internal::TextRunHarfBuzz> runs_;
137 
138   // Maps visual run indices to logical run indices and vice versa.
139   std::vector<int32_t> visual_to_logical_;
140   std::vector<int32_t> logical_to_visual_;
141 
142   bool needs_layout_;
143 
144   // ICU grapheme iterator for the layout text. Valid when |!needs_layout_|. Can
145   // be NULL in case of an error.
146   scoped_ptr<base::i18n::BreakIterator> grapheme_iterator_;
147 
148   DISALLOW_COPY_AND_ASSIGN(RenderTextHarfBuzz);
149 };
150 
151 }  // namespace gfx
152 
153 #endif  // UI_GFX_RENDER_TEXT_HARFBUZZ_H_
154