| 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 |