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

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

Issue 7511029: Implement Pango RenderText for Linux. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: fix compilation error. using ICU functions for utf8/utf16 conversion Created 9 years, 4 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) 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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 177
178 void RenderText::SetDisplayRect(const Rect& r) { 178 void RenderText::SetDisplayRect(const Rect& r) {
179 display_rect_ = r; 179 display_rect_ = r;
180 cached_bounds_and_offset_valid_ = false; 180 cached_bounds_and_offset_valid_ = false;
181 } 181 }
182 182
183 size_t RenderText::GetCursorPosition() const { 183 size_t RenderText::GetCursorPosition() const {
184 return selection_model_.selection_end(); 184 return selection_model_.selection_end();
185 } 185 }
186 186
187 void RenderText::SetCursorPosition(const size_t position) { 187 void RenderText::SetCursorPosition(size_t position) {
188 SelectionModel sel(selection_model()); 188 MoveCursorTo(position, false);
189 sel.set_selection_start(position);
190 sel.set_selection_end(position);
191 sel.set_caret_pos(GetIndexOfPreviousGrapheme(position));
192 sel.set_caret_placement(SelectionModel::TRAILING);
193 SetSelectionModel(sel);
194 } 189 }
195 190
196 void RenderText::MoveCursorLeft(BreakType break_type, bool select) { 191 void RenderText::MoveCursorLeft(BreakType break_type, bool select) {
197 SelectionModel position(selection_model()); 192 SelectionModel position(selection_model());
198 position.set_selection_start(GetCursorPosition()); 193 position.set_selection_start(GetCursorPosition());
199 // Cancelling a selection moves to the edge of the selection. 194 // Cancelling a selection moves to the edge of the selection.
200 if (break_type != LINE_BREAK && !EmptySelection() && !select) { 195 if (break_type != LINE_BREAK && !EmptySelection() && !select) {
201 // Use the selection start if it is left of the selection end. 196 // Use the selection start if it is left of the selection end.
202 SelectionModel selection_start(GetSelectionStart(), GetSelectionStart(), 197 SelectionModel selection_start = GetSelectionModelForSelectionStart();
msw 2011/08/23 08:01:01 Remove the extra space after '='.
xji 2011/08/23 23:52:52 Done.
203 SelectionModel::LEADING);
204 if (GetCursorBounds(selection_start, false).x() < 198 if (GetCursorBounds(selection_start, false).x() <
205 GetCursorBounds(position, false).x()) 199 GetCursorBounds(position, false).x())
206 position = selection_start; 200 position = selection_start;
207 // For word breaks, use the nearest word boundary left of the selection. 201 // For word breaks, use the nearest word boundary left of the selection.
208 if (break_type == WORD_BREAK) 202 if (break_type == WORD_BREAK)
209 position = GetLeftSelectionModel(position, break_type); 203 position = GetLeftSelectionModel(position, break_type);
210 } else { 204 } else {
211 position = GetLeftSelectionModel(position, break_type); 205 position = GetLeftSelectionModel(position, break_type);
212 } 206 }
213 if (select) 207 if (select)
214 position.set_selection_start(GetSelectionStart()); 208 position.set_selection_start(GetSelectionStart());
215 MoveCursorTo(position); 209 MoveCursorTo(position);
216 } 210 }
217 211
218 void RenderText::MoveCursorRight(BreakType break_type, bool select) { 212 void RenderText::MoveCursorRight(BreakType break_type, bool select) {
219 SelectionModel position(selection_model()); 213 SelectionModel position(selection_model());
220 position.set_selection_start(GetCursorPosition()); 214 position.set_selection_start(GetCursorPosition());
221 // Cancelling a selection moves to the edge of the selection. 215 // Cancelling a selection moves to the edge of the selection.
222 if (break_type != LINE_BREAK && !EmptySelection() && !select) { 216 if (break_type != LINE_BREAK && !EmptySelection() && !select) {
223 // Use the selection start if it is right of the selection end. 217 // Use the selection start if it is right of the selection end.
224 SelectionModel selection_start(GetSelectionStart(), GetSelectionStart(), 218 SelectionModel selection_start = GetSelectionModelForSelectionStart();
225 SelectionModel::LEADING);
226 if (GetCursorBounds(selection_start, false).x() > 219 if (GetCursorBounds(selection_start, false).x() >
227 GetCursorBounds(position, false).x()) 220 GetCursorBounds(position, false).x())
228 position = selection_start; 221 position = selection_start;
229 // For word breaks, use the nearest word boundary right of the selection. 222 // For word breaks, use the nearest word boundary right of the selection.
230 if (break_type == WORD_BREAK) 223 if (break_type == WORD_BREAK)
231 position = GetRightSelectionModel(position, break_type); 224 position = GetRightSelectionModel(position, break_type);
232 } else { 225 } else {
233 position = GetRightSelectionModel(position, break_type); 226 position = GetRightSelectionModel(position, break_type);
234 } 227 }
235 if (select) 228 if (select)
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 } 335 }
343 336
344 void RenderText::ApplyDefaultStyle() { 337 void RenderText::ApplyDefaultStyle() {
345 style_ranges_.clear(); 338 style_ranges_.clear();
346 StyleRange style = StyleRange(default_style_); 339 StyleRange style = StyleRange(default_style_);
347 style.range.set_end(text_.length()); 340 style.range.set_end(text_.length());
348 style_ranges_.push_back(style); 341 style_ranges_.push_back(style);
349 cached_bounds_and_offset_valid_ = false; 342 cached_bounds_and_offset_valid_ = false;
350 } 343 }
351 344
352 base::i18n::TextDirection RenderText::GetTextDirection() const { 345 base::i18n::TextDirection RenderText::GetTextDirection() {
353 // TODO(msw): Bidi implementation, intended to replace the functionality added 346 // TODO(msw): Bidi implementation, intended to replace the functionality added
354 // in crrev.com/91881 (discussed in codereview.chromium.org/7324011). 347 // in crrev.com/91881 (discussed in codereview.chromium.org/7324011).
348 if (base::i18n::IsRTL())
349 return base::i18n::RIGHT_TO_LEFT;
355 return base::i18n::LEFT_TO_RIGHT; 350 return base::i18n::LEFT_TO_RIGHT;
356 } 351 }
357 352
358 int RenderText::GetStringWidth() { 353 int RenderText::GetStringWidth() {
359 return default_style_.font.GetStringWidth(text()); 354 return default_style_.font.GetStringWidth(text());
360 } 355 }
361 356
362 void RenderText::Draw(Canvas* canvas) { 357 void RenderText::Draw(Canvas* canvas) {
363 // Clip the canvas to the text display area. 358 // Clip the canvas to the text display area.
364 canvas->ClipRectInt(display_rect_.x(), display_rect_.y(), 359 canvas->ClipRectInt(display_rect_.x(), display_rect_.y(),
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 // Apply a selection style override to a copy of the style ranges. 564 // Apply a selection style override to a copy of the style ranges.
570 if (!EmptySelection()) { 565 if (!EmptySelection()) {
571 StyleRange selection_style(default_style_); 566 StyleRange selection_style(default_style_);
572 selection_style.foreground = kSelectedTextColor; 567 selection_style.foreground = kSelectedTextColor;
573 selection_style.range.set_start(MinOfSelection()); 568 selection_style.range.set_start(MinOfSelection());
574 selection_style.range.set_end(MaxOfSelection()); 569 selection_style.range.set_end(MaxOfSelection());
575 ApplyStyleRangeImpl(style_ranges, selection_style); 570 ApplyStyleRangeImpl(style_ranges, selection_style);
576 } 571 }
577 } 572 }
578 573
574 Point RenderText::ToTextPoint(const Point& point) {
575 Point p(point.Subtract(display_rect_.origin()));
576 p = p.Subtract(GetUpdatedDisplayOffset());
577 if (base::i18n::IsRTL())
578 p.Offset(GetStringWidth() - display_rect_.width() + 1, 0);
579 return p;
580 }
581
582 Point RenderText::ToViewPoint(const Point& point) {
583 Point p(point.Add(display_rect_.origin()));
584 p = p.Add(GetUpdatedDisplayOffset());
585 if (base::i18n::IsRTL())
586 p.Offset(display_rect_.width() - GetStringWidth() - 1, 0);
587 return p;
588 }
589
590 void RenderText::MoveCursorTo(size_t position, bool select) {
591 size_t caret_pos = GetIndexOfPreviousGrapheme(position);
592 SelectionModel::CaretPlacement placement = (caret_pos == position) ?
593 SelectionModel::LEADING : SelectionModel::TRAILING;
594 size_t selection_start = select ? GetSelectionStart() : position;
595 SelectionModel sel(selection_start, position, caret_pos, placement);
596 SetSelectionModel(sel);
597 }
598
579 bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) { 599 bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) {
580 return pos == 0 || (u_isalnum(text()[pos - 1]) && !u_isalnum(text()[pos])) || 600 return pos == 0 || (u_isalnum(text()[pos - 1]) && !u_isalnum(text()[pos])) ||
581 (!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos])); 601 (!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos]));
582 } 602 }
583 603
584 void RenderText::UpdateCachedBoundsAndOffset() { 604 void RenderText::UpdateCachedBoundsAndOffset() {
585 if (cached_bounds_and_offset_valid_) 605 if (cached_bounds_and_offset_valid_)
586 return; 606 return;
587 // First, set the valid flag true to calculate the current cursor bounds using 607 // First, set the valid flag true to calculate the current cursor bounds using
588 // the stale |display_offset_|. Applying |delta_offset| at the end of this 608 // the stale |display_offset_|. Applying |delta_offset| at the end of this
589 // function will set |cursor_bounds_| and |display_offset_| to correct values. 609 // function will set |cursor_bounds_| and |display_offset_| to correct values.
590 cached_bounds_and_offset_valid_ = true; 610 cached_bounds_and_offset_valid_ = true;
591 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_); 611 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_);
592 cursor_bounds_.set_width(std::max(cursor_bounds_.width(), 1)); 612 cursor_bounds_.set_width(std::max(cursor_bounds_.width(), 1));
593 // Update |display_offset_| to ensure the current cursor is visible. 613 // Update |display_offset_| to ensure the current cursor is visible.
594 int display_width = display_rect_.width(); 614 int display_width = display_rect_.width();
595 int string_width = GetStringWidth(); 615 int string_width = GetStringWidth();
596 int delta_offset = 0; 616 int delta_offset = 0;
597 if (string_width < display_width) { 617 if (string_width < display_width) {
598 // Show all text whenever the text fits to the size. 618 // Show all text whenever the text fits to the size.
599 delta_offset = -display_offset_.x(); 619 delta_offset = -display_offset_.x();
600 } else if (cursor_bounds_.right() > display_rect_.right()) { 620 } else if (cursor_bounds_.right() > display_rect_.right()) {
621 // TODO(xji): when the character overflow is a RTL character, currently, if
622 // we pan cursor at the rightmost position, the entered RTL character is not
623 // displayed. Should pan cursor to show the last logical characters.
624 // BTW, Firefox has the same issue.
msw 2011/08/23 08:01:01 No need to call out Firefox here, we can alert the
xji 2011/08/23 23:52:52 Ah, you absolutely right. removed.
625 //
601 // Pan to show the cursor when it overflows to the right, 626 // Pan to show the cursor when it overflows to the right,
602 delta_offset = display_rect_.right() - cursor_bounds_.right(); 627 delta_offset = display_rect_.right() - cursor_bounds_.right();
603 } else if (cursor_bounds_.x() < display_rect_.x()) { 628 } else if (cursor_bounds_.x() < display_rect_.x()) {
629 // TODO(xji): have similar problem as above when overflow character is a
630 // LTR character.
631 //
604 // Pan to show the cursor when it overflows to the left. 632 // Pan to show the cursor when it overflows to the left.
605 delta_offset = display_rect_.x() - cursor_bounds_.x(); 633 delta_offset = display_rect_.x() - cursor_bounds_.x();
606 } 634 }
607 display_offset_.Offset(delta_offset, 0); 635 display_offset_.Offset(delta_offset, 0);
608 cursor_bounds_.Offset(delta_offset, 0); 636 cursor_bounds_.Offset(delta_offset, 0);
609 } 637 }
610 638
639 SelectionModel RenderText::GetSelectionModelForSelectionStart() {
640 if (GetSelectionStart() < GetCursorPosition())
641 return SelectionModel(GetSelectionStart(),
642 GetSelectionStart(),
643 SelectionModel::LEADING);
644 return SelectionModel(GetSelectionStart(),
645 GetIndexOfPreviousGrapheme(GetSelectionStart()),
msw 2011/08/23 08:01:01 What if the selection start is 0 and there is not
xji 2011/08/23 23:52:52 this is called when selection is not empty and sel
646 SelectionModel::TRAILING);
647 }
648
611 } // namespace gfx 649 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698