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

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

Issue 9390022: Simplify handling of BiDi cursor movement (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: make set_selection_start private, fix accidental inclusion of local hacks Created 8 years, 10 months 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
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_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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 71
72 base::i18n::TextDirection RenderTextLinux::GetTextDirection() { 72 base::i18n::TextDirection RenderTextLinux::GetTextDirection() {
73 EnsureLayout(); 73 EnsureLayout();
74 74
75 PangoDirection base_dir = pango_find_base_dir(layout_text_, -1); 75 PangoDirection base_dir = pango_find_base_dir(layout_text_, -1);
76 if (base_dir == PANGO_DIRECTION_RTL || base_dir == PANGO_DIRECTION_WEAK_RTL) 76 if (base_dir == PANGO_DIRECTION_RTL || base_dir == PANGO_DIRECTION_WEAK_RTL)
77 return base::i18n::RIGHT_TO_LEFT; 77 return base::i18n::RIGHT_TO_LEFT;
78 return base::i18n::LEFT_TO_RIGHT; 78 return base::i18n::LEFT_TO_RIGHT;
79 } 79 }
80 80
81 int RenderTextLinux::GetStringWidth() { 81 Size RenderTextLinux::GetStringSize() {
82 EnsureLayout(); 82 EnsureLayout();
83 int width; 83 int width = 0, height = 0;
84 pango_layout_get_pixel_size(layout_, &width, NULL); 84 pango_layout_get_pixel_size(layout_, &width, &height);
85 return width; 85 return Size(width, height);
86 } 86 }
87 87
88 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) { 88 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
89 EnsureLayout(); 89 EnsureLayout();
90 90
91 if (text().empty()) 91 if (text().empty())
92 return SelectionModel(0, 0, SelectionModel::LEADING); 92 return SelectionModel(0, CURSOR_FORWARD);
93 93
94 Point p(ToTextPoint(point)); 94 Point p(ToTextPoint(point));
95 95
96 // When the point is outside of text, return HOME/END position. 96 // When the point is outside of text, return HOME/END position.
97 if (p.x() < 0) 97 if (p.x() < 0)
98 return EdgeSelectionModel(CURSOR_LEFT); 98 return EdgeSelectionModel(CURSOR_LEFT);
99 else if (p.x() > GetStringWidth()) 99 else if (p.x() > GetStringSize().width())
100 return EdgeSelectionModel(CURSOR_RIGHT); 100 return EdgeSelectionModel(CURSOR_RIGHT);
101 101
102 int caret_pos, trailing; 102 int caret_pos, trailing;
msw 2012/02/28 22:51:32 Init these locals to 0.
benrg 2012/03/07 01:04:44 Done (under protest -- though I don't feel all tha
103 pango_layout_xy_to_index(layout_, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE, 103 pango_layout_xy_to_index(layout_, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
104 &caret_pos, &trailing); 104 &caret_pos, &trailing);
105 105
106 size_t selection_end = caret_pos; 106 DCHECK_GE(trailing, 0);
107 if (trailing > 0) { 107 if (trailing > 0) {
108 const char* ch = g_utf8_offset_to_pointer(layout_text_ + caret_pos, 108 caret_pos = g_utf8_offset_to_pointer(layout_text_ + caret_pos,
109 trailing); 109 trailing) - layout_text_;
110 DCHECK_GE(ch, layout_text_); 110 DCHECK_LE(static_cast<size_t>(caret_pos), layout_text_len_);
111 DCHECK_LE(ch, layout_text_ + layout_text_len_);
112 selection_end = ch - layout_text_;
113 } 111 }
114 112
115 return SelectionModel( 113 return SelectionModel(Utf8IndexToUtf16Index(caret_pos),
116 Utf8IndexToUtf16Index(selection_end), 114 (trailing > 0) ? CURSOR_BACKWARD : CURSOR_FORWARD);
117 Utf8IndexToUtf16Index(caret_pos),
118 trailing > 0 ? SelectionModel::TRAILING : SelectionModel::LEADING);
119 } 115 }
120 116
121 Rect RenderTextLinux::GetCursorBounds(const SelectionModel& selection,
122 bool insert_mode) {
123 EnsureLayout();
124
125 size_t caret_pos = insert_mode ? selection.caret_pos() :
126 selection.selection_end();
127 PangoRectangle pos;
128 pango_layout_index_to_pos(layout_, Utf16IndexToUtf8Index(caret_pos), &pos);
129
130 SelectionModel::CaretPlacement caret_placement = selection.caret_placement();
131 int x = pos.x;
132 if ((insert_mode && caret_placement == SelectionModel::TRAILING) ||
133 (!insert_mode && pos.width < 0))
134 x += pos.width;
135 x = PANGO_PIXELS(x);
136
137 int h = std::min(display_rect().height(), PANGO_PIXELS(pos.height));
138 Rect bounds(x, (display_rect().height() - h) / 2, 0, h);
139 bounds.set_origin(ToViewPoint(bounds.origin()));
140
141 if (!insert_mode)
142 bounds.set_width(PANGO_PIXELS(std::abs(pos.width)));
143
144 return bounds;
145 }
146
147 // Assume caret_pos in |current| is n, 'l' represents leading in
148 // caret_placement and 't' represents trailing in caret_placement. Following
149 // is the calculation from (caret_pos, caret_placement) in |current| to
150 // (selection_end, caret_pos, caret_placement) when moving cursor left/right by
151 // one grapheme (for simplicity, assume each grapheme is one character).
152 // If n is in LTR (if moving left) or RTL (if moving right) run,
153 // (n, t) --> (n, n, l).
154 // (n, l) --> (n-1, n-1, l) if n is inside run (not at boundary).
155 // (n, l) --> goto across run case if n is at run boundary.
156 // Otherwise,
157 // (n, l) --> (n+1, n, t).
158 // (n, t) --> (n+2, n+1, t) if n is inside run.
159 // (n, t) --> goto across run case if n is at run boundary.
160 // If n is at run boundary, get its visually left/right run,
161 // If left/right run is LTR/RTL run,
162 // (n, t) --> (left/right run's end, left/right run's end, l).
163 // Otherwise,
164 // (n, t) --> (left/right run's begin + 1, left/right run's begin, t).
165 SelectionModel RenderTextLinux::AdjacentCharSelectionModel( 117 SelectionModel RenderTextLinux::AdjacentCharSelectionModel(
166 const SelectionModel& selection, 118 const SelectionModel& selection,
167 VisualCursorDirection direction) { 119 VisualCursorDirection direction) {
168 size_t caret = selection.caret_pos(); 120 GSList* run = GetRunContainingCaret(selection);
169 SelectionModel::CaretPlacement caret_placement = selection.caret_placement(); 121 if (!run) {
170 GSList* run = GetRunContainingPosition(caret); 122 // The cursor is not in any run: we're at the visual and logical edge.
171 DCHECK(run); 123 SelectionModel edge = EdgeSelectionModel(direction);
172 124 if (edge.caret_pos() == selection.caret_pos())
173 PangoLayoutRun* layout_run = reinterpret_cast<PangoLayoutRun*>(run->data); 125 return edge;
174 PangoItem* item = layout_run->item; 126 else
175 size_t run_start = Utf8IndexToUtf16Index(item->offset); 127 run = (direction == CURSOR_RIGHT) ?
176 size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length); 128 current_line_->runs : g_slist_last(current_line_->runs);
177 129 } else {
178 if (!IsForwardMotion(direction, item)) { 130 // If the cursor is moving within the current run, just move it by one
179 if (caret_placement == SelectionModel::TRAILING) 131 // grapheme in the appropriate direction.
180 return SelectionModel(caret, caret, SelectionModel::LEADING); 132 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
181 else if (caret > run_start) { 133 size_t caret = selection.caret_pos();
182 caret = IndexOfAdjacentGrapheme(caret, CURSOR_BACKWARD); 134 if (IsForwardMotion(direction, item)) {
183 return SelectionModel(caret, caret, SelectionModel::LEADING); 135 if (caret < Utf8IndexToUtf16Index(item->offset + item->length)) {
136 caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD);
137 return SelectionModel(caret, CURSOR_BACKWARD);
138 }
139 } else {
140 if (caret > Utf8IndexToUtf16Index(item->offset)) {
141 caret = IndexOfAdjacentGrapheme(caret, CURSOR_BACKWARD);
142 return SelectionModel(caret, CURSOR_FORWARD);
143 }
184 } 144 }
185 } else { 145 // The cursor is at the edge of a run; move to the visually adjacent run.
186 if (caret_placement == SelectionModel::LEADING) { 146 // TODO(xji): Keep a vector of runs to avoid using a singly-linked list.
187 size_t cursor = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD); 147 run = (direction == CURSOR_RIGHT) ?
188 return SelectionModel(cursor, caret, SelectionModel::TRAILING); 148 run->next : GSListPrevious(current_line_->runs, run);
189 } else if (selection.selection_end() < run_end) { 149 if (!run)
190 caret = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD); 150 return EdgeSelectionModel(direction);
191 size_t cursor = IndexOfAdjacentGrapheme(caret, CURSOR_FORWARD);
192 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
193 }
194 } 151 }
195 152 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
196 // The character is at the edge of its run; advance to the adjacent visual
197 // run.
198 // TODO(xji): Keep a vector of runs to avoid using a singly-linked list.
199 GSList* adjacent_run = (direction == CURSOR_RIGHT) ?
200 run->next : GSListPrevious(current_line_->runs, run);
201 if (!adjacent_run)
202 return EdgeSelectionModel(direction);
203
204 item = reinterpret_cast<PangoLayoutRun*>(adjacent_run->data)->item;
205 return IsForwardMotion(direction, item) ? 153 return IsForwardMotion(direction, item) ?
206 FirstSelectionModelInsideRun(item) : LastSelectionModelInsideRun(item); 154 FirstSelectionModelInsideRun(item) : LastSelectionModelInsideRun(item);
207 } 155 }
208 156
209 SelectionModel RenderTextLinux::AdjacentWordSelectionModel( 157 SelectionModel RenderTextLinux::AdjacentWordSelectionModel(
210 const SelectionModel& selection, 158 const SelectionModel& selection,
211 VisualCursorDirection direction) { 159 VisualCursorDirection direction) {
212 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); 160 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
213 bool success = iter.Init(); 161 bool success = iter.Init();
214 DCHECK(success); 162 DCHECK(success);
215 if (!success) 163 if (!success)
216 return selection; 164 return selection;
217 165
218 SelectionModel end = EdgeSelectionModel(direction);
219 SelectionModel cur(selection); 166 SelectionModel cur(selection);
220 while (!cur.Equals(end)) { 167 for (;;) {
221 cur = AdjacentCharSelectionModel(cur, direction); 168 cur = AdjacentCharSelectionModel(cur, direction);
222 size_t caret = cur.caret_pos(); 169 GSList* run = GetRunContainingCaret(cur);
223 GSList* run = GetRunContainingPosition(caret); 170 if (!run)
224 DCHECK(run); 171 break;
225 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; 172 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
226 size_t cursor = cur.selection_end(); 173 size_t cursor = cur.caret_pos();
227 if (IsForwardMotion(direction, item) ? 174 if (IsForwardMotion(direction, item) ?
228 iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor)) 175 iter.IsEndOfWord(cursor) : iter.IsStartOfWord(cursor))
229 return cur; 176 break;
230 } 177 }
231 178
232 return end; 179 return cur;
233 }
234
235 SelectionModel RenderTextLinux::EdgeSelectionModel(
236 VisualCursorDirection direction) {
237 if (direction == GetVisualDirectionOfLogicalEnd()) {
238 // Advance to the logical end of the text.
239 GSList* run = current_line_->runs;
240 if (direction == CURSOR_RIGHT)
241 run = g_slist_last(run);
242 if (run) {
243 PangoLayoutRun* end_run = reinterpret_cast<PangoLayoutRun*>(run->data);
244 PangoItem* item = end_run->item;
245 if (IsForwardMotion(direction, item)) {
246 size_t caret = Utf8IndexToUtf16Index(
247 Utf8IndexOfAdjacentGrapheme(item->offset + item->length,
248 CURSOR_BACKWARD));
249 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
250 } else {
251 size_t caret = Utf8IndexToUtf16Index(item->offset);
252 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
253 }
254 }
255 }
256 return SelectionModel(0, 0, SelectionModel::LEADING);
257 } 180 }
258 181
259 void RenderTextLinux::SetSelectionModel(const SelectionModel& model) { 182 void RenderTextLinux::SetSelectionModel(const SelectionModel& model) {
260 if (GetSelectionStart() != model.selection_start() || 183 if (selection() != model.selection())
261 GetCursorPosition() != model.selection_end()) {
262 selection_visual_bounds_.clear(); 184 selection_visual_bounds_.clear();
263 }
264 185
265 RenderText::SetSelectionModel(model); 186 RenderText::SetSelectionModel(model);
266 } 187 }
267 188
268 std::vector<Rect> RenderTextLinux::GetSubstringBounds(size_t from, size_t to) { 189 void RenderTextLinux::GetGlyphBounds(size_t index,
269 DCHECK(from <= text().length()); 190 ui::Range* xspan,
270 DCHECK(to <= text().length()); 191 int* height) {
192 PangoRectangle pos;
193 pango_layout_index_to_pos(layout_, Utf16IndexToUtf8Index(index), &pos);
194 *xspan = ui::Range(PANGO_PIXELS(pos.x), PANGO_PIXELS(pos.x + pos.width));
195 *height = PANGO_PIXELS(pos.height);
196 }
271 197
272 if (from == to) 198 std::vector<Rect> RenderTextLinux::GetSubstringBounds(ui::Range range) {
199 DCHECK_LE(range.GetMax(), text().length());
200
201 if (range.is_empty())
273 return std::vector<Rect>(); 202 return std::vector<Rect>();
274 203
275 EnsureLayout(); 204 EnsureLayout();
276 205 if (range == selection())
277 if (from == GetSelectionStart() && to == GetCursorPosition())
278 return GetSelectionBounds(); 206 return GetSelectionBounds();
279 else 207 return CalculateSubstringBounds(range);
280 return CalculateSubstringBounds(from, to);
281 } 208 }
282 209
283 bool RenderTextLinux::IsCursorablePosition(size_t position) { 210 bool RenderTextLinux::IsCursorablePosition(size_t position) {
284 if (position == 0 && text().empty()) 211 if (position == 0 && text().empty())
285 return true; 212 return true;
286 213
287 EnsureLayout(); 214 EnsureLayout();
288 return (position < static_cast<size_t>(num_log_attrs_) && 215 return (position < static_cast<size_t>(num_log_attrs_) &&
289 log_attrs_[position].is_cursor_position); 216 log_attrs_[position].is_cursor_position);
290 } 217 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 size_t RenderTextLinux::IndexOfAdjacentGrapheme( 393 size_t RenderTextLinux::IndexOfAdjacentGrapheme(
467 size_t index, 394 size_t index,
468 LogicalCursorDirection direction) { 395 LogicalCursorDirection direction) {
469 if (index > text().length()) 396 if (index > text().length())
470 return text().length(); 397 return text().length();
471 EnsureLayout(); 398 EnsureLayout();
472 return Utf8IndexToUtf16Index( 399 return Utf8IndexToUtf16Index(
473 Utf8IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), direction)); 400 Utf8IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), direction));
474 } 401 }
475 402
476 GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const { 403 GSList* RenderTextLinux::GetRunContainingCaret(
404 const SelectionModel& caret) const {
405 size_t position = Utf16IndexToUtf8Index(caret.caret_pos());
406 LogicalCursorDirection affinity = caret.caret_affinity();
477 GSList* run = current_line_->runs; 407 GSList* run = current_line_->runs;
478 while (run) { 408 while (run) {
479 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; 409 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
480 size_t run_start = Utf8IndexToUtf16Index(item->offset); 410 ui::Range item_range(item->offset, item->offset + item->length);
481 size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length); 411 if (RangeContainsCaret(item_range, position, affinity))
482
483 if (position >= run_start && position < run_end)
484 return run; 412 return run;
485 run = run->next; 413 run = run->next;
486 } 414 }
487 return NULL; 415 return NULL;
488 } 416 }
489 417
490 size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme( 418 size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme(
491 size_t utf8_index_of_current_grapheme, 419 size_t utf8_index_of_current_grapheme,
492 LogicalCursorDirection direction) const { 420 LogicalCursorDirection direction) const {
493 const char* ch = layout_text_ + utf8_index_of_current_grapheme; 421 const char* ch = layout_text_ + utf8_index_of_current_grapheme;
(...skipping 14 matching lines...) Expand all
508 !log_attrs_[char_offset].is_cursor_position); 436 !log_attrs_[char_offset].is_cursor_position);
509 } 437 }
510 } 438 }
511 439
512 ch = g_utf8_offset_to_pointer(ch, char_offset - start_char_offset); 440 ch = g_utf8_offset_to_pointer(ch, char_offset - start_char_offset);
513 return static_cast<size_t>(ch - layout_text_); 441 return static_cast<size_t>(ch - layout_text_);
514 } 442 }
515 443
516 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun( 444 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun(
517 const PangoItem* item) const { 445 const PangoItem* item) const {
518 size_t caret = Utf8IndexToUtf16Index(item->offset);
519 size_t cursor = Utf8IndexToUtf16Index( 446 size_t cursor = Utf8IndexToUtf16Index(
520 Utf8IndexOfAdjacentGrapheme(item->offset, CURSOR_FORWARD)); 447 Utf8IndexOfAdjacentGrapheme(item->offset, CURSOR_FORWARD));
521 return SelectionModel(cursor, caret, SelectionModel::TRAILING); 448 return SelectionModel(cursor, CURSOR_BACKWARD);
522 } 449 }
523 450
524 SelectionModel RenderTextLinux::LastSelectionModelInsideRun( 451 SelectionModel RenderTextLinux::LastSelectionModelInsideRun(
525 const PangoItem* item) const { 452 const PangoItem* item) const {
526 size_t caret = Utf8IndexToUtf16Index(Utf8IndexOfAdjacentGrapheme( 453 size_t caret = Utf8IndexToUtf16Index(Utf8IndexOfAdjacentGrapheme(
527 item->offset + item->length, CURSOR_BACKWARD)); 454 item->offset + item->length, CURSOR_BACKWARD));
528 return SelectionModel(caret, caret, SelectionModel::LEADING); 455 return SelectionModel(caret, CURSOR_FORWARD);
529 } 456 }
530 457
531 void RenderTextLinux::ResetLayout() { 458 void RenderTextLinux::ResetLayout() {
532 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every 459 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every
533 // operation that triggers ResetLayout(). 460 // operation that triggers ResetLayout().
534 if (layout_) { 461 if (layout_) {
535 g_object_unref(layout_); 462 g_object_unref(layout_);
536 layout_ = NULL; 463 layout_ = NULL;
537 } 464 }
538 if (current_line_) { 465 if (current_line_) {
(...skipping 29 matching lines...) Expand all
568 495
569 size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const { 496 size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const {
570 int32_t utf16_index = 0; 497 int32_t utf16_index = 0;
571 UErrorCode ec = U_ZERO_ERROR; 498 UErrorCode ec = U_ZERO_ERROR;
572 u_strFromUTF8(NULL, 0, &utf16_index, layout_text_, index, &ec); 499 u_strFromUTF8(NULL, 0, &utf16_index, layout_text_, index, &ec);
573 DCHECK(ec == U_BUFFER_OVERFLOW_ERROR || 500 DCHECK(ec == U_BUFFER_OVERFLOW_ERROR ||
574 ec == U_STRING_NOT_TERMINATED_WARNING); 501 ec == U_STRING_NOT_TERMINATED_WARNING);
575 return utf16_index; 502 return utf16_index;
576 } 503 }
577 504
578 std::vector<Rect> RenderTextLinux::CalculateSubstringBounds(size_t from, 505 std::vector<Rect> RenderTextLinux::CalculateSubstringBounds(ui::Range range) {
579 size_t to) {
580 int* ranges; 506 int* ranges;
581 int n_ranges; 507 int n_ranges;
582 size_t from_in_utf8 = Utf16IndexToUtf8Index(from);
583 size_t to_in_utf8 = Utf16IndexToUtf8Index(to);
584 pango_layout_line_get_x_ranges( 508 pango_layout_line_get_x_ranges(
585 current_line_, 509 current_line_,
586 std::min(from_in_utf8, to_in_utf8), 510 Utf16IndexToUtf8Index(range.GetMin()),
587 std::max(from_in_utf8, to_in_utf8), 511 Utf16IndexToUtf8Index(range.GetMax()),
588 &ranges, 512 &ranges,
589 &n_ranges); 513 &n_ranges);
590 514
591 int height; 515 int height;
592 pango_layout_get_pixel_size(layout_, NULL, &height); 516 pango_layout_get_pixel_size(layout_, NULL, &height);
593 517
594 int y = (display_rect().height() - height) / 2; 518 int y = (display_rect().height() - height) / 2;
595 519
596 std::vector<Rect> bounds; 520 std::vector<Rect> bounds;
597 for (int i = 0; i < n_ranges; ++i) { 521 for (int i = 0; i < n_ranges; ++i) {
598 int x = PANGO_PIXELS(ranges[2 * i]); 522 int x = PANGO_PIXELS(ranges[2 * i]);
599 int width = PANGO_PIXELS(ranges[2 * i + 1]) - x; 523 int width = PANGO_PIXELS(ranges[2 * i + 1]) - x;
600 Rect rect(x, y, width, height); 524 Rect rect(x, y, width, height);
601 rect.set_origin(ToViewPoint(rect.origin())); 525 rect.set_origin(ToViewPoint(rect.origin()));
602 bounds.push_back(rect); 526 bounds.push_back(rect);
603 } 527 }
604 g_free(ranges); 528 g_free(ranges);
605 return bounds; 529 return bounds;
606 } 530 }
607 531
608 std::vector<Rect> RenderTextLinux::GetSelectionBounds() { 532 std::vector<Rect> RenderTextLinux::GetSelectionBounds() {
609 if (selection_visual_bounds_.empty()) 533 if (selection_visual_bounds_.empty())
610 selection_visual_bounds_ = 534 selection_visual_bounds_ = CalculateSubstringBounds(selection());
611 CalculateSubstringBounds(GetSelectionStart(), GetCursorPosition());
612 return selection_visual_bounds_; 535 return selection_visual_bounds_;
613 } 536 }
614 537
615 } // namespace gfx 538 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698