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

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

Issue 7458014: Implement Uniscribe RenderText for Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add simple BreakIterator support, use scoped_array, fix home/end, invalidate on toggle insert, etc. 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 size_t start = sel.selection_start(); 168 size_t start = sel.selection_start();
169 size_t end = sel.selection_end(); 169 size_t end = sel.selection_end();
170 selection_model_.set_selection_start(std::min(start, text().length())); 170 selection_model_.set_selection_start(std::min(start, text().length()));
171 selection_model_.set_selection_end(std::min(end, text().length())); 171 selection_model_.set_selection_end(std::min(end, text().length()));
172 selection_model_.set_caret_pos(std::min(sel.caret_pos(), text().length())); 172 selection_model_.set_caret_pos(std::min(sel.caret_pos(), text().length()));
173 selection_model_.set_caret_placement(sel.caret_placement()); 173 selection_model_.set_caret_placement(sel.caret_placement());
174 174
175 cached_bounds_and_offset_valid_ = false; 175 cached_bounds_and_offset_valid_ = false;
176 } 176 }
177 177
178 void RenderText::ToggleInsertMode() {
179 insert_mode_ = !insert_mode_;
180 cached_bounds_and_offset_valid_ = false;
181 }
182
178 void RenderText::SetDisplayRect(const Rect& r) { 183 void RenderText::SetDisplayRect(const Rect& r) {
179 display_rect_ = r; 184 display_rect_ = r;
180 cached_bounds_and_offset_valid_ = false; 185 cached_bounds_and_offset_valid_ = false;
181 } 186 }
182 187
183 size_t RenderText::GetCursorPosition() const { 188 size_t RenderText::GetCursorPosition() const {
184 return selection_model_.selection_end(); 189 return selection_model_.selection_end();
185 } 190 }
186 191
187 void RenderText::SetCursorPosition(const size_t position) { 192 void RenderText::SetCursorPosition(size_t position) {
188 SelectionModel sel(selection_model()); 193 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 } 194 }
195 195
196 void RenderText::MoveCursorLeft(BreakType break_type, bool select) { 196 void RenderText::MoveCursorLeft(BreakType break_type, bool select) {
197 SelectionModel position(selection_model()); 197 SelectionModel position(selection_model());
198 position.set_selection_start(GetCursorPosition()); 198 position.set_selection_start(GetCursorPosition());
199 // Cancelling a selection moves to the edge of the selection. 199 // Cancelling a selection moves to the edge of the selection.
200 if (break_type != LINE_BREAK && !EmptySelection() && !select) { 200 if (break_type != LINE_BREAK && !EmptySelection() && !select) {
201 // Use the selection start if it is left of the selection end. 201 // Use the selection start if it is left of the selection end.
202 SelectionModel selection_start(GetSelectionStart(), GetSelectionStart(), 202 SelectionModel selection_start(GetSelectionStart(), GetSelectionStart(),
203 SelectionModel::LEADING); 203 SelectionModel::LEADING);
(...skipping 26 matching lines...) Expand all
230 if (break_type == WORD_BREAK) 230 if (break_type == WORD_BREAK)
231 position = GetRightSelectionModel(position, break_type); 231 position = GetRightSelectionModel(position, break_type);
232 } else { 232 } else {
233 position = GetRightSelectionModel(position, break_type); 233 position = GetRightSelectionModel(position, break_type);
234 } 234 }
235 if (select) 235 if (select)
236 position.set_selection_start(GetSelectionStart()); 236 position.set_selection_start(GetSelectionStart());
237 MoveCursorTo(position); 237 MoveCursorTo(position);
238 } 238 }
239 239
240 void RenderText::MoveCursorTo(size_t position, bool select) {
241 size_t caret_pos = GetIndexOfPreviousGrapheme(position);
242 SelectionModel::CaretPlacement placement = (caret_pos == position) ?
243 SelectionModel::LEADING : SelectionModel::TRAILING;
244 size_t selection_start = select ? GetSelectionStart() : position;
245 SelectionModel sel(selection_start, position, caret_pos, placement);
246 SetSelectionModel(sel);
xji 2011/08/18 22:47:54 hmm... the functionality seems different from prev
msw 2011/08/19 10:55:30 This has been reincarnated as a convenience functi
xji 2011/08/19 17:38:13 make sense. but I think for complex script, say f
msw 2011/08/19 18:03:33 Interesting, I wonder how that works with the IMEs
247 }
248
240 bool RenderText::MoveCursorTo(const SelectionModel& selection) { 249 bool RenderText::MoveCursorTo(const SelectionModel& selection) {
241 bool changed = !selection.Equals(selection_model_); 250 bool changed = !selection.Equals(selection_model_);
242 SetSelectionModel(selection); 251 SetSelectionModel(selection);
243 return changed; 252 return changed;
244 } 253 }
245 254
246 bool RenderText::MoveCursorTo(const Point& point, bool select) { 255 bool RenderText::MoveCursorTo(const Point& point, bool select) {
247 SelectionModel selection = FindCursorPosition(point); 256 SelectionModel selection = FindCursorPosition(point);
248 if (select) 257 if (select)
249 selection.set_selection_start(GetSelectionStart()); 258 selection.set_selection_start(GetSelectionStart());
250 return MoveCursorTo(selection); 259 return MoveCursorTo(selection);
251 } 260 }
252 261
253 bool RenderText::IsPointInSelection(const Point& point) { 262 bool RenderText::IsPointInSelection(const Point& point) {
263 if (EmptySelection())
264 return false;
254 // TODO(xji): should this check whether the point is inside the visual 265 // TODO(xji): should this check whether the point is inside the visual
255 // selection bounds? In case of "abcFED", if "ED" is selected, |point| points 266 // selection bounds? In case of "abcFED", if "ED" is selected, |point| points
256 // to the right half of 'c', is the point in selection? 267 // to the right half of 'c', is the point in selection?
257 size_t pos = FindCursorPosition(point).selection_end(); 268 size_t pos = FindCursorPosition(point).selection_end();
258 return (pos >= MinOfSelection() && pos < MaxOfSelection()); 269 return (pos >= MinOfSelection() && pos < MaxOfSelection());
259 } 270 }
260 271
261 void RenderText::ClearSelection() { 272 void RenderText::ClearSelection() {
262 SelectionModel sel(selection_model()); 273 SelectionModel sel(selection_model());
263 sel.set_selection_start(GetCursorPosition()); 274 sel.set_selection_start(GetCursorPosition());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 } 312 }
302 313
303 // Now we move selection_end_ to end of selection. Selection boundary 314 // Now we move selection_end_ to end of selection. Selection boundary
304 // is defined as the position where we have alpha-num character on one side 315 // is defined as the position where we have alpha-num character on one side
305 // and non-alpha-num char on the other side. 316 // and non-alpha-num char on the other side.
306 for (; cursor_position < text().length(); cursor_position++) { 317 for (; cursor_position < text().length(); cursor_position++) {
307 if (IsPositionAtWordSelectionBoundary(cursor_position)) 318 if (IsPositionAtWordSelectionBoundary(cursor_position))
308 break; 319 break;
309 } 320 }
310 321
311 SelectionModel sel(selection_model()); 322 MoveCursorTo(selection_start, false);
312 sel.set_selection_start(selection_start); 323 MoveCursorTo(cursor_position, true);
xji 2011/08/18 22:47:54 why this change?
msw 2011/08/19 10:55:30 Convenience of built-in checking for s previous gr
313 sel.set_selection_end(cursor_position);
314 sel.set_caret_pos(GetIndexOfPreviousGrapheme(cursor_position));
315 sel.set_caret_placement(SelectionModel::TRAILING);
316 SetSelectionModel(sel);
317 } 324 }
318 325
319 const ui::Range& RenderText::GetCompositionRange() const { 326 const ui::Range& RenderText::GetCompositionRange() const {
320 return composition_range_; 327 return composition_range_;
321 } 328 }
322 329
323 void RenderText::SetCompositionRange(const ui::Range& composition_range) { 330 void RenderText::SetCompositionRange(const ui::Range& composition_range) {
324 CHECK(!composition_range.IsValid() || 331 CHECK(!composition_range.IsValid() ||
325 ui::Range(0, text_.length()).Contains(composition_range)); 332 ui::Range(0, text_.length()).Contains(composition_range));
326 composition_range_.set_end(composition_range.end()); 333 composition_range_.set_end(composition_range.end());
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 } 589 }
583 590
584 void RenderText::UpdateCachedBoundsAndOffset() { 591 void RenderText::UpdateCachedBoundsAndOffset() {
585 if (cached_bounds_and_offset_valid_) 592 if (cached_bounds_and_offset_valid_)
586 return; 593 return;
587 // First, set the valid flag true to calculate the current cursor bounds using 594 // 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 595 // the stale |display_offset_|. Applying |delta_offset| at the end of this
589 // function will set |cursor_bounds_| and |display_offset_| to correct values. 596 // function will set |cursor_bounds_| and |display_offset_| to correct values.
590 cached_bounds_and_offset_valid_ = true; 597 cached_bounds_and_offset_valid_ = true;
591 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_); 598 cursor_bounds_ = GetCursorBounds(selection_model_, insert_mode_);
592 cursor_bounds_.set_width(std::max(cursor_bounds_.width(), 1));
593 // Update |display_offset_| to ensure the current cursor is visible. 599 // Update |display_offset_| to ensure the current cursor is visible.
594 int display_width = display_rect_.width(); 600 int display_width = display_rect_.width();
595 int string_width = GetStringWidth(); 601 int string_width = GetStringWidth();
596 int delta_offset = 0; 602 int delta_offset = 0;
597 if (string_width < display_width) { 603 if (string_width < display_width) {
598 // Show all text whenever the text fits to the size. 604 // Show all text whenever the text fits to the size.
599 delta_offset = -display_offset_.x(); 605 delta_offset = -display_offset_.x();
600 } else if (cursor_bounds_.right() > display_rect_.right()) { 606 } else if (cursor_bounds_.right() > display_rect_.right()) {
601 // Pan to show the cursor when it overflows to the right, 607 // Pan to show the cursor when it overflows to the right,
602 delta_offset = display_rect_.right() - cursor_bounds_.right(); 608 delta_offset = display_rect_.right() - cursor_bounds_.right();
603 } else if (cursor_bounds_.x() < display_rect_.x()) { 609 } else if (cursor_bounds_.x() < display_rect_.x()) {
604 // Pan to show the cursor when it overflows to the left. 610 // Pan to show the cursor when it overflows to the left.
605 delta_offset = display_rect_.x() - cursor_bounds_.x(); 611 delta_offset = display_rect_.x() - cursor_bounds_.x();
606 } 612 }
607 display_offset_.Offset(delta_offset, 0); 613 display_offset_.Offset(delta_offset, 0);
608 cursor_bounds_.Offset(delta_offset, 0); 614 cursor_bounds_.Offset(delta_offset, 0);
609 } 615 }
610 616
611 } // namespace gfx 617 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698