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

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

Issue 7461102: modification to RenderText for inheritance/SelectionModel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' 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
« no previous file with comments | « no previous file | ui/gfx/render_text.cc » ('j') | ui/gfx/render_text.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #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 <vector> 10 #include <vector>
10 11
11 #include "base/gtest_prod_util.h" 12 #include "base/gtest_prod_util.h"
12 #include "base/i18n/rtl.h" 13 #include "base/i18n/rtl.h"
13 #include "base/string16.h" 14 #include "base/string16.h"
14 #include "third_party/skia/include/core/SkColor.h" 15 #include "third_party/skia/include/core/SkColor.h"
15 #include "ui/base/range/range.h" 16 #include "ui/base/range/range.h"
16 #include "ui/gfx/font.h" 17 #include "ui/gfx/font.h"
17 #include "ui/gfx/rect.h" 18 #include "ui/gfx/rect.h"
18 #include "ui/gfx/point.h" 19 #include "ui/gfx/point.h"
19 20
20 namespace { 21 namespace gfx {
21 22
22 // Strike line width. 23 // Strike line width.
23 const int kStrikeWidth = 2; 24 const int kStrikeWidth = 2;
24 25
25 // Color settings for text, backgrounds and cursor. 26 // Color settings for text, backgrounds and cursor.
26 // These are tentative, and should be derived from theme, system 27 // These are tentative, and should be derived from theme, system
27 // settings and current settings. 28 // settings and current settings.
28 // TODO(oshima): Change this to match the standard chrome 29 // TODO(oshima): Change this to match the standard chrome
29 // before dogfooding textfield views. 30 // before dogfooding textfield views.
30 const SkColor kSelectedTextColor = SK_ColorWHITE; 31 const SkColor kSelectedTextColor = SK_ColorWHITE;
31 const SkColor kFocusedSelectionColor = SK_ColorCYAN; 32 const SkColor kFocusedSelectionColor = SK_ColorCYAN;
32 const SkColor kUnfocusedSelectionColor = SK_ColorLTGRAY; 33 const SkColor kUnfocusedSelectionColor = SK_ColorLTGRAY;
33 const SkColor kCursorColor = SK_ColorBLACK; 34 const SkColor kCursorColor = SK_ColorBLACK;
34 35
35 } // namespace
36
37 namespace gfx {
38
39 class Canvas; 36 class Canvas;
40 class RenderTextTest; 37 class RenderTextTest;
41 38
42 // A visual style applicable to a range of text. 39 // A visual style applicable to a range of text.
43 struct UI_API StyleRange { 40 struct UI_API StyleRange {
44 StyleRange(); 41 StyleRange();
45 42
46 Font font; 43 Font font;
47 SkColor foreground; 44 SkColor foreground;
48 bool strike; 45 bool strike;
49 bool underline; 46 bool underline;
50 ui::Range range; 47 ui::Range range;
51 }; 48 };
52 49
53 typedef std::vector<StyleRange> StyleRanges; 50 typedef std::vector<StyleRange> StyleRanges;
54 51
55 // TODO(msw): Distinguish between logical character and glyph? 52 // TODO(msw): Distinguish between logical character and glyph?
56 enum BreakType { 53 enum BreakType {
57 CHARACTER_BREAK, 54 CHARACTER_BREAK,
58 WORD_BREAK, 55 WORD_BREAK,
59 LINE_BREAK, 56 LINE_BREAK,
60 }; 57 };
61 58
59 // TODO(xji): publish bidi-editing guide line and replace the place holder.
60 // SelectionModel is used to represent the logical selection and visual
61 // position of cursor.
62 //
63 // For bi-directional text, the mapping between visual position and logical
64 // position is not one-to-one. For example, logical text "abcDEF" where capital
65 // letters stand for Hebrew, the visual display is "abcFED". According to the
66 // bidi editing guide (http://bidi-editing-guideline):
67 // 1. If pointing to the right half of the cell of a LTR character, the current
68 // position must be set after this character and the caret must be displayed
69 // after this character.
70 // 2. If pointing to the right half of the cell of a RTL character, the current
71 // position must be set before this character and the caret must be displayed
72 // before this character.
73 //
74 // Pointing to the right half of 'c' and pointing to the right half of 'D' both
75 // set the logical cursor position to 3. But the cursor displayed visually at
76 // different places:
77 // Pointing to the right half of 'c' displays the cursor right of 'c' as
78 // "abc|FED".
79 // Pointing to the right half of 'D' displays the cursor right of 'D' as
80 // "abcFED|".
81 // So, besides the logical selection start point and end point, we need extra
82 // information to specify to which character and on which edge of the character
83 // the visual cursor is bound to. For example, the visual cursor is bound to
84 // the trailing side of the 2nd character 'c' when pointing to right half of
85 // 'c'. And it is bound to the leading edge of the 3rd character 'D' when
86 // pointing to right of 'D'.
87 class UI_API SelectionModel {
88 public:
89 enum CaretPlacement {
90 // PREVIOUS_GRAPHEME_TRAILING means cursor is visually attached to the
91 // trailing edge of previous grapheme.
92 PREVIOUS_GRAPHEME_TRAILING,
93 LEADING,
94 TRAILING,
95 };
96
97 SelectionModel();
98 explicit SelectionModel(size_t pos);
99 SelectionModel(size_t end, size_t pos, CaretPlacement status);
100 SelectionModel(size_t start, size_t end, size_t pos, CaretPlacement status);
101
102 virtual ~SelectionModel();
103
104 size_t selection_start() const { return selection_start_; }
105 void set_selection_start(size_t pos) { selection_start_ = pos; }
106
107 size_t selection_end() const { return selection_end_; }
108 void set_selection_end(size_t pos) { selection_end_ = pos; }
109
110 size_t caret_pos() const { return caret_pos_; }
111 void set_caret_pos(size_t pos) { caret_pos_ = pos; }
112
113 CaretPlacement caret_placement() const { return caret_placement_; }
114 void set_caret_placement(CaretPlacement placement) {
115 caret_placement_ = placement;
116 }
117
118 bool Equals(const SelectionModel& sel) const;
119
120 private:
121 void Init(size_t start, size_t end, size_t pos, CaretPlacement status);
122
123 // Logical selection start. If there is non-empty selection, the selection
124 // always starts visually at the leading edge of the selection_start. So, we
125 // do not need extra information for visual selection bounding.
126 size_t selection_start_;
127
128 // The logical cursor position that next character will be inserted into.
129 // It is also the end of the selection.
130 size_t selection_end_;
131
132 // The following two fields are used to guide cursor visual position.
133 // The index of the character that cursor is visually attached to.
134 size_t caret_pos_;
135 // The visual placement of the cursor, relative to its associated character.
136 CaretPlacement caret_placement_;
137 };
138
62 // TODO(msw): Implement RenderText[Win|Linux] for Uniscribe/Pango BiDi... 139 // TODO(msw): Implement RenderText[Win|Linux] for Uniscribe/Pango BiDi...
63 140
64 // RenderText represents an abstract model of styled text and its corresponding 141 // RenderText represents an abstract model of styled text and its corresponding
65 // visual layout. Support is built in for a cursor, a selection, simple styling, 142 // visual layout. Support is built in for a cursor, a selection, simple styling,
66 // complex scripts, and bi-directional text. Implementations provide mechanisms 143 // complex scripts, and bi-directional text. Implementations provide mechanisms
67 // for rendering and translation between logical and visual data. 144 // for rendering and translation between logical and visual data.
68 class UI_API RenderText { 145 class UI_API RenderText {
69
70 public: 146 public:
71 virtual ~RenderText(); 147 virtual ~RenderText();
72 148
73 // Creates a platform-specific RenderText instance. 149 // Creates a platform-specific RenderText instance.
74 static RenderText* CreateRenderText(); 150 static RenderText* CreateRenderText();
75 151
76 const string16& text() const { return text_; } 152 const string16& text() const { return text_; }
77 virtual void SetText(const string16& text); 153 virtual void SetText(const string16& text);
78 154
155 const SelectionModel& selection_model() const { return selection_model_; }
156 void SetSelectionModel(const SelectionModel& sel);
157
79 bool cursor_visible() const { return cursor_visible_; } 158 bool cursor_visible() const { return cursor_visible_; }
80 void set_cursor_visible(bool visible) { cursor_visible_ = visible; } 159 void set_cursor_visible(bool visible) { cursor_visible_ = visible; }
81 160
82 bool insert_mode() const { return insert_mode_; } 161 bool insert_mode() const { return insert_mode_; }
83 void toggle_insert_mode() { insert_mode_ = !insert_mode_; } 162 void toggle_insert_mode() { insert_mode_ = !insert_mode_; }
84 163
85 bool focused() const { return focused_; } 164 bool focused() const { return focused_; }
86 void set_focused(bool focused) { focused_ = focused; } 165 void set_focused(bool focused) { focused_ = focused; }
87 166
88 const StyleRange& default_style() const { return default_style_; } 167 const StyleRange& default_style() const { return default_style_; }
89 void set_default_style(StyleRange style) { default_style_ = style; } 168 void set_default_style(StyleRange style) { default_style_ = style; }
90 169
91 const Rect& display_rect() const { return display_rect_; } 170 const Rect& display_rect() const { return display_rect_; }
92 void set_display_rect(const Rect& r) { display_rect_ = r; } 171 virtual void set_display_rect(const Rect& r) { display_rect_ = r; }
93 172
94 const gfx::Point& display_offset() const { return display_offset_; } 173 const gfx::Point& display_offset() const { return display_offset_; }
95 174
175 // This cursor position corresponds to SelectionModel::selection_end. In
176 // addition to representing the selection end, it's also where logical text
177 // edits take place, and doesn't necessarily correspond to
178 // SelectionModel::caret_pos.
96 size_t GetCursorPosition() const; 179 size_t GetCursorPosition() const;
97 void SetCursorPosition(const size_t position); 180 void SetCursorPosition(const size_t position);
98 181
182 void SetCaretPlacement(SelectionModel::CaretPlacement placement) {
183 selection_model_.set_caret_placement(placement);
184 }
185
99 // Moves the cursor left or right. Cursor movement is visual, meaning that 186 // Moves the cursor left or right. Cursor movement is visual, meaning that
100 // left and right are relative to screen, not the directionality of the text. 187 // left and right are relative to screen, not the directionality of the text.
101 // If |select| is false, the selection range is emptied at the new position. 188 // If |select| is false, the selection range is emptied at the new position.
102 // If |break_type| is CHARACTER_BREAK, move to the neighboring character. 189 // If |break_type| is CHARACTER_BREAK, move to the neighboring character.
103 // If |break_type| is WORD_BREAK, move to the nearest word boundary. 190 // If |break_type| is WORD_BREAK, move to the nearest word boundary.
104 // If |break_type| is LINE_BREAK, move to text edge as shown on screen. 191 // If |break_type| is LINE_BREAK, move to text edge as shown on screen.
105 void MoveCursorLeft(BreakType break_type, bool select); 192 void MoveCursorLeft(BreakType break_type, bool select);
106 void MoveCursorRight(BreakType break_type, bool select); 193 void MoveCursorRight(BreakType break_type, bool select);
107 194
108 // Moves the cursor to the specified logical |position|. 195 // Set the selection_model_ to the value of |selection|.
109 // If |select| is false, the selection range is emptied at the new position.
110 // Returns true if the cursor position or selection range changed. 196 // Returns true if the cursor position or selection range changed.
111 bool MoveCursorTo(size_t position, bool select); 197 bool MoveCursorTo(const SelectionModel& selection);
112 198
113 // Move the cursor to the position associated with the clicked point. 199 // Move the cursor to the position associated with the clicked point.
114 // If |select| is false, the selection range is emptied at the new position. 200 // If |select| is false, the selection range is emptied at the new position.
115 bool MoveCursorTo(const Point& point, bool select); 201 bool MoveCursorTo(const Point& point, bool select);
116 202
117 const ui::Range& GetSelection() const; 203 size_t GetSelectionStart() const {
118 void SetSelection(const ui::Range& range); 204 return selection_model_.selection_start();
205 }
206 size_t MinOfSelection() const {
207 return std::min(GetSelectionStart(), GetCursorPosition());
208 }
209 size_t MaxOfSelection() const {
210 return std::max(GetSelectionStart(), GetCursorPosition());
211 }
212 bool EmptySelection() const {
213 return GetSelectionStart() == GetCursorPosition();
214 }
119 215
120 // Returns true if the local point is over selected text. 216 // Returns true if the local point is over selected text.
121 bool IsPointInSelection(const Point& point) const; 217 bool IsPointInSelection(const Point& point);
122 218
123 // Selects no text, all text, or the word at the current cursor position. 219 // Selects no text, all text, or the word at the current cursor position.
124 void ClearSelection(); 220 void ClearSelection();
125 void SelectAll(); 221 void SelectAll();
126 void SelectWord(); 222 void SelectWord();
127 223
128 const ui::Range& GetCompositionRange() const; 224 const ui::Range& GetCompositionRange() const;
129 void SetCompositionRange(const ui::Range& composition_range); 225 void SetCompositionRange(const ui::Range& composition_range);
130 226
131 // Apply |style_range| to the internal style model. 227 // Apply |style_range| to the internal style model.
132 virtual void ApplyStyleRange(StyleRange style_range); 228 virtual void ApplyStyleRange(StyleRange style_range);
133 229
134 // Apply |default_style_| over the entire text range. 230 // Apply |default_style_| over the entire text range.
135 virtual void ApplyDefaultStyle(); 231 virtual void ApplyDefaultStyle();
136 232
137 base::i18n::TextDirection GetTextDirection() const; 233 base::i18n::TextDirection GetTextDirection() const;
138 234
139 // Get the width of the entire string. 235 // Get the width of the entire string.
140 int GetStringWidth() const; 236 virtual int GetStringWidth();
141 237
142 virtual void Draw(Canvas* canvas); 238 virtual void Draw(Canvas* canvas);
143 239
144 // TODO(msw): Deprecate this function. Logical and visual cursors are not 240 // Gets the SelectionModel from a visual point in local coordinates.
145 // mapped one-to-one. See the selection_range_ TODO for more information. 241 virtual SelectionModel FindCursorPosition(const Point& point);
146 // Get the logical cursor position from a visual point in local coordinates.
147 virtual size_t FindCursorPosition(const Point& point) const;
148 242
149 // Get the visual bounds containing the logical substring within |range|. 243 // Get the visual bounds containing the logical substring within |from| to
150 // These bounds could be visually discontiguous if the logical selection range 244 // |to|. These bounds could be visually discontinuous if the logical
151 // is split by an odd number of LTR/RTL level change. 245 // selection range is split by an odd number of LTR/RTL level change.
152 virtual std::vector<Rect> GetSubstringBounds( 246 virtual std::vector<Rect> GetSubstringBounds(
153 const ui::Range& range) const; 247 size_t from, size_t to) const;
154 248
155 // Get the visual bounds describing the cursor at |position|. These bounds 249 // Get the visual bounds describing the cursor at |selection|. These bounds
156 // typically represent a vertical line, but if |insert_mode| is true they 250 // typically represent a vertical line, but if |insert_mode| is true they
157 // contain the bounds of the associated glyph. 251 // contain the bounds of the associated glyph.
158 virtual Rect GetCursorBounds(size_t position, bool insert_mode) const; 252 virtual Rect GetCursorBounds(const SelectionModel& selection,
253 bool insert_mode);
254
255 // Compute cursor_bounds_ and update display_offset_ when necessary. Cache
256 // the values for later use and return cursor_bounds_.
257 Rect CursorBounds();
msw 2011/08/03 23:44:38 This should return a const ref.
xji 2011/08/04 06:26:50 Done.
159 258
160 protected: 259 protected:
161 RenderText(); 260 RenderText();
162 261
262 void set_cursor_bounds_valid(bool valid) { cursor_bounds_valid_ = valid; }
263
163 const StyleRanges& style_ranges() const { return style_ranges_; } 264 const StyleRanges& style_ranges() const { return style_ranges_; }
164 265
165 // Get the cursor position that visually neighbors |position|. 266 // Get the cursor position that visually neighbors |position|.
166 // If |move_by_word| is true, return the neighboring word delimiter position. 267 // If |move_by_word| is true, return the neighboring word delimiter position.
167 virtual size_t GetLeftCursorPosition(size_t position, 268 virtual SelectionModel GetLeftCursorPosition(const SelectionModel& current,
168 bool move_by_word) const; 269 bool move_by_word);
169 virtual size_t GetRightCursorPosition(size_t position, 270 virtual SelectionModel GetRightCursorPosition(const SelectionModel& current,
170 bool move_by_word) const; 271 bool move_by_word);
272
273 // Apply composition style (underline) to composition range and selection
274 // style (foreground) to selection range.
275 void ApplyCompositionAndSelectionStyles(StyleRanges* style_ranges) const;
171 276
172 private: 277 private:
173 friend class RenderTextTest; 278 friend class RenderTextTest;
174 279
175 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, DefaultStyle); 280 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, DefaultStyle);
176 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, CustomDefaultStyle); 281 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, CustomDefaultStyle);
177 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, ApplyStyleRange); 282 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, ApplyStyleRange);
178 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, StyleRangesAdjust); 283 FRIEND_TEST_ALL_PREFIXES(RenderTextTest, StyleRangesAdjust);
179 284
180 // Clear out |style_ranges_|. 285 // Clear out |style_ranges_|.
181 void ClearStyleRanges(); 286 void ClearStyleRanges();
182 287
183 bool IsPositionAtWordSelectionBoundary(size_t pos); 288 bool IsPositionAtWordSelectionBoundary(size_t pos);
184 289
290 void UpdateCursorBoundsAndDisplayOffset();
291
185 // Logical UTF-16 string data to be drawn. 292 // Logical UTF-16 string data to be drawn.
186 string16 text_; 293 string16 text_;
187 294
188 // TODO(msw): A single logical cursor position doesn't support two potential 295 // Logical selection range and visual cursor position.
189 // visual cursor positions. For example, clicking right of 'c' & 'D' yeilds: 296 SelectionModel selection_model_;
190 // (visually: 'abc|FEDghi' and 'abcFED|ghi', both logically: 'abc|DEFghi'). 297
191 // Similarly, one visual position may have two associated logical positions. 298 // The cached cursor bounds.
192 // For example, clicking the right side of 'D' and left side of 'g' yields: 299 Rect cursor_bounds_;
193 // (both visually: 'abcFED|ghi', logically: 'abc|DEFghi' and 'abcDEF|ghi'). 300 // cursor_bounds_ is computed when needed and cached afterwards. And it is
194 // Update the cursor model with a leading/trailing flag, a level association, 301 // invalidated in operations such as SetCursorPosition, SetSelection, Font
195 // or a disjoint visual position to satisfy the proposed visual behavior. 302 // related style change, and other operations that trigger re-layout.
196 // Logical selection range; the range end is also the logical cursor position. 303 bool cursor_bounds_valid_;
197 ui::Range selection_range_;
198 304
199 // The cursor visibility and insert mode. 305 // The cursor visibility and insert mode.
200 bool cursor_visible_; 306 bool cursor_visible_;
201 bool insert_mode_; 307 bool insert_mode_;
202 308
203 // The focus state of the text. 309 // The focus state of the text.
204 bool focused_; 310 bool focused_;
205 311
206 // Composition text range. 312 // Composition text range.
207 ui::Range composition_range_; 313 ui::Range composition_range_;
208 314
209 // List of style ranges. Elements in the list never overlap each other. 315 // List of style ranges. Elements in the list never overlap each other.
210 StyleRanges style_ranges_; 316 StyleRanges style_ranges_;
211 // The default text style. 317 // The default text style.
212 StyleRange default_style_; 318 StyleRange default_style_;
213 319
214 // The local display area for rendering the text. 320 // The local display area for rendering the text.
215 Rect display_rect_; 321 Rect display_rect_;
216 // The offset for the text to be drawn, relative to the display area. 322 // The offset for the text to be drawn, relative to the display area.
217 Point display_offset_; 323 Point display_offset_;
218 324
219 DISALLOW_COPY_AND_ASSIGN(RenderText); 325 DISALLOW_COPY_AND_ASSIGN(RenderText);
220 }; 326 };
221 327
222 } // namespace gfx 328 } // namespace gfx
223 329
224 #endif // UI_GFX_RENDER_TEXT_H_ 330 #endif // UI_GFX_RENDER_TEXT_H_
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/render_text.cc » ('j') | ui/gfx/render_text.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698