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

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

Issue 8575020: Improve RenderTextWin font fallback. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: sync Created 9 years 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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.h" 5 #include "ui/gfx/render_text.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/i18n/break_iterator.h" 9 #include "base/i18n/break_iterator.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 split_style.range.set_end(new_range.start()); 60 split_style.range.set_end(new_range.start());
61 i = style_ranges->insert(i, split_style) + 1; 61 i = style_ranges->insert(i, split_style) + 1;
62 i->range.set_start(new_range.end()); 62 i->range.set_start(new_range.end());
63 break; 63 break;
64 } else if (i->range.start() < new_range.start()) { 64 } else if (i->range.start() < new_range.start()) {
65 i->range.set_end(new_range.start()); 65 i->range.set_end(new_range.start());
66 i++; 66 i++;
67 } else if (i->range.end() > new_range.end()) { 67 } else if (i->range.end() > new_range.end()) {
68 i->range.set_start(new_range.end()); 68 i->range.set_start(new_range.end());
69 break; 69 break;
70 } else 70 } else {
71 NOTREACHED(); 71 NOTREACHED();
72 }
72 } 73 }
73 // Add the new range in its sorted location. 74 // Add the new range in its sorted location.
74 style_ranges->insert(i, style_range); 75 style_ranges->insert(i, style_range);
75 } 76 }
76 77
77 } // namespace 78 } // namespace
78 79
79 namespace gfx { 80 namespace gfx {
80 81
81 StyleRange::StyleRange() 82 StyleRange::StyleRange()
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 if (break_type == WORD_BREAK) 180 if (break_type == WORD_BREAK)
180 position = GetRightSelectionModel(position, break_type); 181 position = GetRightSelectionModel(position, break_type);
181 } else { 182 } else {
182 position = GetRightSelectionModel(position, break_type); 183 position = GetRightSelectionModel(position, break_type);
183 } 184 }
184 if (select) 185 if (select)
185 position.set_selection_start(GetSelectionStart()); 186 position.set_selection_start(GetSelectionStart());
186 MoveCursorTo(position); 187 MoveCursorTo(position);
187 } 188 }
188 189
189 bool RenderText::MoveCursorTo(const SelectionModel& selection_model) { 190 bool RenderText::MoveCursorTo(const SelectionModel& model) {
190 SelectionModel sel(selection_model); 191 SelectionModel sel(model);
191 size_t text_length = text().length(); 192 size_t text_length = text().length();
192 // Enforce valid selection model components. 193 // Enforce valid selection model components.
193 if (sel.selection_start() > text_length) 194 if (sel.selection_start() > text_length)
194 sel.set_selection_start(text_length); 195 sel.set_selection_start(text_length);
195 if (sel.selection_end() > text_length) 196 if (sel.selection_end() > text_length)
196 sel.set_selection_end(text_length); 197 sel.set_selection_end(text_length);
197 // The current model only supports caret positions at valid character indices. 198 // The current model only supports caret positions at valid character indices.
198 if (text_length == 0) { 199 if (text_length == 0) {
199 sel.set_caret_pos(0); 200 sel.set_caret_pos(0);
200 sel.set_caret_placement(SelectionModel::LEADING); 201 sel.set_caret_placement(SelectionModel::LEADING);
201 } else if (sel.caret_pos() >= text_length) { 202 } else if (sel.caret_pos() >= text_length) {
202 SelectionModel end = GetTextDirection() == base::i18n::RIGHT_TO_LEFT ? 203 SelectionModel end = GetTextDirection() == base::i18n::RIGHT_TO_LEFT ?
203 LeftEndSelectionModel() : RightEndSelectionModel(); 204 LeftEndSelectionModel() : RightEndSelectionModel();
204 sel.set_caret_pos(end.caret_pos()); 205 sel.set_caret_pos(end.caret_pos());
205 sel.set_caret_placement(end.caret_placement()); 206 sel.set_caret_placement(end.caret_placement());
206 } 207 }
207 208
208 if (!IsCursorablePosition(sel.selection_start()) || 209 if (!IsCursorablePosition(sel.selection_start(), false) ||
209 !IsCursorablePosition(sel.selection_end()) || 210 !IsCursorablePosition(sel.selection_end(), false) ||
210 !IsCursorablePosition(sel.caret_pos())) 211 !IsCursorablePosition(sel.caret_pos(),
212 (sel.caret_placement() == SelectionModel::TRAILING))) {
xji 2011/11/29 21:15:48 I did not quite get the reason of introducing "boo
211 return false; 213 return false;
214 }
212 215
213 bool changed = !sel.Equals(selection_model_); 216 bool changed = !sel.Equals(selection_model_);
214 SetSelectionModel(sel); 217 SetSelectionModel(sel);
215 return changed; 218 return changed;
216 } 219 }
217 220
218 bool RenderText::MoveCursorTo(const Point& point, bool select) { 221 bool RenderText::MoveCursorTo(const Point& point, bool select) {
219 SelectionModel selection = FindCursorPosition(point); 222 SelectionModel selection = FindCursorPosition(point);
220 if (select) 223 if (select)
221 selection.set_selection_start(GetSelectionStart()); 224 selection.set_selection_start(GetSelectionStart());
222 return MoveCursorTo(selection); 225 return MoveCursorTo(selection);
223 } 226 }
224 227
225 bool RenderText::SelectRange(const ui::Range& range) { 228 bool RenderText::SelectRange(const ui::Range& range) {
226 size_t text_length = text().length(); 229 size_t text_length = text().length();
227 size_t start = std::min(range.start(), text_length); 230 size_t start = std::min(range.start(), text_length);
228 size_t end = std::min(range.end(), text_length); 231 size_t end = std::min(range.end(), text_length);
229 232
230 if (!IsCursorablePosition(start) || !IsCursorablePosition(end)) 233 if (!IsCursorablePosition(start, false) || !IsCursorablePosition(end, false))
231 return false; 234 return false;
232 235
233 size_t pos = end; 236 size_t pos = end;
234 SelectionModel::CaretPlacement placement = SelectionModel::LEADING; 237 SelectionModel::CaretPlacement placement = SelectionModel::LEADING;
235 if (start < end) { 238 if (start < end) {
236 pos = GetIndexOfPreviousGrapheme(end); 239 pos = GetIndexOfPreviousGrapheme(end);
237 DCHECK_LT(pos, end); 240 DCHECK_LT(pos, end);
238 placement = SelectionModel::TRAILING; 241 placement = SelectionModel::TRAILING;
239 } else if (end == text_length) { 242 } else if (end == text_length) {
240 SelectionModel boundary = GetTextDirection() == base::i18n::RIGHT_TO_LEFT ? 243 SelectionModel boundary = GetTextDirection() == base::i18n::RIGHT_TO_LEFT ?
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 int left_pos = 0; 406 int left_pos = 0;
404 int right = font.GetStringWidth(text()); 407 int right = font.GetStringWidth(text());
405 int right_pos = text().length(); 408 int right_pos = text().length();
406 409
407 int x = point.x() - (display_rect_.x() + GetUpdatedDisplayOffset().x()); 410 int x = point.x() - (display_rect_.x() + GetUpdatedDisplayOffset().x());
408 if (x <= left) return SelectionModel(left_pos); 411 if (x <= left) return SelectionModel(left_pos);
409 if (x >= right) return SelectionModel(right_pos); 412 if (x >= right) return SelectionModel(right_pos);
410 // binary searching the cursor position. 413 // binary searching the cursor position.
411 // TODO(oshima): use the center of character instead of edge. 414 // TODO(oshima): use the center of character instead of edge.
412 // Binary search may not work for language like Arabic. 415 // Binary search may not work for language like Arabic.
413 while (std::abs(static_cast<long>(right_pos - left_pos)) > 1) { 416 while (std::abs(right_pos - left_pos) > 1) {
414 int pivot_pos = left_pos + (right_pos - left_pos) / 2; 417 int pivot_pos = left_pos + (right_pos - left_pos) / 2;
415 int pivot = font.GetStringWidth(text().substr(0, pivot_pos)); 418 int pivot = font.GetStringWidth(text().substr(0, pivot_pos));
416 if (pivot < x) { 419 if (pivot < x) {
417 left = pivot; 420 left = pivot;
418 left_pos = pivot_pos; 421 left_pos = pivot_pos;
419 } else if (pivot == x) { 422 } else if (pivot == x) {
420 return SelectionModel(pivot_pos); 423 return SelectionModel(pivot_pos);
421 } else { 424 } else {
422 right = pivot; 425 right = pivot;
423 right_pos = pivot_pos; 426 right_pos = pivot_pos;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 475
473 const Point& RenderText::GetUpdatedDisplayOffset() { 476 const Point& RenderText::GetUpdatedDisplayOffset() {
474 UpdateCachedBoundsAndOffset(); 477 UpdateCachedBoundsAndOffset();
475 return display_offset_; 478 return display_offset_;
476 } 479 }
477 480
478 SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current, 481 SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current,
479 BreakType break_type) { 482 BreakType break_type) {
480 if (break_type == LINE_BREAK) 483 if (break_type == LINE_BREAK)
481 return LeftEndSelectionModel(); 484 return LeftEndSelectionModel();
482 size_t pos = std::max(static_cast<long>(current.selection_end() - 1), 485 size_t pos = std::max<int>(current.selection_end() - 1, 0);
483 static_cast<long>(0));
484 if (break_type == CHARACTER_BREAK) 486 if (break_type == CHARACTER_BREAK)
485 return SelectionModel(pos, pos, SelectionModel::LEADING); 487 return SelectionModel(pos, pos, SelectionModel::LEADING);
486 488
487 // Notes: We always iterate words from the beginning. 489 // Notes: We always iterate words from the beginning.
488 // This is probably fast enough for our usage, but we may 490 // This is probably fast enough for our usage, but we may
489 // want to modify WordIterator so that it can start from the 491 // want to modify WordIterator so that it can start from the
490 // middle of string and advance backwards. 492 // middle of string and advance backwards.
491 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); 493 base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD);
492 bool success = iter.Init(); 494 bool success = iter.Init();
493 DCHECK(success); 495 DCHECK(success);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 if (base::i18n::IsRTL()) 605 if (base::i18n::IsRTL())
604 p.Offset(display_rect().width() - GetStringWidth() - 1, 0); 606 p.Offset(display_rect().width() - GetStringWidth() - 1, 0);
605 return p; 607 return p;
606 } 608 }
607 609
608 void RenderText::SetSelectionModel(const SelectionModel& selection_model) { 610 void RenderText::SetSelectionModel(const SelectionModel& selection_model) {
609 DCHECK_LE(selection_model.selection_start(), text().length()); 611 DCHECK_LE(selection_model.selection_start(), text().length());
610 selection_model_.set_selection_start(selection_model.selection_start()); 612 selection_model_.set_selection_start(selection_model.selection_start());
611 DCHECK_LE(selection_model.selection_end(), text().length()); 613 DCHECK_LE(selection_model.selection_end(), text().length());
612 selection_model_.set_selection_end(selection_model.selection_end()); 614 selection_model_.set_selection_end(selection_model.selection_end());
613 DCHECK_LT(selection_model.caret_pos(), 615 DCHECK_LT(selection_model.caret_pos(), std::max<size_t>(text().length(), 1));
614 std::max(text().length(), static_cast<size_t>(1)));
615 selection_model_.set_caret_pos(selection_model.caret_pos()); 616 selection_model_.set_caret_pos(selection_model.caret_pos());
616 selection_model_.set_caret_placement(selection_model.caret_placement()); 617 selection_model_.set_caret_placement(selection_model.caret_placement());
617 618
618 cached_bounds_and_offset_valid_ = false; 619 cached_bounds_and_offset_valid_ = false;
619 UpdateLayout(); 620 UpdateLayout();
620 } 621 }
621 622
622 void RenderText::MoveCursorTo(size_t position, bool select) { 623 void RenderText::MoveCursorTo(size_t position, bool select) {
623 size_t cursor = std::min(position, text().length()); 624 size_t cursor = std::min(position, text().length());
624 size_t caret_pos = GetIndexOfPreviousGrapheme(cursor); 625 size_t caret_pos = GetIndexOfPreviousGrapheme(cursor);
625 SelectionModel::CaretPlacement placement = (caret_pos == cursor) ? 626 SelectionModel::CaretPlacement placement = (caret_pos == cursor) ?
626 SelectionModel::LEADING : SelectionModel::TRAILING; 627 SelectionModel::LEADING : SelectionModel::TRAILING;
627 size_t selection_start = select ? GetSelectionStart() : cursor; 628 size_t selection_start = select ? GetSelectionStart() : cursor;
628 if (IsCursorablePosition(cursor)) { 629 if (IsCursorablePosition(cursor, false)) {
629 SelectionModel sel(selection_start, cursor, caret_pos, placement); 630 SelectionModel sel(selection_start, cursor, caret_pos, placement);
630 SetSelectionModel(sel); 631 SetSelectionModel(sel);
631 } 632 }
632 } 633 }
633 634
634 void RenderText::UpdateCachedBoundsAndOffset() { 635 void RenderText::UpdateCachedBoundsAndOffset() {
635 if (cached_bounds_and_offset_valid_) 636 if (cached_bounds_and_offset_valid_)
636 return; 637 return;
637 // First, set the valid flag true to calculate the current cursor bounds using 638 // First, set the valid flag true to calculate the current cursor bounds using
638 // the stale |display_offset_|. Applying |delta_offset| at the end of this 639 // the stale |display_offset_|. Applying |delta_offset| at the end of this
(...skipping 19 matching lines...) Expand all
658 // LTR character. 659 // LTR character.
659 // 660 //
660 // Pan to show the cursor when it overflows to the left. 661 // Pan to show the cursor when it overflows to the left.
661 delta_offset = display_rect_.x() - cursor_bounds_.x(); 662 delta_offset = display_rect_.x() - cursor_bounds_.x();
662 } 663 }
663 display_offset_.Offset(delta_offset, 0); 664 display_offset_.Offset(delta_offset, 0);
664 cursor_bounds_.Offset(delta_offset, 0); 665 cursor_bounds_.Offset(delta_offset, 0);
665 } 666 }
666 667
667 } // namespace gfx 668 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698