| OLD | NEW |
| 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 CaretPlacement placement) { | 123 CaretPlacement placement) { |
| 124 selection_start_ = start; | 124 selection_start_ = start; |
| 125 selection_end_ = end; | 125 selection_end_ = end; |
| 126 caret_pos_ = pos; | 126 caret_pos_ = pos; |
| 127 caret_placement_ = placement; | 127 caret_placement_ = placement; |
| 128 } | 128 } |
| 129 | 129 |
| 130 RenderText::~RenderText() { | 130 RenderText::~RenderText() { |
| 131 } | 131 } |
| 132 | 132 |
| 133 void RenderText::set_display_rect(const Rect& r) { | |
| 134 display_rect_ = r; | |
| 135 } | |
| 136 | |
| 137 void RenderText::SetText(const string16& text) { | 133 void RenderText::SetText(const string16& text) { |
| 138 size_t old_text_length = text_.length(); | 134 size_t old_text_length = text_.length(); |
| 139 text_ = text; | 135 text_ = text; |
| 140 | 136 |
| 141 // Update the style ranges as needed. | 137 // Update the style ranges as needed. |
| 142 if (text_.empty()) { | 138 if (text_.empty()) { |
| 143 style_ranges_.clear(); | 139 style_ranges_.clear(); |
| 144 } else if (style_ranges_.empty()) { | 140 } else if (style_ranges_.empty()) { |
| 145 ApplyDefaultStyle(); | 141 ApplyDefaultStyle(); |
| 146 } else if (text_.length() > old_text_length) { | 142 } else if (text_.length() > old_text_length) { |
| 147 style_ranges_.back().range.set_end(text_.length()); | 143 style_ranges_.back().range.set_end(text_.length()); |
| 148 } else if (text_.length() < old_text_length) { | 144 } else if (text_.length() < old_text_length) { |
| 149 StyleRanges::iterator i; | 145 StyleRanges::iterator i; |
| 150 for (i = style_ranges_.begin(); i != style_ranges_.end(); i++) { | 146 for (i = style_ranges_.begin(); i != style_ranges_.end(); i++) { |
| 151 if (i->range.start() >= text_.length()) { | 147 if (i->range.start() >= text_.length()) { |
| 152 i = style_ranges_.erase(i); | 148 i = style_ranges_.erase(i); |
| 153 if (i == style_ranges_.end()) | 149 if (i == style_ranges_.end()) |
| 154 break; | 150 break; |
| 155 } else if (i->range.end() > text_.length()) { | 151 } else if (i->range.end() > text_.length()) { |
| 156 i->range.set_end(text_.length()); | 152 i->range.set_end(text_.length()); |
| 157 } | 153 } |
| 158 } | 154 } |
| 159 style_ranges_.back().range.set_end(text_.length()); | 155 style_ranges_.back().range.set_end(text_.length()); |
| 160 } | 156 } |
| 161 #ifndef NDEBUG | 157 #ifndef NDEBUG |
| 162 CheckStyleRanges(style_ranges_, text_.length()); | 158 CheckStyleRanges(style_ranges_, text_.length()); |
| 163 #endif | 159 #endif |
| 160 cached_bounds_and_offset_valid_ = false; |
| 164 } | 161 } |
| 165 | 162 |
| 166 void RenderText::SetSelectionModel(const SelectionModel& sel) { | 163 void RenderText::SetSelectionModel(const SelectionModel& sel) { |
| 167 size_t start = sel.selection_start(); | 164 size_t start = sel.selection_start(); |
| 168 size_t end = sel.selection_end(); | 165 size_t end = sel.selection_end(); |
| 169 selection_model_.set_selection_start(std::min(start, text().length())); | 166 selection_model_.set_selection_start(std::min(start, text().length())); |
| 170 selection_model_.set_selection_end(std::min(end, text().length())); | 167 selection_model_.set_selection_end(std::min(end, text().length())); |
| 171 selection_model_.set_caret_pos(std::min(sel.caret_pos(), text().length())); | 168 selection_model_.set_caret_pos(std::min(sel.caret_pos(), text().length())); |
| 172 selection_model_.set_caret_placement(sel.caret_placement()); | 169 selection_model_.set_caret_placement(sel.caret_placement()); |
| 173 | 170 |
| 174 cursor_bounds_valid_ = false; | 171 cached_bounds_and_offset_valid_ = false; |
| 172 } |
| 173 |
| 174 void RenderText::SetDisplayRect(const Rect& r) { |
| 175 display_rect_ = r; |
| 176 cached_bounds_and_offset_valid_ = false; |
| 175 } | 177 } |
| 176 | 178 |
| 177 size_t RenderText::GetCursorPosition() const { | 179 size_t RenderText::GetCursorPosition() const { |
| 178 return selection_model_.selection_end(); | 180 return selection_model_.selection_end(); |
| 179 } | 181 } |
| 180 | 182 |
| 181 void RenderText::SetCursorPosition(const size_t position) { | 183 void RenderText::SetCursorPosition(const size_t position) { |
| 182 SelectionModel sel(selection_model()); | 184 SelectionModel sel(selection_model()); |
| 183 sel.set_selection_start(position); | 185 sel.set_selection_start(position); |
| 184 sel.set_selection_end(position); | 186 sel.set_selection_end(position); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 void RenderText::ApplyStyleRange(StyleRange style_range) { | 323 void RenderText::ApplyStyleRange(StyleRange style_range) { |
| 322 const ui::Range& new_range = style_range.range; | 324 const ui::Range& new_range = style_range.range; |
| 323 if (!new_range.IsValid() || new_range.is_empty()) | 325 if (!new_range.IsValid() || new_range.is_empty()) |
| 324 return; | 326 return; |
| 325 CHECK(!new_range.is_reversed()); | 327 CHECK(!new_range.is_reversed()); |
| 326 CHECK(ui::Range(0, text_.length()).Contains(new_range)); | 328 CHECK(ui::Range(0, text_.length()).Contains(new_range)); |
| 327 ApplyStyleRangeImpl(&style_ranges_, style_range); | 329 ApplyStyleRangeImpl(&style_ranges_, style_range); |
| 328 #ifndef NDEBUG | 330 #ifndef NDEBUG |
| 329 CheckStyleRanges(style_ranges_, text_.length()); | 331 CheckStyleRanges(style_ranges_, text_.length()); |
| 330 #endif | 332 #endif |
| 331 // TODO(xji): only invalidate cursor_bounds if font or underline change. | 333 // TODO(xji): only invalidate if font or underline changes. |
| 332 cursor_bounds_valid_ = false; | 334 cached_bounds_and_offset_valid_ = false; |
| 333 } | 335 } |
| 334 | 336 |
| 335 void RenderText::ApplyDefaultStyle() { | 337 void RenderText::ApplyDefaultStyle() { |
| 336 style_ranges_.clear(); | 338 style_ranges_.clear(); |
| 337 StyleRange style = StyleRange(default_style_); | 339 StyleRange style = StyleRange(default_style_); |
| 338 style.range.set_end(text_.length()); | 340 style.range.set_end(text_.length()); |
| 339 style_ranges_.push_back(style); | 341 style_ranges_.push_back(style); |
| 340 cursor_bounds_valid_ = false; | 342 cached_bounds_and_offset_valid_ = false; |
| 341 } | 343 } |
| 342 | 344 |
| 343 base::i18n::TextDirection RenderText::GetTextDirection() const { | 345 base::i18n::TextDirection RenderText::GetTextDirection() const { |
| 344 // TODO(msw): Bidi implementation, intended to replace the functionality added | 346 // TODO(msw): Bidi implementation, intended to replace the functionality added |
| 345 // in crrev.com/91881 (discussed in codereview.chromium.org/7324011). | 347 // in crrev.com/91881 (discussed in codereview.chromium.org/7324011). |
| 346 return base::i18n::LEFT_TO_RIGHT; | 348 return base::i18n::LEFT_TO_RIGHT; |
| 347 } | 349 } |
| 348 | 350 |
| 349 int RenderText::GetStringWidth() { | 351 int RenderText::GetStringWidth() { |
| 350 return GetSubstringBounds(0, text_.length())[0].width(); | 352 return default_style_.font.GetStringWidth(text()); |
| 351 } | 353 } |
| 352 | 354 |
| 353 void RenderText::Draw(Canvas* canvas) { | 355 void RenderText::Draw(Canvas* canvas) { |
| 354 // Clip the canvas to the text display area. | 356 // Clip the canvas to the text display area. |
| 355 canvas->ClipRectInt(display_rect_.x(), display_rect_.y(), | 357 canvas->ClipRectInt(display_rect_.x(), display_rect_.y(), |
| 356 display_rect_.width(), display_rect_.height()); | 358 display_rect_.width(), display_rect_.height()); |
| 357 | 359 |
| 358 // Draw the selection. | 360 // Draw the selection. |
| 359 std::vector<Rect> selection(GetSubstringBounds(GetSelectionStart(), | 361 std::vector<Rect> selection(GetSubstringBounds(GetSelectionStart(), |
| 360 GetCursorPosition())); | 362 GetCursorPosition())); |
| 361 SkColor selection_color = | 363 SkColor selection_color = |
| 362 focused() ? kFocusedSelectionColor : kUnfocusedSelectionColor; | 364 focused() ? kFocusedSelectionColor : kUnfocusedSelectionColor; |
| 363 for (std::vector<Rect>::const_iterator i = selection.begin(); | 365 for (std::vector<Rect>::const_iterator i = selection.begin(); |
| 364 i < selection.end(); ++i) { | 366 i < selection.end(); ++i) { |
| 365 Rect r(*i); | 367 Rect r(*i); |
| 366 r.Offset(display_rect_.origin()); | |
| 367 r.Offset(display_offset_); | |
| 368 // Center the rect vertically in |display_rect_|. | |
| 369 r.Offset(Point(0, (display_rect_.height() - r.height()) / 2)); | |
| 370 canvas->FillRectInt(selection_color, r.x(), r.y(), r.width(), r.height()); | 368 canvas->FillRectInt(selection_color, r.x(), r.y(), r.width(), r.height()); |
| 371 } | 369 } |
| 372 | 370 |
| 373 // Create a temporary copy of the style ranges for composition and selection. | 371 // Create a temporary copy of the style ranges for composition and selection. |
| 374 StyleRanges style_ranges(style_ranges_); | 372 StyleRanges style_ranges(style_ranges_); |
| 375 ApplyCompositionAndSelectionStyles(&style_ranges); | 373 ApplyCompositionAndSelectionStyles(&style_ranges); |
| 376 | 374 |
| 377 // Draw the text. | 375 // Draw the text. |
| 378 Rect bounds(display_rect_); | 376 Rect bounds(display_rect_); |
| 379 bounds.Offset(display_offset_); | 377 bounds.Offset(GetUpdatedDisplayOffset()); |
| 380 for (StyleRanges::const_iterator i = style_ranges.begin(); | 378 for (StyleRanges::const_iterator i = style_ranges.begin(); |
| 381 i < style_ranges.end(); ++i) { | 379 i < style_ranges.end(); ++i) { |
| 382 const Font& font = !i->underline ? i->font : | 380 const Font& font = !i->underline ? i->font : |
| 383 i->font.DeriveFont(0, i->font.GetStyle() | Font::UNDERLINED); | 381 i->font.DeriveFont(0, i->font.GetStyle() | Font::UNDERLINED); |
| 384 string16 text = text_.substr(i->range.start(), i->range.length()); | 382 string16 text = text_.substr(i->range.start(), i->range.length()); |
| 385 bounds.set_width(font.GetStringWidth(text)); | 383 bounds.set_width(font.GetStringWidth(text)); |
| 386 canvas->DrawStringInt(text, font, i->foreground, bounds); | 384 canvas->DrawStringInt(text, font, i->foreground, bounds); |
| 387 | 385 |
| 388 // Draw the strikethrough. | 386 // Draw the strikethrough. |
| 389 if (i->strike) { | 387 if (i->strike) { |
| 390 SkPaint paint; | 388 SkPaint paint; |
| 391 paint.setAntiAlias(true); | 389 paint.setAntiAlias(true); |
| 392 paint.setStyle(SkPaint::kFill_Style); | 390 paint.setStyle(SkPaint::kFill_Style); |
| 393 paint.setColor(i->foreground); | 391 paint.setColor(i->foreground); |
| 394 paint.setStrokeWidth(kStrikeWidth); | 392 paint.setStrokeWidth(kStrikeWidth); |
| 395 canvas->AsCanvasSkia()->drawLine(SkIntToScalar(bounds.x()), | 393 canvas->AsCanvasSkia()->drawLine(SkIntToScalar(bounds.x()), |
| 396 SkIntToScalar(bounds.bottom()), | 394 SkIntToScalar(bounds.bottom()), |
| 397 SkIntToScalar(bounds.right()), | 395 SkIntToScalar(bounds.right()), |
| 398 SkIntToScalar(bounds.y()), | 396 SkIntToScalar(bounds.y()), |
| 399 paint); | 397 paint); |
| 400 } | 398 } |
| 401 | 399 |
| 402 bounds.set_x(bounds.x() + bounds.width()); | 400 bounds.set_x(bounds.x() + bounds.width()); |
| 403 } | 401 } |
| 404 | 402 |
| 405 // Paint cursor. Replace cursor is drawn as rectangle for now. | 403 // Paint cursor. Replace cursor is drawn as rectangle for now. |
| 406 if (cursor_visible() && focused()) { | 404 Rect cursor(GetUpdatedCursorBounds()); |
| 407 bounds = CursorBounds(); | 405 if (cursor_visible() && focused() && !cursor.IsEmpty()) |
| 408 bounds.Offset(display_offset_); | 406 canvas->DrawRectInt(kCursorColor, cursor.x(), cursor.y(), |
| 409 if (!bounds.IsEmpty()) | 407 cursor.width(), cursor.height()); |
| 410 canvas->DrawRectInt(kCursorColor, | |
| 411 bounds.x(), | |
| 412 bounds.y(), | |
| 413 bounds.width(), | |
| 414 bounds.height()); | |
| 415 } | |
| 416 } | 408 } |
| 417 | 409 |
| 418 SelectionModel RenderText::FindCursorPosition(const Point& point) { | 410 SelectionModel RenderText::FindCursorPosition(const Point& point) { |
| 419 const Font& font = default_style_.font; | 411 const Font& font = default_style_.font; |
| 420 int left = 0; | 412 int left = 0; |
| 421 int left_pos = 0; | 413 int left_pos = 0; |
| 422 int right = font.GetStringWidth(text()); | 414 int right = font.GetStringWidth(text()); |
| 423 int right_pos = text().length(); | 415 int right_pos = text().length(); |
| 424 | 416 |
| 425 int x = point.x(); | 417 int x = point.x() - (display_rect_.x() + GetUpdatedDisplayOffset().x()); |
| 426 if (x <= left) return SelectionModel(left_pos); | 418 if (x <= left) return SelectionModel(left_pos); |
| 427 if (x >= right) return SelectionModel(right_pos); | 419 if (x >= right) return SelectionModel(right_pos); |
| 428 // binary searching the cursor position. | 420 // binary searching the cursor position. |
| 429 // TODO(oshima): use the center of character instead of edge. | 421 // TODO(oshima): use the center of character instead of edge. |
| 430 // Binary search may not work for language like arabic. | 422 // Binary search may not work for language like arabic. |
| 431 while (std::abs(static_cast<long>(right_pos - left_pos)) > 1) { | 423 while (std::abs(static_cast<long>(right_pos - left_pos)) > 1) { |
| 432 int pivot_pos = left_pos + (right_pos - left_pos) / 2; | 424 int pivot_pos = left_pos + (right_pos - left_pos) / 2; |
| 433 int pivot = font.GetStringWidth(text().substr(0, pivot_pos)); | 425 int pivot = font.GetStringWidth(text().substr(0, pivot_pos)); |
| 434 if (pivot < x) { | 426 if (pivot < x) { |
| 435 left = pivot; | 427 left = pivot; |
| 436 left_pos = pivot_pos; | 428 left_pos = pivot_pos; |
| 437 } else if (pivot == x) { | 429 } else if (pivot == x) { |
| 438 return SelectionModel(pivot_pos); | 430 return SelectionModel(pivot_pos); |
| 439 } else { | 431 } else { |
| 440 right = pivot; | 432 right = pivot; |
| 441 right_pos = pivot_pos; | 433 right_pos = pivot_pos; |
| 442 } | 434 } |
| 443 } | 435 } |
| 444 return SelectionModel(left_pos); | 436 return SelectionModel(left_pos); |
| 445 } | 437 } |
| 446 | 438 |
| 447 std::vector<Rect> RenderText::GetSubstringBounds( | 439 std::vector<Rect> RenderText::GetSubstringBounds( |
| 448 size_t from, size_t to) const { | 440 size_t from, size_t to) { |
| 449 size_t start = std::min(from, to); | 441 size_t start = std::min(from, to); |
| 450 size_t end = std::max(from, to); | 442 size_t end = std::max(from, to); |
| 451 const Font& font = default_style_.font; | 443 const Font& font = default_style_.font; |
| 452 int start_x = font.GetStringWidth(text().substr(0, start)); | 444 int start_x = font.GetStringWidth(text().substr(0, start)); |
| 453 int end_x = font.GetStringWidth(text().substr(0, end)); | 445 int end_x = font.GetStringWidth(text().substr(0, end)); |
| 454 std::vector<Rect> bounds; | 446 Rect rect(start_x, 0, end_x - start_x, font.GetHeight()); |
| 455 bounds.push_back(Rect(start_x, 0, end_x - start_x, font.GetHeight())); | 447 rect.Offset(display_rect_.origin()); |
| 456 return bounds; | 448 rect.Offset(GetUpdatedDisplayOffset()); |
| 449 // Center the rect vertically in |display_rect_|. |
| 450 rect.Offset(Point(0, (display_rect_.height() - rect.height()) / 2)); |
| 451 return std::vector<Rect>(1, rect); |
| 457 } | 452 } |
| 458 | 453 |
| 459 Rect RenderText::GetCursorBounds(const SelectionModel& selection, | 454 Rect RenderText::GetCursorBounds(const SelectionModel& selection, |
| 460 bool insert_mode) { | 455 bool insert_mode) { |
| 461 size_t cursor_pos = selection.selection_end(); | 456 size_t from = selection.selection_end(); |
| 462 const Font& font = default_style_.font; | 457 size_t to = insert_mode ? from : std::min(text_.length(), from + 1); |
| 463 int x = font.GetStringWidth(text_.substr(0U, cursor_pos)); | 458 return GetSubstringBounds(from, to)[0]; |
| 464 DCHECK_GE(x, 0); | |
| 465 int h = std::min(display_rect_.height(), font.GetHeight()); | |
| 466 Rect bounds(x, (display_rect_.height() - h) / 2, 1, h); | |
| 467 if (!insert_mode && text_.length() != cursor_pos) | |
| 468 bounds.set_width(font.GetStringWidth(text_.substr(0, cursor_pos + 1)) - x); | |
| 469 return bounds; | |
| 470 } | 459 } |
| 471 | 460 |
| 472 const Rect& RenderText::CursorBounds() { | 461 const Rect& RenderText::GetUpdatedCursorBounds() { |
| 473 if (cursor_bounds_valid_ == false) { | 462 UpdateCachedBoundsAndOffset(); |
| 474 UpdateCursorBoundsAndDisplayOffset(); | |
| 475 cursor_bounds_valid_ = true; | |
| 476 } | |
| 477 return cursor_bounds_; | 463 return cursor_bounds_; |
| 478 } | 464 } |
| 479 | 465 |
| 480 RenderText::RenderText() | 466 RenderText::RenderText() |
| 481 : text_(), | 467 : text_(), |
| 482 selection_model_(), | 468 selection_model_(), |
| 483 cursor_bounds_(), | 469 cursor_bounds_(), |
| 484 cursor_bounds_valid_(false), | |
| 485 cursor_visible_(false), | 470 cursor_visible_(false), |
| 486 insert_mode_(true), | 471 insert_mode_(true), |
| 487 composition_range_(), | 472 composition_range_(), |
| 488 style_ranges_(), | 473 style_ranges_(), |
| 489 default_style_(), | 474 default_style_(), |
| 490 display_rect_(), | 475 display_rect_(), |
| 491 display_offset_() { | 476 display_offset_(), |
| 477 cached_bounds_and_offset_valid_(false) { |
| 478 } |
| 479 |
| 480 const Point& RenderText::GetUpdatedDisplayOffset() { |
| 481 UpdateCachedBoundsAndOffset(); |
| 482 return display_offset_; |
| 492 } | 483 } |
| 493 | 484 |
| 494 SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current, | 485 SelectionModel RenderText::GetLeftSelectionModel(const SelectionModel& current, |
| 495 BreakType break_type) { | 486 BreakType break_type) { |
| 496 if (break_type == LINE_BREAK) | 487 if (break_type == LINE_BREAK) |
| 497 return SelectionModel(0, 0, SelectionModel::LEADING); | 488 return SelectionModel(0, 0, SelectionModel::LEADING); |
| 498 size_t pos = std::max(static_cast<long>(current.selection_end() - 1), | 489 size_t pos = std::max(static_cast<long>(current.selection_end() - 1), |
| 499 static_cast<long>(0)); | 490 static_cast<long>(0)); |
| 500 if (break_type == CHARACTER_BREAK) | 491 if (break_type == CHARACTER_BREAK) |
| 501 return SelectionModel(pos, pos, SelectionModel::LEADING); | 492 return SelectionModel(pos, pos, SelectionModel::LEADING); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 selection_style.range.set_end(MaxOfSelection()); | 568 selection_style.range.set_end(MaxOfSelection()); |
| 578 ApplyStyleRangeImpl(style_ranges, selection_style); | 569 ApplyStyleRangeImpl(style_ranges, selection_style); |
| 579 } | 570 } |
| 580 } | 571 } |
| 581 | 572 |
| 582 bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) { | 573 bool RenderText::IsPositionAtWordSelectionBoundary(size_t pos) { |
| 583 return pos == 0 || (u_isalnum(text()[pos - 1]) && !u_isalnum(text()[pos])) || | 574 return pos == 0 || (u_isalnum(text()[pos - 1]) && !u_isalnum(text()[pos])) || |
| 584 (!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos])); | 575 (!u_isalnum(text()[pos - 1]) && u_isalnum(text()[pos])); |
| 585 } | 576 } |
| 586 | 577 |
| 587 void RenderText::UpdateCursorBoundsAndDisplayOffset() { | 578 void RenderText::UpdateCachedBoundsAndOffset() { |
| 588 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode()); | 579 if (cached_bounds_and_offset_valid_) |
| 580 return; |
| 581 // First, set the valid flag true to calculate the current cursor bounds using |
| 582 // the stale |display_offset_|. Applying |delta_offset| at the end of this |
| 583 // function will set |cursor_bounds_| and |display_offset_| to correct values. |
| 584 cached_bounds_and_offset_valid_ = true; |
| 585 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_); |
| 586 cursor_bounds_.set_width(std::max(cursor_bounds_.width(), 1)); |
| 589 // Update |display_offset_| to ensure the current cursor is visible. | 587 // Update |display_offset_| to ensure the current cursor is visible. |
| 590 int display_width = display_rect_.width(); | 588 int display_width = display_rect_.width(); |
| 591 int string_width = GetStringWidth(); | 589 int string_width = GetStringWidth(); |
| 590 int delta_offset = 0; |
| 592 if (string_width < display_width) { | 591 if (string_width < display_width) { |
| 593 // Show all text whenever the text fits to the size. | 592 // Show all text whenever the text fits to the size. |
| 594 display_offset_.set_x(0); | 593 delta_offset = -display_offset_.x(); |
| 595 } else if ((display_offset_.x() + cursor_bounds_.right()) > display_width) { | 594 } else if (cursor_bounds_.right() > display_rect_.right()) { |
| 596 // Pan to show the cursor when it overflows to the right, | 595 // Pan to show the cursor when it overflows to the right, |
| 597 display_offset_.set_x(display_width - cursor_bounds_.right()); | 596 delta_offset = display_rect_.right() - cursor_bounds_.right(); |
| 598 } else if ((display_offset_.x() + cursor_bounds_.x()) < 0) { | 597 } else if (cursor_bounds_.x() < display_rect_.x()) { |
| 599 // Pan to show the cursor when it overflows to the left. | 598 // Pan to show the cursor when it overflows to the left. |
| 600 display_offset_.set_x(-cursor_bounds_.x()); | 599 delta_offset = display_rect_.x() - cursor_bounds_.x(); |
| 601 } | 600 } |
| 601 display_offset_.Offset(delta_offset, 0); |
| 602 cursor_bounds_.Offset(delta_offset, 0); |
| 602 } | 603 } |
| 603 | 604 |
| 604 } // namespace gfx | 605 } // namespace gfx |
| OLD | NEW |