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

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

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 #ifndef UI_GFX_RENDER_TEXT_H_ 5 #ifndef UI_GFX_RENDER_TEXT_H_
6 #define UI_GFX_RENDER_TEXT_H_ 6 #define UI_GFX_RENDER_TEXT_H_
7 #pragma once 7 #pragma once
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <vector> 10 #include <vector>
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 LINE_BREAK, 83 LINE_BREAK,
84 }; 84 };
85 85
86 // Horizontal text alignment styles. 86 // Horizontal text alignment styles.
87 enum HorizontalAlignment { 87 enum HorizontalAlignment {
88 ALIGN_LEFT, 88 ALIGN_LEFT,
89 ALIGN_CENTER, 89 ALIGN_CENTER,
90 ALIGN_RIGHT, 90 ALIGN_RIGHT,
91 }; 91 };
92 92
93 // VisualCursorDirection and LogicalCursorDirection represent directions of
94 // motion of the cursor in BiDi text. The combinations that make sense are:
95 //
96 // base::i18n::TextDirection VisualCursorDirection LogicalCursorDirection
97 // LEFT_TO_RIGHT CURSOR_LEFT CURSOR_BACKWARD
98 // LEFT_TO_RIGHT CURSOR_RIGHT CURSOR_FORWARD
99 // RIGHT_TO_LEFT CURSOR_RIGHT CURSOR_BACKWARD
100 // RIGHT_TO_LEFT CURSOR_LEFT CURSOR_FORWARD
101 enum VisualCursorDirection {
102 CURSOR_LEFT,
103 CURSOR_RIGHT
104 };
105 enum LogicalCursorDirection {
106 CURSOR_BACKWARD,
107 CURSOR_FORWARD
108 };
109
110 // RenderText represents an abstract model of styled text and its corresponding 93 // RenderText represents an abstract model of styled text and its corresponding
111 // visual layout. Support is built in for a cursor, a selection, simple styling, 94 // visual layout. Support is built in for a cursor, a selection, simple styling,
112 // complex scripts, and bi-directional text. Implementations provide mechanisms 95 // complex scripts, and bi-directional text. Implementations provide mechanisms
113 // for rendering and translation between logical and visual data. 96 // for rendering and translation between logical and visual data.
114 class UI_EXPORT RenderText { 97 class UI_EXPORT RenderText {
115 public: 98 public:
116 virtual ~RenderText(); 99 virtual ~RenderText();
117 100
118 // Creates a platform-specific RenderText instance. 101 // Creates a platform-specific RenderText instance.
119 static RenderText* CreateRenderText(); 102 static RenderText* CreateRenderText();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 void set_default_style(const StyleRange& style) { default_style_ = style; } 136 void set_default_style(const StyleRange& style) { default_style_ = style; }
154 137
155 const Rect& display_rect() const { return display_rect_; } 138 const Rect& display_rect() const { return display_rect_; }
156 void SetDisplayRect(const Rect& r); 139 void SetDisplayRect(const Rect& r);
157 140
158 void set_fade_head(bool fade_head) { fade_head_ = fade_head; } 141 void set_fade_head(bool fade_head) { fade_head_ = fade_head; }
159 bool fade_head() const { return fade_head_; } 142 bool fade_head() const { return fade_head_; }
160 void set_fade_tail(bool fade_tail) { fade_tail_ = fade_tail; } 143 void set_fade_tail(bool fade_tail) { fade_tail_ = fade_tail; }
161 bool fade_tail() const { return fade_tail_; } 144 bool fade_tail() const { return fade_tail_; }
162 145
163 // This cursor position corresponds to SelectionModel::selection_end. In 146 size_t cursor_position() const { return selection_model_.caret_pos(); }
164 // addition to representing the selection end, it's also where logical text
165 // edits take place, and doesn't necessarily correspond to
166 // SelectionModel::caret_pos.
167 size_t GetCursorPosition() const;
168 void SetCursorPosition(size_t position); 147 void SetCursorPosition(size_t position);
169 148
170 // Moves the cursor left or right. Cursor movement is visual, meaning that 149 // Moves the cursor left or right. Cursor movement is visual, meaning that
171 // left and right are relative to screen, not the directionality of the text. 150 // left and right are relative to screen, not the directionality of the text.
172 // If |select| is false, the selection start is moved to the same position. 151 // If |select| is false, the selection start is moved to the same position.
173 void MoveCursor(BreakType break_type, 152 void MoveCursor(BreakType break_type,
174 VisualCursorDirection direction, 153 VisualCursorDirection direction,
175 bool select); 154 bool select);
176 155
177 // Set the selection_model_ to the value of |selection|. 156 // Set the selection_model_ to the value of |selection|.
178 // The selection model components are modified if invalid. 157 // The selection range is clamped to text().length() if out of range.
179 // Returns true if the cursor position or selection range changed. 158 // Returns true if the cursor position or selection range changed.
180 // If |selectin_start_| or |selection_end_| or |caret_pos_| in 159 // If any index in |selection_model| is not a cursorable position (not on a
181 // |selection_model| is not a cursorable position (not on grapheme boundary), 160 // grapheme boundary), it is a no-op and returns false.
182 // it is a NO-OP and returns false.
183 bool MoveCursorTo(const SelectionModel& selection_model); 161 bool MoveCursorTo(const SelectionModel& selection_model);
184 162
185 // Move the cursor to the position associated with the clicked point. 163 // Move the cursor to the position associated with the clicked point.
186 // If |select| is false, the selection start is moved to the same position. 164 // If |select| is false, the selection start is moved to the same position.
187 // Returns true if the cursor position or selection range changed. 165 // Returns true if the cursor position or selection range changed.
188 bool MoveCursorTo(const Point& point, bool select); 166 bool MoveCursorTo(const Point& point, bool select);
189 167
190 // Set the selection_model_ based on |range|. 168 // Set the selection_model_ based on |range|.
191 // If the |range| start or end is greater than text length, it is modified 169 // If the |range| start or end is greater than text length, it is modified
192 // to be the text length. 170 // to be the text length.
193 // If the |range| start or end is not a cursorable position (not on grapheme 171 // If the |range| start or end is not a cursorable position (not on grapheme
194 // boundary), it is a NO-OP and returns false. Otherwise, returns true. 172 // boundary), it is a NO-OP and returns false. Otherwise, returns true.
195 bool SelectRange(const ui::Range& range); 173 bool SelectRange(const ui::Range& range);
196 174
197 size_t GetSelectionStart() const { 175 const ui::Range& selection() const { return selection_model_.selection(); }
msw 2012/02/28 22:51:32 nit: move this up with cursor_position()
benrg 2012/03/07 01:04:44 Done. I also moved selection_model().
198 return selection_model_.selection_start();
199 }
200 size_t MinOfSelection() const {
201 return std::min(GetSelectionStart(), GetCursorPosition());
202 }
203 size_t MaxOfSelection() const {
204 return std::max(GetSelectionStart(), GetCursorPosition());
205 }
206 bool EmptySelection() const {
207 return GetSelectionStart() == GetCursorPosition();
208 }
209 176
210 // Returns true if the local point is over selected text. 177 // Returns true if the local point is over selected text.
211 bool IsPointInSelection(const Point& point); 178 bool IsPointInSelection(const Point& point);
212 179
213 // Selects no text, all text, or the word at the current cursor position. 180 // Selects no text, all text, or the word at the current cursor position.
214 void ClearSelection(); 181 void ClearSelection();
215 void SelectAll(); 182 void SelectAll();
216 void SelectWord(); 183 void SelectWord();
217 184
218 const ui::Range& GetCompositionRange() const; 185 const ui::Range& GetCompositionRange() const;
219 void SetCompositionRange(const ui::Range& composition_range); 186 void SetCompositionRange(const ui::Range& composition_range);
220 187
221 // Apply |style_range| to the internal style model. 188 // Apply |style_range| to the internal style model.
222 void ApplyStyleRange(const StyleRange& style_range); 189 void ApplyStyleRange(const StyleRange& style_range);
223 190
224 // Apply |default_style_| over the entire text range. 191 // Apply |default_style_| over the entire text range.
225 void ApplyDefaultStyle(); 192 void ApplyDefaultStyle();
226 193
227 // Returns the dominant direction of the current text. 194 // Returns the dominant direction of the current text.
228 virtual base::i18n::TextDirection GetTextDirection() = 0; 195 virtual base::i18n::TextDirection GetTextDirection() = 0;
229 196
230 // Returns the visual movement direction corresponding to the logical end 197 // Returns the visual movement direction corresponding to the logical end
231 // of the text, considering only the dominant direction returned by 198 // of the text, considering only the dominant direction returned by
232 // |GetTextDirection()|, not the direction of a particular run. 199 // |GetTextDirection()|, not the direction of a particular run.
233 VisualCursorDirection GetVisualDirectionOfLogicalEnd(); 200 VisualCursorDirection GetVisualDirectionOfLogicalEnd();
234 201
235 // Get the width of the entire string. 202 // Get the size in pixels of the entire string.
236 virtual int GetStringWidth() = 0; 203 virtual Size GetStringSize() = 0;
237 204
238 void Draw(Canvas* canvas); 205 void Draw(Canvas* canvas);
239 206
240 // Gets the SelectionModel from a visual point in local coordinates. 207 // Gets the SelectionModel from a visual point in local coordinates.
241 virtual SelectionModel FindCursorPosition(const Point& point) = 0; 208 virtual SelectionModel FindCursorPosition(const Point& point) = 0;
242 209
243 // Get the visual bounds of a cursor at |selection|. These bounds typically 210 // Get the visual bounds of a cursor at |selection|. These bounds typically
244 // represent a vertical line, but if |insert_mode| is true they contain the 211 // represent a vertical line, but if |insert_mode| is true they contain the
245 // bounds of the associated glyph. These bounds are in local coordinates, but 212 // bounds of the associated glyph. These bounds are in local coordinates, but
246 // may be outside the visible region if the text is longer than the textfield. 213 // may be outside the visible region if the text is longer than the textfield.
247 // Subsequent text, cursor, or bounds changes may invalidate returned values. 214 // Subsequent text, cursor, or bounds changes may invalidate returned values.
248 virtual Rect GetCursorBounds(const SelectionModel& selection, 215 Rect GetCursorBounds(const SelectionModel& selection, bool insert_mode);
249 bool insert_mode) = 0;
250 216
251 // Compute the current cursor bounds, panning the text to show the cursor in 217 // Compute the current cursor bounds, panning the text to show the cursor in
252 // the display rect if necessary. These bounds are in local coordinates. 218 // the display rect if necessary. These bounds are in local coordinates.
253 // Subsequent text, cursor, or bounds changes may invalidate returned values. 219 // Subsequent text, cursor, or bounds changes may invalidate returned values.
254 const Rect& GetUpdatedCursorBounds(); 220 const Rect& GetUpdatedCursorBounds();
255 221
256 // Given an |index| in text(), return the next or previous grapheme boundary 222 // Given an |index| in text(), return the next or previous grapheme boundary
257 // in logical order (that is, the nearest index for which 223 // in logical order (that is, the nearest index for which
258 // |IsCursorablePosition(index)| returns true). The return value is in the 224 // |IsCursorablePosition(index)| returns true). The return value is in the
259 // range 0 to text().length() inclusive (the input is clamped if it is out of 225 // range 0 to text().length() inclusive (the input is clamped if it is out of
(...skipping 30 matching lines...) Expand all
290 VisualCursorDirection direction) = 0; 256 VisualCursorDirection direction) = 0;
291 257
292 // Get the selection model visually left/right of |selection| by one word. 258 // Get the selection model visually left/right of |selection| by one word.
293 // The returned value represents a cursor/caret position without a selection. 259 // The returned value represents a cursor/caret position without a selection.
294 virtual SelectionModel AdjacentWordSelectionModel( 260 virtual SelectionModel AdjacentWordSelectionModel(
295 const SelectionModel& selection, 261 const SelectionModel& selection,
296 VisualCursorDirection direction) = 0; 262 VisualCursorDirection direction) = 0;
297 263
298 // Get the SelectionModels corresponding to visual text ends. 264 // Get the SelectionModels corresponding to visual text ends.
299 // The returned value represents a cursor/caret position without a selection. 265 // The returned value represents a cursor/caret position without a selection.
300 virtual SelectionModel EdgeSelectionModel( 266 SelectionModel EdgeSelectionModel(VisualCursorDirection direction);
301 VisualCursorDirection direction) = 0;
302 267
303 // Sets the selection model, the argument is assumed to be valid. 268 // Sets the selection model, the argument is assumed to be valid.
304 virtual void SetSelectionModel(const SelectionModel& model); 269 virtual void SetSelectionModel(const SelectionModel& model);
305 270
306 // Get the visual bounds containing the logical substring within |from| to 271 // Get the height and horizontal bounds (relative to the left of the text, not
307 // |to|. If |from| equals |to|, the result is empty. These bounds could be 272 // the view) of the glyph starting at |index|. If the glyph is RTL then
308 // visually discontinuous if the substring is split by a LTR/RTL level change. 273 // xspan->is_reversed(). This does not return a Rect because a Rect can't have
274 // a negative width.
275 virtual void GetGlyphBounds(size_t index, ui::Range* xspan, int* height) = 0;
276
277 // Get the visual bounds containing the logical substring within the |range|.
278 // If |range| is empty, the result is empty. These bounds could be visually
279 // discontinuous if the substring is split by a LTR/RTL level change.
309 // These bounds are in local coordinates, but may be outside the visible 280 // These bounds are in local coordinates, but may be outside the visible
310 // region if the text is longer than the textfield. Subsequent text, cursor, 281 // region if the text is longer than the textfield. Subsequent text, cursor,
311 // or bounds changes may invalidate returned values. 282 // or bounds changes may invalidate returned values.
312 virtual std::vector<Rect> GetSubstringBounds(size_t from, size_t to) = 0; 283 virtual std::vector<Rect> GetSubstringBounds(ui::Range range) = 0;
313 284
314 // Return true if cursor can appear in front of the character at |position|, 285 // Return true if cursor can appear in front of the character at |position|,
315 // which means it is a grapheme boundary or the first character in the text. 286 // which means it is a grapheme boundary or the first character in the text.
316 virtual bool IsCursorablePosition(size_t position) = 0; 287 virtual bool IsCursorablePosition(size_t position) = 0;
317 288
318 // Update the layout so that the next draw request can correctly 289 // Update the layout so that the next draw request can correctly
319 // render the text and its attributes. 290 // render the text and its attributes.
320 virtual void UpdateLayout() = 0; 291 virtual void UpdateLayout() = 0;
321 292
322 // Ensure the text is laid out. 293 // Ensure the text is laid out.
(...skipping 20 matching lines...) Expand all
343 314
344 // Returns display offset based on current text alignment. 315 // Returns display offset based on current text alignment.
345 Point GetAlignmentOffset(); 316 Point GetAlignmentOffset();
346 317
347 // Returns the origin point for drawing text via Skia. 318 // Returns the origin point for drawing text via Skia.
348 Point GetOriginForSkiaDrawing(); 319 Point GetOriginForSkiaDrawing();
349 320
350 // Applies fade effects to |renderer|. 321 // Applies fade effects to |renderer|.
351 void ApplyFadeEffects(internal::SkiaTextRenderer* renderer); 322 void ApplyFadeEffects(internal::SkiaTextRenderer* renderer);
352 323
324 // A convenience function to check whether the glyph attached to the caret
325 // is within the given range.
326 static bool RangeContainsCaret(const ui::Range& range,
327 size_t caret_pos,
328 LogicalCursorDirection caret_affinity);
329
353 private: 330 private:
354 friend class RenderTextTest; 331 friend class RenderTextTest;
355 332
356 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, DefaultStyle); 333 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, DefaultStyle);
357 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, CustomDefaultStyle); 334 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, CustomDefaultStyle);
358 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, ApplyStyleRange); 335 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, ApplyStyleRange);
359 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, StyleRangesAdjust); 336 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, StyleRangesAdjust);
360 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, GraphemePositions); 337 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, GraphemePositions);
361 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, SelectionModels); 338 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, EdgeSelectionModels);
362 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, OriginForSkiaDrawing); 339 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, OriginForSkiaDrawing);
363 340
364 // Set the cursor to |position|, with the caret trailing the previous 341 // Set the cursor to |position|, with the caret trailing the previous
365 // grapheme, or if there is no previous grapheme, leading the cursor position. 342 // grapheme, or if there is no previous grapheme, leading the cursor position.
366 // If |select| is false, the selection start is moved to the same position. 343 // If |select| is false, the selection start is moved to the same position.
367 // If the |position| is not a cursorable position (not on grapheme boundary), 344 // If the |position| is not a cursorable position (not on grapheme boundary),
368 // it is a NO-OP. 345 // it is a NO-OP.
369 void MoveCursorTo(size_t position, bool select); 346 void MoveCursorTo(size_t position, bool select);
370 347
371 // Update the cached bounds and display offset to ensure that the current 348 // Update the cached bounds and display offset to ensure that the current
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 // The cached bounds and offset are invalidated by changes to the cursor, 401 // The cached bounds and offset are invalidated by changes to the cursor,
425 // selection, font, and other operations that adjust the visible text bounds. 402 // selection, font, and other operations that adjust the visible text bounds.
426 bool cached_bounds_and_offset_valid_; 403 bool cached_bounds_and_offset_valid_;
427 404
428 DISALLOW_COPY_AND_ASSIGN(RenderText); 405 DISALLOW_COPY_AND_ASSIGN(RenderText);
429 }; 406 };
430 407
431 } // namespace gfx 408 } // namespace gfx
432 409
433 #endif // UI_GFX_RENDER_TEXT_H_ 410 #endif // UI_GFX_RENDER_TEXT_H_
OLDNEW
« no previous file with comments | « ui/gfx/canvas_skia_skia.cc ('k') | ui/gfx/render_text.cc » ('j') | ui/gfx/render_text.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698