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