OLD | NEW |
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_linux.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> |
(...skipping 22 matching lines...) Expand all Loading... |
33 } | 33 } |
34 | 34 |
35 // Returns true if the given visual cursor |direction| is logically forward | 35 // Returns true if the given visual cursor |direction| is logically forward |
36 // motion in the given Pango |item|. | 36 // motion in the given Pango |item|. |
37 bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) { | 37 bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) { |
38 bool rtl = item->analysis.level & 1; | 38 bool rtl = item->analysis.level & 1; |
39 return rtl == (direction == CURSOR_LEFT); | 39 return rtl == (direction == CURSOR_LEFT); |
40 } | 40 } |
41 | 41 |
42 // Checks whether |range| contains |index|. This is not the same as calling | 42 // Checks whether |range| contains |index|. This is not the same as calling |
43 // |range.Contains(ui::Range(index))| - as that would return true when | 43 // |range.Contains(gfx::Range(index))| - as that would return true when |
44 // |index| == |range.end()|. | 44 // |index| == |range.end()|. |
45 bool IndexInRange(const ui::Range& range, size_t index) { | 45 bool IndexInRange(const gfx::Range& range, size_t index) { |
46 return index >= range.start() && index < range.end(); | 46 return index >= range.start() && index < range.end(); |
47 } | 47 } |
48 | 48 |
49 // Sets underline metrics on |renderer| according to Pango font |desc|. | 49 // Sets underline metrics on |renderer| according to Pango font |desc|. |
50 void SetPangoUnderlineMetrics(PangoFontDescription *desc, | 50 void SetPangoUnderlineMetrics(PangoFontDescription *desc, |
51 internal::SkiaTextRenderer* renderer) { | 51 internal::SkiaTextRenderer* renderer) { |
52 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); | 52 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); |
53 int thickness = pango_font_metrics_get_underline_thickness(metrics); | 53 int thickness = pango_font_metrics_get_underline_thickness(metrics); |
54 // Pango returns the position "above the baseline". Change its sign to convert | 54 // Pango returns the position "above the baseline". Change its sign to convert |
55 // it to a vertical offset from the baseline. | 55 // it to a vertical offset from the baseline. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 } | 130 } |
131 | 131 |
132 std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() { | 132 std::vector<RenderText::FontSpan> RenderTextLinux::GetFontSpansForTesting() { |
133 EnsureLayout(); | 133 EnsureLayout(); |
134 | 134 |
135 std::vector<RenderText::FontSpan> spans; | 135 std::vector<RenderText::FontSpan> spans; |
136 for (GSList* it = current_line_->runs; it; it = it->next) { | 136 for (GSList* it = current_line_->runs; it; it = it->next) { |
137 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(it->data)->item; | 137 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(it->data)->item; |
138 const int start = LayoutIndexToTextIndex(item->offset); | 138 const int start = LayoutIndexToTextIndex(item->offset); |
139 const int end = LayoutIndexToTextIndex(item->offset + item->length); | 139 const int end = LayoutIndexToTextIndex(item->offset + item->length); |
140 const ui::Range range(start, end); | 140 const gfx::Range range(start, end); |
141 | 141 |
142 ScopedPangoFontDescription desc(pango_font_describe(item->analysis.font)); | 142 ScopedPangoFontDescription desc(pango_font_describe(item->analysis.font)); |
143 spans.push_back(RenderText::FontSpan(Font(desc.get()), range)); | 143 spans.push_back(RenderText::FontSpan(Font(desc.get()), range)); |
144 } | 144 } |
145 | 145 |
146 return spans; | 146 return spans; |
147 } | 147 } |
148 | 148 |
149 SelectionModel RenderTextLinux::AdjacentCharSelectionModel( | 149 SelectionModel RenderTextLinux::AdjacentCharSelectionModel( |
150 const SelectionModel& selection, | 150 const SelectionModel& selection, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; | 207 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; |
208 size_t cursor = cur.caret_pos(); | 208 size_t cursor = cur.caret_pos(); |
209 if (IsForwardMotion(direction, item) ? | 209 if (IsForwardMotion(direction, item) ? |
210 iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) | 210 iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) |
211 break; | 211 break; |
212 } | 212 } |
213 | 213 |
214 return cur; | 214 return cur; |
215 } | 215 } |
216 | 216 |
217 ui::Range RenderTextLinux::GetGlyphBounds(size_t index) { | 217 gfx::Range RenderTextLinux::GetGlyphBounds(size_t index) { |
218 PangoRectangle pos; | 218 PangoRectangle pos; |
219 pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(index), &pos); | 219 pango_layout_index_to_pos(layout_, TextIndexToLayoutIndex(index), &pos); |
220 // TODO(derat): Support fractional ranges for subpixel positioning? | 220 // TODO(derat): Support fractional ranges for subpixel positioning? |
221 return ui::Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width)); | 221 return gfx::Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width)); |
222 } | 222 } |
223 | 223 |
224 std::vector<Rect> RenderTextLinux::GetSubstringBounds(const ui::Range& range) { | 224 std::vector<Rect> RenderTextLinux::GetSubstringBounds(const gfx::Range& range) { |
225 DCHECK_LE(range.GetMax(), text().length()); | 225 DCHECK_LE(range.GetMax(), text().length()); |
226 if (range.is_empty()) | 226 if (range.is_empty()) |
227 return std::vector<Rect>(); | 227 return std::vector<Rect>(); |
228 | 228 |
229 EnsureLayout(); | 229 EnsureLayout(); |
230 int* ranges = NULL; | 230 int* ranges = NULL; |
231 int n_ranges = 0; | 231 int n_ranges = 0; |
232 pango_layout_line_get_x_ranges(current_line_, | 232 pango_layout_line_get_x_ranges(current_line_, |
233 TextIndexToLayoutIndex(range.GetMin()), | 233 TextIndexToLayoutIndex(range.GetMin()), |
234 TextIndexToLayoutIndex(range.GetMax()), | 234 TextIndexToLayoutIndex(range.GetMax()), |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 | 421 |
422 // Track the current glyph and the glyph at the start of its styled range. | 422 // Track the current glyph and the glyph at the start of its styled range. |
423 int glyph_index = 0; | 423 int glyph_index = 0; |
424 int style_start_glyph_index = glyph_index; | 424 int style_start_glyph_index = glyph_index; |
425 | 425 |
426 // Track the x-coordinates for each styled range (|x| marks the current). | 426 // Track the x-coordinates for each styled range (|x| marks the current). |
427 SkScalar style_start_x = x; | 427 SkScalar style_start_x = x; |
428 | 428 |
429 // Track the current style and its text (not layout) index range. | 429 // Track the current style and its text (not layout) index range. |
430 style.UpdatePosition(GetGlyphTextIndex(run, style_start_glyph_index)); | 430 style.UpdatePosition(GetGlyphTextIndex(run, style_start_glyph_index)); |
431 ui::Range style_range = style.GetRange(); | 431 gfx::Range style_range = style.GetRange(); |
432 | 432 |
433 do { | 433 do { |
434 const PangoGlyphInfo& glyph = run->glyphs->glyphs[glyph_index]; | 434 const PangoGlyphInfo& glyph = run->glyphs->glyphs[glyph_index]; |
435 glyphs[glyph_index] = static_cast<uint16>(glyph.glyph); | 435 glyphs[glyph_index] = static_cast<uint16>(glyph.glyph); |
436 // Use pango_units_to_double() rather than PANGO_PIXELS() here, so units | 436 // Use pango_units_to_double() rather than PANGO_PIXELS() here, so units |
437 // are not rounded to the pixel grid if subpixel positioning is enabled. | 437 // are not rounded to the pixel grid if subpixel positioning is enabled. |
438 pos[glyph_index].set(x + pango_units_to_double(glyph.geometry.x_offset), | 438 pos[glyph_index].set(x + pango_units_to_double(glyph.geometry.x_offset), |
439 y + pango_units_to_double(glyph.geometry.y_offset)); | 439 y + pango_units_to_double(glyph.geometry.y_offset)); |
440 x += pango_units_to_double(glyph.geometry.width); | 440 x += pango_units_to_double(glyph.geometry.width); |
441 | 441 |
(...skipping 29 matching lines...) Expand all Loading... |
471 UndoCompositionAndSelectionStyles(); | 471 UndoCompositionAndSelectionStyles(); |
472 } | 472 } |
473 | 473 |
474 GSList* RenderTextLinux::GetRunContainingCaret( | 474 GSList* RenderTextLinux::GetRunContainingCaret( |
475 const SelectionModel& caret) const { | 475 const SelectionModel& caret) const { |
476 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); | 476 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); |
477 LogicalCursorDirection affinity = caret.caret_affinity(); | 477 LogicalCursorDirection affinity = caret.caret_affinity(); |
478 GSList* run = current_line_->runs; | 478 GSList* run = current_line_->runs; |
479 while (run) { | 479 while (run) { |
480 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; | 480 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; |
481 ui::Range item_range(item->offset, item->offset + item->length); | 481 gfx::Range item_range(item->offset, item->offset + item->length); |
482 if (RangeContainsCaret(item_range, position, affinity)) | 482 if (RangeContainsCaret(item_range, position, affinity)) |
483 return run; | 483 return run; |
484 run = run->next; | 484 run = run->next; |
485 } | 485 } |
486 return NULL; | 486 return NULL; |
487 } | 487 } |
488 | 488 |
489 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun( | 489 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun( |
490 const PangoItem* item) { | 490 const PangoItem* item) { |
491 size_t caret = IndexOfAdjacentGrapheme( | 491 size_t caret = IndexOfAdjacentGrapheme( |
(...skipping 12 matching lines...) Expand all Loading... |
504 int glyph_index) const { | 504 int glyph_index) const { |
505 return LayoutIndexToTextIndex(run->item->offset + | 505 return LayoutIndexToTextIndex(run->item->offset + |
506 run->glyphs->log_clusters[glyph_index]); | 506 run->glyphs->log_clusters[glyph_index]); |
507 } | 507 } |
508 | 508 |
509 RenderText* RenderText::CreateInstance() { | 509 RenderText* RenderText::CreateInstance() { |
510 return new RenderTextLinux; | 510 return new RenderTextLinux; |
511 } | 511 } |
512 | 512 |
513 } // namespace gfx | 513 } // namespace gfx |
OLD | NEW |