1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/render_text_harfbuzz.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <limits>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <map>
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/i18n/bidi_line_iterator.h"
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/i18n/break_iterator.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/i18n/char_iterator.h"
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/lazy_instance.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/harfbuzz-ng/src/hb.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/icu/source/common/unicode/ubidi.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/skia/include/core/SkColor.h"
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "third_party/skia/include/core/SkTypeface.h"
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/canvas.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/font_fallback.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/gfx/font_render_params.h"
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/utf16_indexing.h"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/gfx/font_fallback_win.h"
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace gfx {
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Text length limit. Longer strings are slow and not fully tested.
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst size_t kMaxTextLength = 10000;
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The maximum number of scripts a Unicode character can belong to. This value
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// is arbitrarily chosen to be a good limit because it is unlikely for a single
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// character to belong to more scripts.
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kMaxScripts = 5;
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Maps from code points to glyph indices in a font.
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef std::map<uint32_t, uint16_t> GlyphCache;
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Font data provider for HarfBuzz using Skia. Copied from Blink.
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(ckocagil): Eliminate the duplication. http://crbug.com/368375
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct FontData {
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData(GlyphCache* glyph_cache) : glyph_cache_(glyph_cache) {}
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkPaint paint_;
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GlyphCache* glyph_cache_;
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value) {
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return SkScalarToFixed(value);
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Deletes the object at the given pointer after casting it to the given type.
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template<typename Type>
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DeleteByType(void* data) {
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Type* typed_data = reinterpret_cast<Type*>(data);
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delete typed_data;
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template<typename Type>
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void DeleteArrayByType(void* data) {
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Type* typed_data = reinterpret_cast<Type*>(data);
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  delete[] typed_data;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Outputs the |width| and |extents| of the glyph with index |codepoint| in
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |paint|'s font.
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void GetGlyphWidthAndExtents(SkPaint* paint,
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             hb_codepoint_t codepoint,
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             hb_position_t* width,
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                             hb_glyph_extents_t* extents) {
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LE(codepoint, 0xFFFFU);
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkScalar sk_width;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkRect sk_bounds;
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  uint16_t glyph = codepoint;
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  paint->getTextWidths(&glyph, sizeof(glyph), &sk_width, &sk_bounds);
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (width)
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *width = SkiaScalarToHarfBuzzPosition(sk_width);
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (extents) {
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Invert y-axis because Skia is y-grows-down but we set up HarfBuzz to be
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // y-grows-up.
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    extents->x_bearing = SkiaScalarToHarfBuzzPosition(sk_bounds.fLeft);
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    extents->y_bearing = SkiaScalarToHarfBuzzPosition(-sk_bounds.fTop);
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    extents->width = SkiaScalarToHarfBuzzPosition(sk_bounds.width());
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    extents->height = SkiaScalarToHarfBuzzPosition(-sk_bounds.height());
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Writes the |glyph| index for the given |unicode| code point. Returns whether
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// the glyph exists, i.e. it is not a missing glyph.
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_bool_t GetGlyph(hb_font_t* font,
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   void* data,
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   hb_codepoint_t unicode,
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   hb_codepoint_t variation_selector,
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   hb_codepoint_t* glyph,
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   void* user_data) {
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData* font_data = reinterpret_cast<FontData*>(data);
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GlyphCache* cache = font_data->glyph_cache_;
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool exists = cache->count(unicode) != 0;
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!exists) {
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SkPaint* paint = &font_data->paint_;
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &(*cache)[unicode]);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *glyph = (*cache)[unicode];
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return !!*glyph;
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns the horizontal advance value of the |glyph|.
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_position_t GetGlyphHorizontalAdvance(hb_font_t* font,
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        void* data,
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        hb_codepoint_t glyph,
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        void* user_data) {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData* font_data = reinterpret_cast<FontData*>(data);
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_position_t advance = 0;
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetGlyphWidthAndExtents(&font_data->paint_, glyph, &advance, 0);
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return advance;
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_bool_t GetGlyphHorizontalOrigin(hb_font_t* font,
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   void* data,
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   hb_codepoint_t glyph,
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   hb_position_t* x,
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   hb_position_t* y,
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   void* user_data) {
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Just return true, like the HarfBuzz-FreeType implementation.
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_position_t GetGlyphKerning(FontData* font_data,
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              hb_codepoint_t first_glyph,
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              hb_codepoint_t second_glyph) {
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkTypeface* typeface = font_data->paint_.getTypeface();
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const uint16_t glyphs[2] = { static_cast<uint16_t>(first_glyph),
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               static_cast<uint16_t>(second_glyph) };
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int32_t kerning_adjustments[1] = { 0 };
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments))
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkScalar size = font_data->paint_.getTextSize();
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return SkiaScalarToHarfBuzzPosition(
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SkScalarMulDiv(SkIntToScalar(kerning_adjustments[0]), size, upm));
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_position_t GetGlyphHorizontalKerning(hb_font_t* font,
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        void* data,
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        hb_codepoint_t left_glyph,
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        hb_codepoint_t right_glyph,
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                        void* user_data) {
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData* font_data = reinterpret_cast<FontData*>(data);
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (font_data->paint_.isVerticalText()) {
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // We don't support cross-stream kerning.
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return GetGlyphKerning(font_data, left_glyph, right_glyph);
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_position_t GetGlyphVerticalKerning(hb_font_t* font,
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      void* data,
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      hb_codepoint_t top_glyph,
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      hb_codepoint_t bottom_glyph,
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      void* user_data) {
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData* font_data = reinterpret_cast<FontData*>(data);
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!font_data->paint_.isVerticalText()) {
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // We don't support cross-stream kerning.
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return GetGlyphKerning(font_data, top_glyph, bottom_glyph);
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Writes the |extents| of |glyph|.
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_bool_t GetGlyphExtents(hb_font_t* font,
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          void* data,
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          hb_codepoint_t glyph,
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          hb_glyph_extents_t* extents,
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          void* user_data) {
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData* font_data = reinterpret_cast<FontData*>(data);
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GetGlyphWidthAndExtents(&font_data->paint_, glyph, 0, extents);
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class FontFuncs {
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FontFuncs() : font_funcs_(hb_font_funcs_create()) {
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    hb_font_funcs_set_glyph_func(font_funcs_, GetGlyph, 0, 0);
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hb_font_funcs_set_glyph_h_advance_func(
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        font_funcs_, GetGlyphHorizontalAdvance, 0, 0);
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hb_font_funcs_set_glyph_h_kerning_func(
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        font_funcs_, GetGlyphHorizontalKerning, 0, 0);
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hb_font_funcs_set_glyph_h_origin_func(
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        font_funcs_, GetGlyphHorizontalOrigin, 0, 0);
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hb_font_funcs_set_glyph_v_kerning_func(
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        font_funcs_, GetGlyphVerticalKerning, 0, 0);
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    hb_font_funcs_set_glyph_extents_func(
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        font_funcs_, GetGlyphExtents, 0, 0);
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    hb_font_funcs_make_immutable(font_funcs_);
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ~FontFuncs() {
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    hb_font_funcs_destroy(font_funcs_);
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  hb_font_funcs_t* get() { return font_funcs_; }
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  hb_font_funcs_t* font_funcs_;
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FontFuncs);
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)base::LazyInstance<FontFuncs>::Leaky g_font_funcs = LAZY_INSTANCE_INITIALIZER;
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns the raw data of the font table |tag|.
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)hb_blob_t* GetFontTable(hb_face_t* face, hb_tag_t tag, void* user_data) {
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkTypeface* typeface = reinterpret_cast<SkTypeface*>(user_data);
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const size_t table_size = typeface->getTableSize(tag);
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!table_size)
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<char[]> buffer(new char[table_size]);
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!buffer)
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t actual_size = typeface->getTableData(tag, 0, table_size, buffer.get());
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (table_size != actual_size)
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  char* buffer_raw = buffer.release();
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return hb_blob_create(buffer_raw, table_size, HB_MEMORY_MODE_WRITABLE,
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        buffer_raw, DeleteArrayByType<char>);
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UnrefSkTypeface(void* data) {
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkTypeface* skia_face = reinterpret_cast<SkTypeface*>(data);
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SkSafeUnref(skia_face);
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Wrapper class for a HarfBuzz face created from a given Skia face.
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class HarfBuzzFace {
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  HarfBuzzFace() : face_(NULL) {}
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ~HarfBuzzFace() {
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (face_)
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      hb_face_destroy(face_);
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void Init(SkTypeface* skia_face) {
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SkSafeRef(skia_face);
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    face_ = hb_face_create_for_tables(GetFontTable, skia_face, UnrefSkTypeface);
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK(face_);
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  hb_face_t* get() {
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return face_;
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  hb_face_t* face_;
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Creates a HarfBuzz font from the given Skia face and text size.
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccihb_font_t* CreateHarfBuzzFont(SkTypeface* skia_face,
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              int text_size,
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              const FontRenderParams& params,
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              bool background_is_transparent) {
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  typedef std::pair<HarfBuzzFace, GlyphCache> FaceCache;
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache?
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static std::map<SkFontID, FaceCache> face_caches;
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FaceCache* face_cache = &face_caches[skia_face->uniqueID()];
2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (face_cache->first.get() == NULL)
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    face_cache->first.Init(skia_face);
287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  hb_font_t* harfbuzz_font = hb_font_create(face_cache->first.get());
289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const int scale = SkScalarToFixed(text_size);
290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  hb_font_set_scale(harfbuzz_font, scale, scale);
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  FontData* hb_font_data = new FontData(&face_cache->second);
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_font_data->paint_.setTypeface(skia_face);
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_font_data->paint_.setTextSize(text_size);
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(ckocagil): Do we need to update these params later?
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  internal::ApplyRenderParams(params, background_is_transparent,
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                              &hb_font_data->paint_);
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  hb_font_set_funcs(harfbuzz_font, g_font_funcs.Get().get(), hb_font_data,
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    DeleteByType<FontData>);
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_font_make_immutable(harfbuzz_font);
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return harfbuzz_font;
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true if characters of |block_code| may trigger font fallback.
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsUnusualBlockCode(UBlockCode block_code) {
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return block_code == UBLOCK_GEOMETRIC_SHAPES ||
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         block_code == UBLOCK_MISCELLANEOUS_SYMBOLS;
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IsBracket(UChar32 character) {
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static const char kBrackets[] = { '(', ')', '{', '}', '<', '>', };
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static const char* kBracketsEnd = kBrackets + arraysize(kBrackets);
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return std::find(kBrackets, kBracketsEnd, character) != kBracketsEnd;
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns the boundary between a special and a regular character. Special
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// characters are brackets or characters that satisfy |IsUnusualBlockCode|.
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccisize_t FindRunBreakingCharacter(const base::string16& text,
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                size_t run_start,
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                size_t run_break) {
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const int32 run_length = static_cast<int32>(run_break - run_start);
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::i18n::UTF16CharIterator iter(text.c_str() + run_start, run_length);
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const UChar32 first_char = iter.get();
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const UBlockCode first_block = ublock_getCode(first_char);
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const bool first_block_unusual = IsUnusualBlockCode(first_block);
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const bool first_bracket = IsBracket(first_char);
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (iter.Advance() && iter.array_pos() < run_length) {
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const UChar32 current_char = iter.get();
3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const UBlockCode current_block = ublock_getCode(current_char);
3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const bool block_break = current_block != first_block &&
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        (first_block_unusual || IsUnusualBlockCode(current_block));
3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (block_break || first_bracket != IsBracket(current_char))
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return run_start + iter.array_pos();
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return run_break;
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// If the given scripts match, returns the one that isn't USCRIPT_COMMON or
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// USCRIPT_INHERITED, i.e. the more specific one. Otherwise returns
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// USCRIPT_INVALID_CODE.
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UScriptCode ScriptIntersect(UScriptCode first, UScriptCode second) {
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (first == second ||
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (second > USCRIPT_INVALID_CODE && second <= USCRIPT_INHERITED)) {
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return first;
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (first > USCRIPT_INVALID_CODE && first <= USCRIPT_INHERITED)
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return second;
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return USCRIPT_INVALID_CODE;
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Writes the script and the script extensions of the character with the
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Unicode |codepoint|. Returns the number of written scripts.
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int GetScriptExtensions(UChar32 codepoint, UScriptCode* scripts) {
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UErrorCode icu_error = U_ZERO_ERROR;
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // ICU documentation incorrectly states that the result of
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // |uscript_getScriptExtensions| will contain the regular script property.
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Write the character's script property to the first element.
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scripts[0] = uscript_getScript(codepoint, &icu_error);
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (U_FAILURE(icu_error))
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return 0;
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Fill the rest of |scripts| with the extensions.
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int count = uscript_getScriptExtensions(codepoint, scripts + 1,
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          kMaxScripts - 1, &icu_error);
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (U_FAILURE(icu_error))
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    count = 0;
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return count + 1;
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Intersects the script extensions set of |codepoint| with |result| and writes
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// to |result|, reading and updating |result_size|.
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ScriptSetIntersect(UChar32 codepoint,
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        UScriptCode* result,
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                        size_t* result_size) {
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UScriptCode scripts[kMaxScripts] = { USCRIPT_INVALID_CODE };
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int count = GetScriptExtensions(codepoint, scripts);
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t out_size = 0;
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < *result_size; ++i) {
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (int j = 0; j < count; ++j) {
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      UScriptCode intersection = ScriptIntersect(result[i], scripts[j]);
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (intersection != USCRIPT_INVALID_CODE) {
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        result[out_size++] = intersection;
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *result_size = out_size;
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Find the longest sequence of characters from 0 and up to |length| that
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// have at least one common UScriptCode value. Writes the common script value to
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// |script| and returns the length of the sequence. Takes the characters' script
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// extensions into account. http://www.unicode.org/reports/tr24/#ScriptX
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Consider 3 characters with the script values {Kana}, {Hira, Kana}, {Kana}.
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Without script extensions only the first script in each set would be taken
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// into account, resulting in 3 runs where 1 would be enough.
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(ckocagil): Write a unit test for the case above.
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int ScriptInterval(const base::string16& text,
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   size_t start,
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   size_t length,
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   UScriptCode* script) {
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_GT(length, 0U);
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UScriptCode scripts[kMaxScripts] = { USCRIPT_INVALID_CODE };
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::i18n::UTF16CharIterator char_iterator(text.c_str() + start, length);
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t scripts_size = GetScriptExtensions(char_iterator.get(), scripts);
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  *script = scripts[0];
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (char_iterator.Advance()) {
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScriptSetIntersect(char_iterator.get(), scripts, &scripts_size);
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (scripts_size == 0U)
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return char_iterator.array_pos();
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *script = scripts[0];
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return length;
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// A port of hb_icu_script_to_script because harfbuzz on CrOS is built without
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// hb-icu. See http://crbug.com/356929
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)inline hb_script_t ICUScriptToHBScript(UScriptCode script) {
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (script == USCRIPT_INVALID_CODE)
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return HB_SCRIPT_INVALID;
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return hb_script_from_string(uscript_getShortName(script), -1);
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Helper template function for |TextRunHarfBuzz::GetClusterAt()|. |Iterator|
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// can be a forward or reverse iterator type depending on the text direction.
4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)template <class Iterator>
4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GetClusterAtImpl(size_t pos,
4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      Range range,
4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      Iterator elements_begin,
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      Iterator elements_end,
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      bool reversed,
4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      Range* chars,
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                      Range* glyphs) {
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Iterator element = std::upper_bound(elements_begin, elements_end, pos);
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  chars->set_end(element == elements_end ? range.end() : *element);
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  glyphs->set_end(reversed ? elements_end - element : element - elements_begin);
4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(element != elements_begin);
4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  while (--element != elements_begin && *element == *(element - 1));
4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  chars->set_start(*element);
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  glyphs->set_start(
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      reversed ? elements_end - element : element - elements_begin);
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (reversed)
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *glyphs = Range(glyphs->end(), glyphs->start());
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!chars->is_reversed());
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!chars->is_empty());
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!glyphs->is_reversed());
4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(!glyphs->is_empty());
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace internal {
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
463cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TextRunHarfBuzz::TextRunHarfBuzz()
4646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    : width(0.0f),
4656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      preceding_run_widths(0.0f),
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      is_rtl(false),
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      level(0),
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      script(USCRIPT_INVALID_CODE),
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      glyph_count(static_cast<size_t>(-1)),
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      font_size(0),
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      font_style(0),
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      strike(false),
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      diagonal_strike(false),
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      underline(false) {}
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TextRunHarfBuzz::~TextRunHarfBuzz() {}
477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void TextRunHarfBuzz::GetClusterAt(size_t pos,
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   Range* chars,
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   Range* glyphs) const {
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(range.Contains(Range(pos, pos + 1)));
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(chars);
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(glyphs);
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (glyph_count == 0) {
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *chars = range;
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    *glyphs = Range();
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (is_rtl) {
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    GetClusterAtImpl(pos, range, glyph_to_char.rbegin(), glyph_to_char.rend(),
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        true, chars, glyphs);
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetClusterAtImpl(pos, range, glyph_to_char.begin(), glyph_to_char.end(),
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      false, chars, glyphs);
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)Range TextRunHarfBuzz::CharRangeToGlyphRange(const Range& char_range) const {
502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(range.Contains(char_range));
503f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!char_range.is_reversed());
504f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(!char_range.is_empty());
505f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range start_glyphs;
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range end_glyphs;
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range temp_range;
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetClusterAt(char_range.start(), &temp_range, &start_glyphs);
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetClusterAt(char_range.end() - 1, &temp_range, &end_glyphs);
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return is_rtl ? Range(end_glyphs.start(), start_glyphs.end()) :
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      Range(start_glyphs.start(), end_glyphs.end());
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t TextRunHarfBuzz::CountMissingGlyphs() const {
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const int kMissingGlyphId = 0;
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t missing = 0;
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 0; i < glyph_count; ++i)
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    missing += (glyphs[i] == kMissingGlyphId) ? 1 : 0;
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return missing;
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Range TextRunHarfBuzz::GetGraphemeBounds(
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::i18n::BreakIterator* grapheme_iterator,
5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t text_index) {
5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_LT(text_index, range.end());
5286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // TODO(msw): Support floating point grapheme bounds.
5296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const int preceding_run_widths_int = SkScalarRoundToInt(preceding_run_widths);
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (glyph_count == 0)
5316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return Range(preceding_run_widths_int, preceding_run_widths_int + width);
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range chars;
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range glyphs;
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetClusterAt(text_index, &chars, &glyphs);
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int cluster_begin_x = SkScalarRoundToInt(positions[glyphs.start()].x());
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const int cluster_end_x = glyphs.end() < glyph_count ?
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SkScalarRoundToInt(positions[glyphs.end()].x()) : width;
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // A cluster consists of a number of code points and corresponds to a number
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // of glyphs that should be drawn together. A cluster can contain multiple
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // graphemes. In order to place the cursor at a grapheme boundary inside the
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // cluster, we simply divide the cluster width by the number of graphemes.
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (chars.length() > 1 && grapheme_iterator) {
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int before = 0;
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int total = 0;
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (size_t i = chars.start(); i < chars.end(); ++i) {
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (grapheme_iterator->IsGraphemeBoundary(i)) {
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        if (i < text_index)
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          ++before;
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ++total;
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      }
5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK_GT(total, 0);
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (total > 1) {
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (is_rtl)
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        before = total - before - 1;
5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DCHECK_GE(before, 0);
5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      DCHECK_LT(before, total);
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const int cluster_width = cluster_end_x - cluster_begin_x;
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const int grapheme_begin_x = cluster_begin_x + static_cast<int>(0.5f +
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          cluster_width * before / static_cast<float>(total));
5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const int grapheme_end_x = cluster_begin_x + static_cast<int>(0.5f +
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          cluster_width * (before + 1) / static_cast<float>(total));
5656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return Range(preceding_run_widths_int + grapheme_begin_x,
5666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   preceding_run_widths_int + grapheme_end_x);
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return Range(preceding_run_widths_int + cluster_begin_x,
5716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               preceding_run_widths_int + cluster_end_x);
572cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
573cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
574cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace internal
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RenderTextHarfBuzz::RenderTextHarfBuzz()
577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : RenderText(),
5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      needs_layout_(false) {
5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  set_truncate_length(kMaxTextLength);
5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RenderTextHarfBuzz::~RenderTextHarfBuzz() {}
583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)Size RenderTextHarfBuzz::GetStringSize() {
5856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const SizeF size_f = GetStringSizeF();
5866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return Size(std::ceil(size_f.width()), size_f.height());
5876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
5886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SizeF RenderTextHarfBuzz::GetStringSizeF() {
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EnsureLayout();
591f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return lines()[0].size;
592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SelectionModel RenderTextHarfBuzz::FindCursorPosition(const Point& point) {
595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EnsureLayout();
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int x = ToTextPoint(point).x();
598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int offset = 0;
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t run_index = GetRunContainingXCoord(x, &offset);
600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (run_index >= runs_.size())
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return EdgeSelectionModel((x < 0) ? CURSOR_LEFT : CURSOR_RIGHT);
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const internal::TextRunHarfBuzz& run = *runs_[run_index];
603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < run.glyph_count; ++i) {
605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const SkScalar end =
606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        i + 1 == run.glyph_count ? run.width : run.positions[i + 1].x();
607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const SkScalar middle = (end + run.positions[i].x()) / 2;
608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (offset < middle) {
610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return SelectionModel(LayoutIndexToTextIndex(
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          run.glyph_to_char[i] + (run.is_rtl ? 1 : 0)),
612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          (run.is_rtl ? CURSOR_BACKWARD : CURSOR_FORWARD));
613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (offset < end) {
615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return SelectionModel(LayoutIndexToTextIndex(
616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          run.glyph_to_char[i] + (run.is_rtl ? 0 : 1)),
617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          (run.is_rtl ? CURSOR_FORWARD : CURSOR_BACKWARD));
618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return EdgeSelectionModel(CURSOR_RIGHT);
621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<RenderText::FontSpan> RenderTextHarfBuzz::GetFontSpansForTesting() {
6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EnsureLayout();
6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<RenderText::FontSpan> spans;
6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (size_t i = 0; i < runs_.size(); ++i) {
6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SkString family_name;
6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    runs_[i]->skia_face->getFamilyName(&family_name);
6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Font font(family_name.c_str(), runs_[i]->font_size);
6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    spans.push_back(RenderText::FontSpan(font,
6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        Range(LayoutIndexToTextIndex(runs_[i]->range.start()),
6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci              LayoutIndexToTextIndex(runs_[i]->range.end()))));
6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return spans;
637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
638cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Range RenderTextHarfBuzz::GetGlyphBounds(size_t index) {
6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EnsureLayout();
6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t run_index =
6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetRunContainingCaret(SelectionModel(index, CURSOR_FORWARD));
6435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Return edge bounds if the index is invalid or beyond the layout text size.
6445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (run_index >= runs_.size())
6455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return Range(GetStringSize().width());
6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const size_t layout_index = TextIndexToLayoutIndex(index);
6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  internal::TextRunHarfBuzz* run = runs_[run_index];
6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Range bounds = run->GetGraphemeBounds(grapheme_iterator_.get(), layout_index);
6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return run->is_rtl ? Range(bounds.end(), bounds.start()) : bounds;
6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int RenderTextHarfBuzz::GetLayoutTextBaseline() {
653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EnsureLayout();
654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return lines()[0].baseline;
655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
656cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
657cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SelectionModel RenderTextHarfBuzz::AdjacentCharSelectionModel(
658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const SelectionModel& selection,
659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    VisualCursorDirection direction) {
660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!needs_layout_);
661cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  internal::TextRunHarfBuzz* run;
662cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t run_index = GetRunContainingCaret(selection);
663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (run_index >= runs_.size()) {
664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // The cursor is not in any run: we're at the visual and logical edge.
665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SelectionModel edge = EdgeSelectionModel(direction);
666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (edge.caret_pos() == selection.caret_pos())
667cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return edge;
668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int visual_index = (direction == CURSOR_RIGHT) ? 0 : runs_.size() - 1;
669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run = runs_[visual_to_logical_[visual_index]];
670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If the cursor is moving within the current run, just move it by one
672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // grapheme in the appropriate direction.
673cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run = runs_[run_index];
674cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t caret = selection.caret_pos();
675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool forward_motion = run->is_rtl == (direction == CURSOR_LEFT);
676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (forward_motion) {
677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (caret < LayoutIndexToTextIndex(run->range.end())) {
678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD);
679cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return SelectionModel(caret, CURSOR_BACKWARD);
680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
682cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (caret > LayoutIndexToTextIndex(run->range.start())) {
683cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        caret = IndexOfAdjacentGrapheme(caret, CURSOR_BACKWARD);
684cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return SelectionModel(caret, CURSOR_FORWARD);
685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
687cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // The cursor is at the edge of a run; move to the visually adjacent run.
688cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int visual_index = logical_to_visual_[run_index];
689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    visual_index += (direction == CURSOR_LEFT) ? -1 : 1;
690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (visual_index < 0 || visual_index >= static_cast<int>(runs_.size()))
691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return EdgeSelectionModel(direction);
692cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run = runs_[visual_to_logical_[visual_index]];
693cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
694cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool forward_motion = run->is_rtl == (direction == CURSOR_LEFT);
695cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return forward_motion ? FirstSelectionModelInsideRun(run) :
696cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          LastSelectionModelInsideRun(run);
697cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
698cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
699cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SelectionModel RenderTextHarfBuzz::AdjacentWordSelectionModel(
700cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const SelectionModel& selection,
701cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    VisualCursorDirection direction) {
702cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (obscured())
703cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return EdgeSelectionModel(direction);
704cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
705cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
706cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool success = iter.Init();
707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(success);
708cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!success)
709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return selection;
710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Match OS specific word break behavior.
7126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#if defined(OS_WIN)
713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t pos;
714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (direction == CURSOR_RIGHT) {
715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pos = std::min(selection.caret_pos() + 1, text().length());
716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    while (iter.Advance()) {
717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      pos = iter.pos();
718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (iter.IsWord() && pos > selection.caret_pos())
719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {  // direction == CURSOR_LEFT
722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Notes: We always iterate words from the beginning.
723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // This is probably fast enough for our usage, but we may
724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // want to modify WordIterator so that it can start from the
725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // middle of string and advance backwards.
726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pos = std::max<int>(selection.caret_pos() - 1, 0);
727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    while (iter.Advance()) {
728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (iter.IsWord()) {
729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        size_t begin = iter.pos() - iter.GetString().length();
730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (begin == selection.caret_pos()) {
731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // The cursor is at the beginning of a word.
732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // Move to previous word.
733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          break;
734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        } else if (iter.pos() >= selection.caret_pos()) {
735cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // The cursor is in the middle or at the end of a word.
736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // Move to the top of current word.
737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          pos = begin;
738cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          break;
739cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        }
740cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        pos = iter.pos() - iter.GetString().length();
741cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
742cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
743cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
744cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return SelectionModel(pos, CURSOR_FORWARD);
7456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#else
7466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SelectionModel cur(selection);
7476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (;;) {
7486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    cur = AdjacentCharSelectionModel(cur, direction);
7496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    size_t run = GetRunContainingCaret(cur);
7506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (run == runs_.size())
7516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
7526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const bool is_forward = runs_[run]->is_rtl == (direction == CURSOR_LEFT);
7536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    size_t cursor = cur.caret_pos();
7546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (is_forward ? iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor))
7556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
7566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
7576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return cur;
7586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif
759cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
761cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<Rect> RenderTextHarfBuzz::GetSubstringBounds(const Range& range) {
762cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!needs_layout_);
763cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(Range(0, text().length()).Contains(range));
764cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Range layout_range(TextIndexToLayoutIndex(range.start()),
765cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     TextIndexToLayoutIndex(range.end()));
766cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(Range(0, GetLayoutText().length()).Contains(layout_range));
767cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
768cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<Rect> rects;
769cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (layout_range.is_empty())
770cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return rects;
771cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<Range> bounds;
772cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
773cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Add a Range for each run/selection intersection.
774cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    internal::TextRunHarfBuzz* run = runs_[visual_to_logical_[i]];
776cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Range intersection = run->range.Intersect(layout_range);
7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!intersection.IsValid())
7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      continue;
7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(!intersection.is_reversed());
7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Range leftmost_character_x = run->GetGraphemeBounds(
7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        grapheme_iterator_.get(),
7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        run->is_rtl ? intersection.end() - 1 : intersection.start());
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Range rightmost_character_x = run->GetGraphemeBounds(
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        grapheme_iterator_.get(),
7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        run->is_rtl ? intersection.start() : intersection.end() - 1);
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Range range_x(leftmost_character_x.start(), rightmost_character_x.end());
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(!range_x.is_reversed());
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (range_x.is_empty())
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      continue;
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Union this with the last range if they're adjacent.
7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(bounds.empty() || bounds.back().GetMax() <= range_x.GetMin());
7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!bounds.empty() && bounds.back().GetMax() == range_x.GetMin()) {
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      range_x = Range(bounds.back().GetMin(), range_x.GetMax());
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      bounds.pop_back();
796cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bounds.push_back(range_x);
798cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
799cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < bounds.size(); ++i) {
800cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<Rect> current_rects = TextBoundsToViewBounds(bounds[i]);
801cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rects.insert(rects.end(), current_rects.begin(), current_rects.end());
802cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
803cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rects;
804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t RenderTextHarfBuzz::TextIndexToLayoutIndex(size_t index) const {
807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LE(index, text().length());
808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ptrdiff_t i = obscured() ? UTF16IndexToOffset(text(), 0, index) : index;
809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_GE(i, 0);
810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Clamp layout indices to the length of the text actually used for layout.
811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return std::min<size_t>(GetLayoutText().length(), i);
812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t RenderTextHarfBuzz::LayoutIndexToTextIndex(size_t index) const {
815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!obscured())
816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return index;
817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LE(index, GetLayoutText().length());
819cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const size_t text_index = UTF16OffsetToIndex(text(), 0, index);
820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_LE(text_index, text().length());
821cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return text_index;
822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
823cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
824cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RenderTextHarfBuzz::IsValidCursorIndex(size_t index) {
825cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (index == 0 || index == text().length())
826cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
827cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsValidLogicalIndex(index))
828cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
829cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EnsureLayout();
8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return !grapheme_iterator_ || grapheme_iterator_->IsGraphemeBoundary(index);
831cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
832cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
833cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RenderTextHarfBuzz::ResetLayout() {
834cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  needs_layout_ = true;
835cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
836cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
837cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RenderTextHarfBuzz::EnsureLayout() {
838cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (needs_layout_) {
839cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    runs_.clear();
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    grapheme_iterator_.reset();
841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
842cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!GetLayoutText().empty()) {
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      grapheme_iterator_.reset(new base::i18n::BreakIterator(GetLayoutText(),
8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::i18n::BreakIterator::BREAK_CHARACTER));
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (!grapheme_iterator_->Init())
8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        grapheme_iterator_.reset();
8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
848cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ItemizeText();
849cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
850cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      for (size_t i = 0; i < runs_.size(); ++i)
851cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ShapeRun(runs_[i]);
852cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
853cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Precalculate run width information.
8546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      float preceding_run_widths = 0.0f;
855cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      for (size_t i = 0; i < runs_.size(); ++i) {
856cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        internal::TextRunHarfBuzz* run = runs_[visual_to_logical_[i]];
857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        run->preceding_run_widths = preceding_run_widths;
858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        preceding_run_widths += run->width;
859cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
860cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
861cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
862cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    needs_layout_ = false;
863cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<internal::Line> empty_lines;
864cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    set_lines(&empty_lines);
865cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
866cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
867cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (lines().empty()) {
868cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    std::vector<internal::Line> lines;
869cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    lines.push_back(internal::Line());
870f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    lines[0].baseline = font_list().GetBaseline();
871f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    lines[0].size.set_height(font_list().GetHeight());
872cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
873cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int current_x = 0;
874cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SkPaint paint;
875cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
876cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (size_t i = 0; i < runs_.size(); ++i) {
877cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]];
878cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      internal::LineSegment segment;
879cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      segment.x_range = Range(current_x, current_x + run.width);
880cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      segment.char_range = run.range;
881cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      segment.run = i;
882cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lines[0].segments.push_back(segment);
883cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
884cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      paint.setTypeface(run.skia_face.get());
885cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      paint.setTextSize(run.font_size);
886cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SkPaint::FontMetrics metrics;
887cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      paint.getFontMetrics(&metrics);
888cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
889cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lines[0].size.set_width(lines[0].size.width() + run.width);
890cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lines[0].size.set_height(std::max(lines[0].size.height(),
8916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                        metrics.fDescent - metrics.fAscent));
892cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      lines[0].baseline = std::max(lines[0].baseline,
893cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                   SkScalarRoundToInt(-metrics.fAscent));
894cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
895cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
896cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    set_lines(&lines);
897cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
898cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
899cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
900cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RenderTextHarfBuzz::DrawVisualText(Canvas* canvas) {
901cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!needs_layout_);
902cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  internal::SkiaTextRenderer renderer(canvas);
903cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ApplyFadeEffects(&renderer);
904cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ApplyTextShadows(&renderer);
905cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ApplyCompositionAndSelectionStyles();
906cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
907116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int current_x = 0;
908cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const Vector2d line_offset = GetLineOffset(0);
909cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
910cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const internal::TextRunHarfBuzz& run = *runs_[visual_to_logical_[i]];
911cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    renderer.SetTypeface(run.skia_face.get());
912cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    renderer.SetTextSize(run.font_size);
9131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    renderer.SetFontRenderParams(run.render_params,
9141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 background_is_transparent());
915cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
916cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Vector2d origin = line_offset + Vector2d(current_x, lines()[0].baseline);
917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<SkPoint[]> positions(new SkPoint[run.glyph_count]);
918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (size_t j = 0; j < run.glyph_count; ++j) {
919116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      positions[j] = run.positions[j];
920116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      positions[j].offset(SkIntToScalar(origin.x()), SkIntToScalar(origin.y()));
921116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
922cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
923cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    for (BreakList<SkColor>::const_iterator it =
924cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             colors().GetBreak(run.range.start());
925cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         it != colors().breaks().end() && it->first < run.range.end();
926cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)         ++it) {
927cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const Range intersection = colors().GetRange(it).Intersect(run.range);
928cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const Range colored_glyphs = run.CharRangeToGlyphRange(intersection);
929cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The range may be empty if a portion of a multi-character grapheme is
930cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // selected, yielding two colors for a single glyph. For now, this just
931cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // paints the glyph with a single style, but it should paint it twice,
932cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // clipped according to selection bounds. See http://crbug.com/366786
933cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (colored_glyphs.is_empty())
934cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        continue;
935cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
936cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      renderer.SetForegroundColor(it->second);
937116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      renderer.DrawPosText(&positions[colored_glyphs.start()],
938cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           &run.glyphs[colored_glyphs.start()],
939cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           colored_glyphs.length());
940cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int width = (colored_glyphs.end() == run.glyph_count ? run.width :
941cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)              run.positions[colored_glyphs.end()].x()) -
942cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          run.positions[colored_glyphs.start()].x();
943116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      renderer.DrawDecorations(origin.x(), origin.y(), width, run.underline,
944116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                               run.strike, run.diagonal_strike);
945cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
946cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
947cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    current_x += run.width;
948cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
949cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
950cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  renderer.EndDiagonalStrike();
951cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
952cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UndoCompositionAndSelectionStyles();
953cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
954cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
955cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t RenderTextHarfBuzz::GetRunContainingCaret(
956cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const SelectionModel& caret) const {
957cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!needs_layout_);
958cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t layout_position = TextIndexToLayoutIndex(caret.caret_pos());
959cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  LogicalCursorDirection affinity = caret.caret_affinity();
960cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t run = 0; run < runs_.size(); ++run) {
961cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (RangeContainsCaret(runs_[run]->range, layout_position, affinity))
962cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return run;
963cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
964cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return runs_.size();
965cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
966cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
967cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t RenderTextHarfBuzz::GetRunContainingXCoord(int x, int* offset) const {
968cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!needs_layout_);
969cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (x < 0)
970cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return runs_.size();
971cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Find the text run containing the argument point (assumed already offset).
972cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int current_x = 0;
973cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < runs_.size(); ++i) {
974cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t run = visual_to_logical_[i];
975cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    current_x += runs_[run]->width;
976cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (x < current_x) {
977cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *offset = x - (current_x - runs_[run]->width);
978cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return run;
979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
980cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
981cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return runs_.size();
982cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
983cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
984cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SelectionModel RenderTextHarfBuzz::FirstSelectionModelInsideRun(
985cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const internal::TextRunHarfBuzz* run) {
986cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t position = LayoutIndexToTextIndex(run->range.start());
987cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  position = IndexOfAdjacentGrapheme(position, CURSOR_FORWARD);
988cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return SelectionModel(position, CURSOR_BACKWARD);
989cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
990cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
991cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SelectionModel RenderTextHarfBuzz::LastSelectionModelInsideRun(
992cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const internal::TextRunHarfBuzz* run) {
993cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t position = LayoutIndexToTextIndex(run->range.end());
994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  position = IndexOfAdjacentGrapheme(position, CURSOR_BACKWARD);
995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return SelectionModel(position, CURSOR_FORWARD);
996cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
997cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
998cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RenderTextHarfBuzz::ItemizeText() {
999cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const base::string16& text = GetLayoutText();
1000cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const bool is_text_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
1001cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(0U, text.length());
1002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1003f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // If ICU fails to itemize the text, we create a run that spans the entire
1004f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // text. This is needed because leaving the runs set empty causes some clients
1005f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // to misbehave since they expect non-zero text metrics from a non-empty text.
1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::i18n::BiDiLineIterator bidi_iterator;
1007f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!bidi_iterator.Open(text, is_text_rtl, false)) {
1008f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz;
1009f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    run->range = Range(0, text.length());
1010f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    runs_.push_back(run);
1011f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    visual_to_logical_ = logical_to_visual_ = std::vector<int32_t>(1, 0);
1012f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
1013f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
1014cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1015cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Temporarily apply composition underlines and selection colors.
1016cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ApplyCompositionAndSelectionStyles();
1017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Build the list of runs from the script items and ranged styles. Use an
1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // empty color BreakList to avoid breaking runs at color boundaries.
1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BreakList<SkColor> empty_colors;
1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  empty_colors.SetMax(text.length());
1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  internal::StyleIterator style(empty_colors, styles());
1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t run_break = 0; run_break < text.length();) {
1025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz;
1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->range.set_start(run_break);
1027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->font_style = (style.style(BOLD) ? Font::BOLD : 0) |
1028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      (style.style(ITALIC) ? Font::ITALIC : 0);
1029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->strike = style.style(STRIKE);
1030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->diagonal_strike = style.style(DIAGONAL_STRIKE);
1031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->underline = style.style(UNDERLINE);
1032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1033f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int32 script_item_break = 0;
1034f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level);
1035f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Odd BiDi embedding levels correspond to RTL runs.
1036f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    run->is_rtl = (run->level % 2) == 1;
1037f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Find the length and script of this script run.
1038f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    script_item_break = ScriptInterval(text, run_break,
1039f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        script_item_break - run_break, &run->script) + run_break;
1040f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1041f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Find the next break and advance the iterators as needed.
1042f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    run_break = std::min(static_cast<size_t>(script_item_break),
1043f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                         TextIndexToLayoutIndex(style.GetRange().end()));
1044f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Break runs at certain characters that need to be rendered separately to
10461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // prevent either an unusual character from forcing a fallback font on the
10471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // entire run, or brackets from being affected by a fallback font.
10481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // http://crbug.com/278913, http://crbug.com/396776
1049f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (run_break > run->range.start())
10501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      run_break = FindRunBreakingCharacter(text, run->range.start(), run_break);
1051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK(IsValidCodePointIndex(text, run_break));
1053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    style.UpdatePosition(LayoutIndexToTextIndex(run_break));
1054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->range.set_end(run_break);
1055f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
1056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    runs_.push_back(run);
1057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Undo the temporarily applied composition underlines and selection colors.
1060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  UndoCompositionAndSelectionStyles();
1061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const size_t num_runs = runs_.size();
1063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<UBiDiLevel> levels(num_runs);
1064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < num_runs; ++i)
1065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    levels[i] = runs_[i]->level;
1066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  visual_to_logical_.resize(num_runs);
1067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ubidi_reorderVisual(&levels[0], num_runs, &visual_to_logical_[0]);
1068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  logical_to_visual_.resize(num_runs);
1069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ubidi_reorderLogical(&levels[0], num_runs, &logical_to_visual_[0]);
1070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RenderTextHarfBuzz::ShapeRun(internal::TextRunHarfBuzz* run) {
1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const Font& primary_font = font_list().GetPrimaryFont();
10745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const std::string primary_font_name = primary_font.GetFontName();
1075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  run->font_size = primary_font.GetFontSize();
1076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t best_font_missing = std::numeric_limits<size_t>::max();
10785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string best_font;
10795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string current_font;
10805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Try shaping with |primary_font|.
10825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (ShapeRunWithFont(run, primary_font_name)) {
10835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    current_font = primary_font_name;
10845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t current_missing = run->CountMissingGlyphs();
10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (current_missing == 0)
10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (current_missing < best_font_missing) {
10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      best_font_missing = current_missing;
10895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      best_font = current_font;
10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
10915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if defined(OS_WIN)
10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Font uniscribe_font;
10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::char16* run_text = &(GetLayoutText()[run->range.start()]);
10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (GetUniscribeFallbackFont(primary_font, run_text, run->range.length(),
10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                               &uniscribe_font) &&
10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ShapeRunWithFont(run, uniscribe_font.GetFontName())) {
10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    current_font = uniscribe_font.GetFontName();
11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t current_missing = run->CountMissingGlyphs();
11015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (current_missing == 0)
11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (current_missing < best_font_missing) {
11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      best_font_missing = current_missing;
11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      best_font = current_font;
11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
11095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Try shaping with the fonts in the fallback list except the first, which is
11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |primary_font|.
11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<std::string> fonts = GetFallbackFontFamilies(primary_font_name);
11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (size_t i = 1; i < fonts.size(); ++i) {
11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (!ShapeRunWithFont(run, fonts[i]))
11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      continue;
11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    current_font = fonts[i];
11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t current_missing = run->CountMissingGlyphs();
11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (current_missing == 0)
11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return;
11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (current_missing < best_font_missing) {
11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      best_font_missing = current_missing;
11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      best_font = current_font;
11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!best_font.empty() &&
11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (best_font == current_font || ShapeRunWithFont(run, best_font))) {
11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run->glyph_count = 0;
11326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  run->width = 0.0f;
11335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
11355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool RenderTextHarfBuzz::ShapeRunWithFont(internal::TextRunHarfBuzz* run,
11365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          const std::string& font_family) {
11375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const base::string16& text = GetLayoutText();
11385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  skia::RefPtr<SkTypeface> skia_face =
11395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      internal::CreateSkiaTypeface(font_family, run->font_style);
11405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (skia_face == NULL)
11415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return false;
11425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run->skia_face = skia_face;
11431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  FontRenderParamsQuery query(false);
11441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  query.families.push_back(font_family);
11451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  query.pixel_size = run->font_size;
11461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  query.style = run->font_style;
11471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  run->render_params = GetFontRenderParams(query, NULL);
1148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_font_t* harfbuzz_font = CreateHarfBuzzFont(run->skia_face.get(),
11491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      run->font_size, run->render_params, background_is_transparent());
1150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create a HarfBuzz buffer and add the string to be shaped. The HarfBuzz
1152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // buffer holds our text, run information to be used by the shaping engine,
1153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // and the resulting glyph data.
1154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_buffer_t* buffer = hb_buffer_create();
1155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_buffer_add_utf16(buffer, reinterpret_cast<const uint16*>(text.c_str()),
1156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                      text.length(), run->range.start(), run->range.length());
1157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_buffer_set_script(buffer, ICUScriptToHBScript(run->script));
1158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_buffer_set_direction(buffer,
1159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      run->is_rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
1160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(ckocagil): Should we determine the actual language?
1161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_buffer_set_language(buffer, hb_language_get_default());
1162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Shape the text.
1164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_shape(harfbuzz_font, buffer, NULL, 0);
1165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Populate the run fields with the resulting glyph data in the buffer.
1167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  unsigned int glyph_count = 0;
1168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(buffer, &glyph_count);
1169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  run->glyph_count = glyph_count;
11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  hb_glyph_position_t* hb_positions =
11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      hb_buffer_get_glyph_positions(buffer, NULL);
1172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  run->glyphs.reset(new uint16[run->glyph_count]);
11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  run->glyph_to_char.resize(run->glyph_count);
1174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  run->positions.reset(new SkPoint[run->glyph_count]);
11756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  run->width = 0.0f;
1176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < run->glyph_count; ++i) {
1177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->glyphs[i] = infos[i].codepoint;
1178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    run->glyph_to_char[i] = infos[i].cluster;
11796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const int x_offset = SkFixedToScalar(hb_positions[i].x_offset);
11806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const int y_offset = SkFixedToScalar(hb_positions[i].y_offset);
1181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    run->positions[i].set(run->width + x_offset, -y_offset);
11826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    run->width += SkFixedToScalar(hb_positions[i].x_advance);
11831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_LINUX)
11841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Match Pango's glyph rounding logic on Linux.
11851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!run->render_params.subpixel_positioning)
11861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      run->width = std::floor(run->width + 0.5f);
11871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
1188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
1189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_buffer_destroy(buffer);
1191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  hb_font_destroy(harfbuzz_font);
11925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
1193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace gfx
1196