Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(380)

Side by Side Diff: ui/gfx/render_text_pango.cc

Issue 26541007: ozone: Allow building for ozone without depending on pango (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: prepare-land Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/render_text_pango.h ('k') | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/render_text_linux.h" 5 #include "ui/gfx/render_text_pango.h"
6 6
7 #include <pango/pangocairo.h> 7 #include <pango/pangocairo.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/i18n/break_iterator.h" 12 #include "base/i18n/break_iterator.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "third_party/skia/include/core/SkTypeface.h" 14 #include "third_party/skia/include/core/SkTypeface.h"
15 #include "ui/gfx/canvas.h" 15 #include "ui/gfx/canvas.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 renderer->SetUnderlineMetrics(PANGO_PIXELS(thickness), 60 renderer->SetUnderlineMetrics(PANGO_PIXELS(thickness),
61 PANGO_PIXELS(position)); 61 PANGO_PIXELS(position));
62 } 62 }
63 63
64 } // namespace 64 } // namespace
65 65
66 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index. 66 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index.
67 // Since caret_pos is used internally, we could save utf8 index for caret_pos 67 // Since caret_pos is used internally, we could save utf8 index for caret_pos
68 // to avoid conversion. 68 // to avoid conversion.
69 69
70 RenderTextLinux::RenderTextLinux() 70 RenderTextPango::RenderTextPango()
71 : layout_(NULL), 71 : layout_(NULL),
72 current_line_(NULL), 72 current_line_(NULL),
73 log_attrs_(NULL), 73 log_attrs_(NULL),
74 num_log_attrs_(0), 74 num_log_attrs_(0),
75 layout_text_(NULL) { 75 layout_text_(NULL) {
76 } 76 }
77 77
78 RenderTextLinux::~RenderTextLinux() { 78 RenderTextPango::~RenderTextPango() {
79 ResetLayout(); 79 ResetLayout();
80 } 80 }
81 81
82 Size RenderTextLinux::GetStringSize() { 82 Size RenderTextPango::GetStringSize() {
83 EnsureLayout(); 83 EnsureLayout();
84 int width = 0, height = 0; 84 int width = 0, height = 0;
85 pango_layout_get_pixel_size(layout_, &width, &height); 85 pango_layout_get_pixel_size(layout_, &width, &height);
86 // Keep a consistent height between this particular string's PangoLayout and 86 // Keep a consistent height between this particular string's PangoLayout and
87 // potentially larger text supported by the FontList. 87 // potentially larger text supported by the FontList.
88 // For example, if a text field contains a Japanese character, which is 88 // For example, if a text field contains a Japanese character, which is
89 // smaller than Latin ones, and then later a Latin one is inserted, this 89 // smaller than Latin ones, and then later a Latin one is inserted, this
90 // ensures that the text baseline does not shift. 90 // ensures that the text baseline does not shift.
91 return Size(width, std::max(height, font_list().GetHeight())); 91 return Size(width, std::max(height, font_list().GetHeight()));
92 } 92 }
93 93
94 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) { 94 SelectionModel RenderTextPango::FindCursorPosition(const Point& point) {
95 EnsureLayout(); 95 EnsureLayout();
96 96
97 if (text().empty()) 97 if (text().empty())
98 return SelectionModel(0, CURSOR_FORWARD); 98 return SelectionModel(0, CURSOR_FORWARD);
99 99
100 Point p(ToTextPoint(point)); 100 Point p(ToTextPoint(point));
101 101
102 // When the point is outside of text, return HOME/END position. 102 // When the point is outside of text, return HOME/END position.
103 if (p.x() < 0) 103 if (p.x() < 0)
104 return EdgeSelectionModel(CURSOR_LEFT); 104 return EdgeSelectionModel(CURSOR_LEFT);
105 if (p.x() > GetStringSize().width()) 105 if (p.x() > GetStringSize().width())
106 return EdgeSelectionModel(CURSOR_RIGHT); 106 return EdgeSelectionModel(CURSOR_RIGHT);
107 107
108 int caret_pos = 0, trailing = 0; 108 int caret_pos = 0, trailing = 0;
109 pango_layout_xy_to_index(layout_, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE, 109 pango_layout_xy_to_index(layout_, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
110 &caret_pos, &trailing); 110 &caret_pos, &trailing);
111 111
112 DCHECK_GE(trailing, 0); 112 DCHECK_GE(trailing, 0);
113 if (trailing > 0) { 113 if (trailing > 0) {
114 caret_pos = g_utf8_offset_to_pointer(layout_text_ + caret_pos, 114 caret_pos = g_utf8_offset_to_pointer(layout_text_ + caret_pos,
115 trailing) - layout_text_; 115 trailing) - layout_text_;
116 DCHECK_LE(static_cast<size_t>(caret_pos), strlen(layout_text_)); 116 DCHECK_LE(static_cast<size_t>(caret_pos), strlen(layout_text_));
117 } 117 }
118 118
119 return SelectionModel(LayoutIndexToTextIndex(caret_pos), 119 return SelectionModel(LayoutIndexToTextIndex(caret_pos),
120 (trailing > 0) ? CURSOR_BACKWARD : CURSOR_FORWARD); 120 (trailing > 0) ? CURSOR_BACKWARD : CURSOR_FORWARD);
121 } 121 }
122 122
123 std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() { 123 std::vector<RenderText::FontSpan> RenderTextPango::GetFontSpansForTesting() {
124 EnsureLayout(); 124 EnsureLayout();
125 125
126 std::vector<RenderText::FontSpan> spans; 126 std::vector<RenderText::FontSpan> spans;
127 for (GSList* it = current_line_->runs; it; it = it->next) { 127 for (GSList* it = current_line_->runs; it; it = it->next) {
128 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(it->data)->item; 128 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(it->data)->item;
129 const int start = LayoutIndexToTextIndex(item->offset); 129 const int start = LayoutIndexToTextIndex(item->offset);
130 const int end = LayoutIndexToTextIndex(item->offset + item->length); 130 const int end = LayoutIndexToTextIndex(item->offset + item->length);
131 const Range range(start, end); 131 const Range range(start, end);
132 132
133 ScopedPangoFontDescription desc(pango_font_describe(item->analysis.font)); 133 ScopedPangoFontDescription desc(pango_font_describe(item->analysis.font));
134 spans.push_back(RenderText::FontSpan(Font(desc.get()), range)); 134 spans.push_back(RenderText::FontSpan(Font(desc.get()), range));
135 } 135 }
136 136
137 return spans; 137 return spans;
138 } 138 }
139 139
140 int RenderTextLinux::GetLayoutTextBaseline() { 140 int RenderTextPango::GetLayoutTextBaseline() {
141 EnsureLayout(); 141 EnsureLayout();
142 return PANGO_PIXELS(pango_layout_get_baseline(layout_)); 142 return PANGO_PIXELS(pango_layout_get_baseline(layout_));
143 } 143 }
144 144
145 SelectionModel RenderTextLinux::AdjacentCharSelectionModel( 145 SelectionModel RenderTextPango::AdjacentCharSelectionModel(
146 const SelectionModel& selection, 146 const SelectionModel& selection,
147 VisualCursorDirection direction) { 147 VisualCursorDirection direction) {
148 GSList* run = GetRunContainingCaret(selection); 148 GSList* run = GetRunContainingCaret(selection);
149 if (!run) { 149 if (!run) {
150 // The cursor is not in any run: we're at the visual and logical edge. 150 // The cursor is not in any run: we're at the visual and logical edge.
151 SelectionModel edge = EdgeSelectionModel(direction); 151 SelectionModel edge = EdgeSelectionModel(direction);
152 if (edge.caret_pos() == selection.caret_pos()) 152 if (edge.caret_pos() == selection.caret_pos())
153 return edge; 153 return edge;
154 else 154 else
155 run = (direction == CURSOR_RIGHT) ? 155 run = (direction == CURSOR_RIGHT) ?
(...skipping 19 matching lines...) Expand all
175 run = (direction == CURSOR_RIGHT) ? 175 run = (direction == CURSOR_RIGHT) ?
176 run->next : GSListPrevious(current_line_->runs, run); 176 run->next : GSListPrevious(current_line_->runs, run);
177 if (!run) 177 if (!run)
178 return EdgeSelectionModel(direction); 178 return EdgeSelectionModel(direction);
179 } 179 }
180 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; 180 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
181 return IsForwardMotion(direction, item) ? 181 return IsForwardMotion(direction, item) ?
182 FirstSelectionModelInsideRun(item) : LastSelectionModelInsideRun(item); 182 FirstSelectionModelInsideRun(item) : LastSelectionModelInsideRun(item);
183 } 183 }
184 184
185 SelectionModel RenderTextLinux::AdjacentWordSelectionModel( 185 SelectionModel RenderTextPango::AdjacentWordSelectionModel(
186 const SelectionModel& selection, 186 const SelectionModel& selection,
187 VisualCursorDirection direction) { 187 VisualCursorDirection direction) {
188 if (obscured()) 188 if (obscured())
189 return EdgeSelectionModel(direction); 189 return EdgeSelectionModel(direction);
190 190
191 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); 191 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
192 bool success = iter.Init(); 192 bool success = iter.Init();
193 DCHECK(success); 193 DCHECK(success);
194 if (!success) 194 if (!success)
195 return selection; 195 return selection;
196 196
197 SelectionModel cur(selection); 197 SelectionModel cur(selection);
198 for (;;) { 198 for (;;) {
199 cur = AdjacentCharSelectionModel(cur, direction); 199 cur = AdjacentCharSelectionModel(cur, direction);
200 GSList* run = GetRunContainingCaret(cur); 200 GSList* run = GetRunContainingCaret(cur);
201 if (!run) 201 if (!run)
202 break; 202 break;
203 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; 203 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
204 size_t cursor = cur.caret_pos(); 204 size_t cursor = cur.caret_pos();
205 if (IsForwardMotion(direction, item) ? 205 if (IsForwardMotion(direction, item) ?
206 iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) 206 iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor))
207 break; 207 break;
208 } 208 }
209 209
210 return cur; 210 return cur;
211 } 211 }
212 212
213 Range RenderTextLinux::GetGlyphBounds(size_t index) { 213 Range RenderTextPango::GetGlyphBounds(size_t index) {
214 PangoRectangle pos; 214 PangoRectangle pos;
215 pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(index), &pos); 215 pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(index), &pos);
216 // TODO(derat): Support fractional ranges for subpixel positioning? 216 // TODO(derat): Support fractional ranges for subpixel positioning?
217 return Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width)); 217 return Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width));
218 } 218 }
219 219
220 std::vector<Rect> RenderTextLinux::GetSubstringBounds(const Range& range) { 220 std::vector<Rect> RenderTextPango::GetSubstringBounds(const Range& range) {
221 DCHECK_LE(range.GetMax(), text().length()); 221 DCHECK_LE(range.GetMax(), text().length());
222 if (range.is_empty()) 222 if (range.is_empty())
223 return std::vector<Rect>(); 223 return std::vector<Rect>();
224 224
225 EnsureLayout(); 225 EnsureLayout();
226 int* ranges = NULL; 226 int* ranges = NULL;
227 int n_ranges = 0; 227 int n_ranges = 0;
228 pango_layout_line_get_x_ranges(current_line_, 228 pango_layout_line_get_x_ranges(current_line_,
229 TextIndexToLayoutIndex(range.GetMin()), 229 TextIndexToLayoutIndex(range.GetMin()),
230 TextIndexToLayoutIndex(range.GetMax()), 230 TextIndexToLayoutIndex(range.GetMax()),
231 &ranges, 231 &ranges,
232 &n_ranges); 232 &n_ranges);
233 233
234 const int height = GetStringSize().height(); 234 const int height = GetStringSize().height();
235 235
236 std::vector<Rect> bounds; 236 std::vector<Rect> bounds;
237 for (int i = 0; i < n_ranges; ++i) { 237 for (int i = 0; i < n_ranges; ++i) {
238 // TODO(derat): Support fractional bounds for subpixel positioning? 238 // TODO(derat): Support fractional bounds for subpixel positioning?
239 int x = PANGO_PIXELS(ranges[2 * i]); 239 int x = PANGO_PIXELS(ranges[2 * i]);
240 int width = PANGO_PIXELS(ranges[2 * i + 1]) - x; 240 int width = PANGO_PIXELS(ranges[2 * i + 1]) - x;
241 Rect rect(x, 0, width, height); 241 Rect rect(x, 0, width, height);
242 rect.set_origin(ToViewPoint(rect.origin())); 242 rect.set_origin(ToViewPoint(rect.origin()));
243 bounds.push_back(rect); 243 bounds.push_back(rect);
244 } 244 }
245 g_free(ranges); 245 g_free(ranges);
246 return bounds; 246 return bounds;
247 } 247 }
248 248
249 size_t RenderTextLinux::TextIndexToLayoutIndex(size_t index) const { 249 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const {
250 DCHECK(layout_); 250 DCHECK(layout_);
251 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index); 251 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index);
252 // Clamp layout indices to the length of the text actually used for layout. 252 // Clamp layout indices to the length of the text actually used for layout.
253 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); 253 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1));
254 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); 254 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset);
255 return (layout_pointer - layout_text_); 255 return (layout_pointer - layout_text_);
256 } 256 }
257 257
258 size_t RenderTextLinux::LayoutIndexToTextIndex(size_t index) const { 258 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const {
259 DCHECK(layout_); 259 DCHECK(layout_);
260 const char* layout_pointer = layout_text_ + index; 260 const char* layout_pointer = layout_text_ + index;
261 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); 261 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer);
262 return gfx::UTF16OffsetToIndex(text(), 0, offset); 262 return gfx::UTF16OffsetToIndex(text(), 0, offset);
263 } 263 }
264 264
265 bool RenderTextLinux::IsCursorablePosition(size_t position) { 265 bool RenderTextPango::IsCursorablePosition(size_t position) {
266 if (position == 0 && text().empty()) 266 if (position == 0 && text().empty())
267 return true; 267 return true;
268 if (position >= text().length()) 268 if (position >= text().length())
269 return position == text().length(); 269 return position == text().length();
270 if (!gfx::IsValidCodePointIndex(text(), position)) 270 if (!gfx::IsValidCodePointIndex(text(), position))
271 return false; 271 return false;
272 272
273 EnsureLayout(); 273 EnsureLayout();
274 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position); 274 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position);
275 // Check that the index corresponds with a valid text code point, that it is 275 // Check that the index corresponds with a valid text code point, that it is
276 // marked as a legitimate cursor position by Pango, and that it is not 276 // marked as a legitimate cursor position by Pango, and that it is not
277 // truncated from layout text (its glyph is shown on screen). 277 // truncated from layout text (its glyph is shown on screen).
278 return (offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position && 278 return (offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position &&
279 offset < g_utf8_strlen(layout_text_, -1)); 279 offset < g_utf8_strlen(layout_text_, -1));
280 } 280 }
281 281
282 void RenderTextLinux::ResetLayout() { 282 void RenderTextPango::ResetLayout() {
283 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every 283 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every
284 // operation that triggers ResetLayout(). 284 // operation that triggers ResetLayout().
285 if (layout_) { 285 if (layout_) {
286 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. 286 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used.
287 g_object_unref(layout_); 287 g_object_unref(layout_);
288 layout_ = NULL; 288 layout_ = NULL;
289 } 289 }
290 if (current_line_) { 290 if (current_line_) {
291 pango_layout_line_unref(current_line_); 291 pango_layout_line_unref(current_line_);
292 current_line_ = NULL; 292 current_line_ = NULL;
293 } 293 }
294 if (log_attrs_) { 294 if (log_attrs_) {
295 g_free(log_attrs_); 295 g_free(log_attrs_);
296 log_attrs_ = NULL; 296 log_attrs_ = NULL;
297 num_log_attrs_ = 0; 297 num_log_attrs_ = 0;
298 } 298 }
299 layout_text_ = NULL; 299 layout_text_ = NULL;
300 } 300 }
301 301
302 void RenderTextLinux::EnsureLayout() { 302 void RenderTextPango::EnsureLayout() {
303 if (layout_ == NULL) { 303 if (layout_ == NULL) {
304 cairo_surface_t* surface = 304 cairo_surface_t* surface =
305 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); 305 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
306 CHECK_EQ(CAIRO_STATUS_SUCCESS, cairo_surface_status(surface)); 306 CHECK_EQ(CAIRO_STATUS_SUCCESS, cairo_surface_status(surface));
307 cairo_t* cr = cairo_create(surface); 307 cairo_t* cr = cairo_create(surface);
308 CHECK_EQ(CAIRO_STATUS_SUCCESS, cairo_status(cr)); 308 CHECK_EQ(CAIRO_STATUS_SUCCESS, cairo_status(cr));
309 309
310 layout_ = pango_cairo_create_layout(cr); 310 layout_ = pango_cairo_create_layout(cr);
311 CHECK_NE(static_cast<PangoLayout*>(NULL), layout_); 311 CHECK_NE(static_cast<PangoLayout*>(NULL), layout_);
312 cairo_destroy(cr); 312 cairo_destroy(cr);
(...skipping 18 matching lines...) Expand all
331 SetupPangoAttributes(layout_); 331 SetupPangoAttributes(layout_);
332 332
333 current_line_ = pango_layout_get_line_readonly(layout_, 0); 333 current_line_ = pango_layout_get_line_readonly(layout_, 0);
334 CHECK_NE(static_cast<PangoLayoutLine*>(NULL), current_line_); 334 CHECK_NE(static_cast<PangoLayoutLine*>(NULL), current_line_);
335 pango_layout_line_ref(current_line_); 335 pango_layout_line_ref(current_line_);
336 336
337 pango_layout_get_log_attrs(layout_, &log_attrs_, &num_log_attrs_); 337 pango_layout_get_log_attrs(layout_, &log_attrs_, &num_log_attrs_);
338 } 338 }
339 } 339 }
340 340
341 void RenderTextLinux::SetupPangoAttributes(PangoLayout* layout) { 341 void RenderTextPango::SetupPangoAttributes(PangoLayout* layout) {
342 PangoAttrList* attrs = pango_attr_list_new(); 342 PangoAttrList* attrs = pango_attr_list_new();
343 343
344 // Splitting text runs to accommodate styling can break Arabic glyph shaping. 344 // Splitting text runs to accommodate styling can break Arabic glyph shaping.
345 // Only split text runs as needed for bold and italic font styles changes. 345 // Only split text runs as needed for bold and italic font styles changes.
346 BreakList<bool>::const_iterator bold = styles()[BOLD].breaks().begin(); 346 BreakList<bool>::const_iterator bold = styles()[BOLD].breaks().begin();
347 BreakList<bool>::const_iterator italic = styles()[ITALIC].breaks().begin(); 347 BreakList<bool>::const_iterator italic = styles()[ITALIC].breaks().begin();
348 while (bold != styles()[BOLD].breaks().end() && 348 while (bold != styles()[BOLD].breaks().end() &&
349 italic != styles()[ITALIC].breaks().end()) { 349 italic != styles()[ITALIC].breaks().end()) {
350 const int style = (bold->second ? Font::BOLD : 0) | 350 const int style = (bold->second ? Font::BOLD : 0) |
351 (italic->second ? Font::ITALIC : 0); 351 (italic->second ? Font::ITALIC : 0);
(...skipping 14 matching lines...) Expand all
366 bold += bold_end == style_end ? 1 : 0; 366 bold += bold_end == style_end ? 1 : 0;
367 italic += italic_end == style_end ? 1 : 0; 367 italic += italic_end == style_end ? 1 : 0;
368 } 368 }
369 DCHECK(bold == styles()[BOLD].breaks().end()); 369 DCHECK(bold == styles()[BOLD].breaks().end());
370 DCHECK(italic == styles()[ITALIC].breaks().end()); 370 DCHECK(italic == styles()[ITALIC].breaks().end());
371 371
372 pango_layout_set_attributes(layout, attrs); 372 pango_layout_set_attributes(layout, attrs);
373 pango_attr_list_unref(attrs); 373 pango_attr_list_unref(attrs);
374 } 374 }
375 375
376 void RenderTextLinux::DrawVisualText(Canvas* canvas) { 376 void RenderTextPango::DrawVisualText(Canvas* canvas) {
377 DCHECK(layout_); 377 DCHECK(layout_);
378 378
379 // Skia will draw glyphs with respect to the baseline. 379 // Skia will draw glyphs with respect to the baseline.
380 Vector2d offset(GetLineOffset(0) + Vector2d(0, GetLayoutTextBaseline())); 380 Vector2d offset(GetLineOffset(0) + Vector2d(0, GetLayoutTextBaseline()));
381 381
382 SkScalar x = SkIntToScalar(offset.x()); 382 SkScalar x = SkIntToScalar(offset.x());
383 SkScalar y = SkIntToScalar(offset.y()); 383 SkScalar y = SkIntToScalar(offset.y());
384 384
385 std::vector<SkPoint> pos; 385 std::vector<SkPoint> pos;
386 std::vector<uint16> glyphs; 386 std::vector<uint16> glyphs;
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 style_start_glyph_index = glyph_index; 465 style_start_glyph_index = glyph_index;
466 style_start_x = x; 466 style_start_x = x;
467 } 467 }
468 } while (glyph_index < glyph_count); 468 } while (glyph_index < glyph_count);
469 } 469 }
470 470
471 // Undo the temporarily applied composition underlines and selection colors. 471 // Undo the temporarily applied composition underlines and selection colors.
472 UndoCompositionAndSelectionStyles(); 472 UndoCompositionAndSelectionStyles();
473 } 473 }
474 474
475 GSList* RenderTextLinux::GetRunContainingCaret( 475 GSList* RenderTextPango::GetRunContainingCaret(
476 const SelectionModel& caret) const { 476 const SelectionModel& caret) const {
477 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); 477 size_t position = TextIndexToLayoutIndex(caret.caret_pos());
478 LogicalCursorDirection affinity = caret.caret_affinity(); 478 LogicalCursorDirection affinity = caret.caret_affinity();
479 GSList* run = current_line_->runs; 479 GSList* run = current_line_->runs;
480 while (run) { 480 while (run) {
481 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; 481 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
482 Range item_range(item->offset, item->offset + item->length); 482 Range item_range(item->offset, item->offset + item->length);
483 if (RangeContainsCaret(item_range, position, affinity)) 483 if (RangeContainsCaret(item_range, position, affinity))
484 return run; 484 return run;
485 run = run->next; 485 run = run->next;
486 } 486 }
487 return NULL; 487 return NULL;
488 } 488 }
489 489
490 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun( 490 SelectionModel RenderTextPango::FirstSelectionModelInsideRun(
491 const PangoItem* item) { 491 const PangoItem* item) {
492 size_t caret = IndexOfAdjacentGrapheme( 492 size_t caret = IndexOfAdjacentGrapheme(
493 LayoutIndexToTextIndex(item->offset), CURSOR_FORWARD); 493 LayoutIndexToTextIndex(item->offset), CURSOR_FORWARD);
494 return SelectionModel(caret, CURSOR_BACKWARD); 494 return SelectionModel(caret, CURSOR_BACKWARD);
495 } 495 }
496 496
497 SelectionModel RenderTextLinux::LastSelectionModelInsideRun( 497 SelectionModel RenderTextPango::LastSelectionModelInsideRun(
498 const PangoItem* item) { 498 const PangoItem* item) {
499 size_t caret = IndexOfAdjacentGrapheme( 499 size_t caret = IndexOfAdjacentGrapheme(
500 LayoutIndexToTextIndex(item->offset + item->length), CURSOR_BACKWARD); 500 LayoutIndexToTextIndex(item->offset + item->length), CURSOR_BACKWARD);
501 return SelectionModel(caret, CURSOR_FORWARD); 501 return SelectionModel(caret, CURSOR_FORWARD);
502 } 502 }
503 503
504 size_t RenderTextLinux::GetGlyphTextIndex(PangoLayoutRun* run, 504 size_t RenderTextPango::GetGlyphTextIndex(PangoLayoutRun* run,
505 int glyph_index) const { 505 int glyph_index) const {
506 return LayoutIndexToTextIndex(run->item->offset + 506 return LayoutIndexToTextIndex(run->item->offset +
507 run->glyphs->log_clusters[glyph_index]); 507 run->glyphs->log_clusters[glyph_index]);
508 } 508 }
509 509
510 RenderText* RenderText::CreateInstance() { 510 RenderText* RenderText::CreateInstance() {
511 return new RenderTextLinux; 511 return new RenderTextPango;
512 } 512 }
513 513
514 } // namespace gfx 514 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text_pango.h ('k') | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698