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

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

Issue 7841056: fix know issues in RenderText (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: fix Win test failure Created 9 years, 3 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_linux.h" 5 #include "ui/gfx/render_text_linux.h"
6 6
7 #include <pango/pangocairo.h> 7 #include <pango/pangocairo.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 bounds = GetUpdatedCursorBounds(); 116 bounds = GetUpdatedCursorBounds();
117 if (cursor_visible() && focused()) 117 if (cursor_visible() && focused())
118 canvas->DrawRectInt(kCursorColor, 118 canvas->DrawRectInt(kCursorColor,
119 bounds.x(), 119 bounds.x(),
120 bounds.y(), 120 bounds.y(),
121 bounds.width(), 121 bounds.width(),
122 bounds.height()); 122 bounds.height());
123 } 123 }
124 124
125 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) { 125 SelectionModel RenderTextLinux::FindCursorPosition(const Point& point) {
126 // TODO(xji): when points outside of text, return HOME/END position.
127 PangoLayout* layout = EnsureLayout(); 126 PangoLayout* layout = EnsureLayout();
128 127
129 if (text().empty()) 128 if (text().empty())
130 return SelectionModel(0, 0, SelectionModel::LEADING); 129 return SelectionModel(0, 0, SelectionModel::LEADING);
131 130
132 Point p(ToTextPoint(point)); 131 Point p(ToTextPoint(point));
132
133 // When the point is outside of text, return HOME/END position.
134 if (p.x() < 0)
135 return LeftEndSelectionModel();
136 else if (p.x() > GetStringWidth())
137 return RightEndSelectionModel();
138
133 int caret_pos, trailing; 139 int caret_pos, trailing;
134 pango_layout_xy_to_index(layout, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE, 140 pango_layout_xy_to_index(layout, p.x() * PANGO_SCALE, p.y() * PANGO_SCALE,
135 &caret_pos, &trailing); 141 &caret_pos, &trailing);
136 142
137 size_t selection_end = caret_pos; 143 size_t selection_end = caret_pos;
138 if (trailing > 0) { 144 if (trailing > 0) {
139 const char* ch = g_utf8_offset_to_pointer(layout_text_ + caret_pos, 145 const char* ch = g_utf8_offset_to_pointer(layout_text_ + caret_pos,
140 trailing); 146 trailing);
141 DCHECK_GE(ch, layout_text_); 147 DCHECK_GE(ch, layout_text_);
142 DCHECK_LE(ch, layout_text_ + layout_text_len_); 148 DCHECK_LE(ch, layout_text_ + layout_text_len_);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 if (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) { 211 if (GetTextDirection() == base::i18n::RIGHT_TO_LEFT) {
206 if (current_line_->runs) { 212 if (current_line_->runs) {
207 PangoLayoutRun* first_visual_run = 213 PangoLayoutRun* first_visual_run =
208 reinterpret_cast<PangoLayoutRun*>(current_line_->runs->data); 214 reinterpret_cast<PangoLayoutRun*>(current_line_->runs->data);
209 PangoItem* item = first_visual_run->item; 215 PangoItem* item = first_visual_run->item;
210 if (item->analysis.level % 2 == 0) { // LTR. 216 if (item->analysis.level % 2 == 0) { // LTR.
211 size_t caret = Utf8IndexToUtf16Index(item->offset); 217 size_t caret = Utf8IndexToUtf16Index(item->offset);
212 return SelectionModel(text().length(), caret, SelectionModel::LEADING); 218 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
213 } else { // RTL. 219 } else { // RTL.
214 size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length, 220 size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length,
215 PREVIOUS); 221 false);
216 return SelectionModel(text().length(), caret, SelectionModel::TRAILING); 222 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
217 } 223 }
218 } 224 }
219 } 225 }
220 return SelectionModel(0, 0, SelectionModel::LEADING); 226 return SelectionModel(0, 0, SelectionModel::LEADING);
221 } 227 }
222 228
223 SelectionModel RenderTextLinux::RightEndSelectionModel() { 229 SelectionModel RenderTextLinux::RightEndSelectionModel() {
224 if (GetTextDirection() == base::i18n::LEFT_TO_RIGHT) { 230 if (GetTextDirection() == base::i18n::LEFT_TO_RIGHT) {
225 PangoLayoutRun* last_visual_run = GetLastRun(); 231 PangoLayoutRun* last_visual_run = GetLastRun();
226 if (last_visual_run) { 232 if (last_visual_run) {
227 PangoItem* item = last_visual_run->item; 233 PangoItem* item = last_visual_run->item;
228 if (item->analysis.level % 2 == 0) { // LTR. 234 if (item->analysis.level % 2 == 0) { // LTR.
229 size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length, 235 size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length,
230 PREVIOUS); 236 false);
231 return SelectionModel(text().length(), caret, SelectionModel::TRAILING); 237 return SelectionModel(text().length(), caret, SelectionModel::TRAILING);
232 } else { // RTL. 238 } else { // RTL.
233 size_t caret = Utf8IndexToUtf16Index(item->offset); 239 size_t caret = Utf8IndexToUtf16Index(item->offset);
234 return SelectionModel(text().length(), caret, SelectionModel::LEADING); 240 return SelectionModel(text().length(), caret, SelectionModel::LEADING);
235 } 241 }
236 } 242 }
237 } 243 }
238 return SelectionModel(0, 0, SelectionModel::LEADING); 244 return SelectionModel(0, 0, SelectionModel::LEADING);
239 } 245 }
240 246
241 size_t RenderTextLinux::GetIndexOfPreviousGrapheme(size_t position) { 247 bool RenderTextLinux::IsCursorablePosition(size_t position) {
248 if (position == 0 && text().empty())
249 return true;
250
242 EnsureLayout(); 251 EnsureLayout();
243 size_t index = Utf16IndexToUtf8Index(position); 252 return (position >= 0 && position < static_cast<size_t>(num_log_attrs_) &&
244 return Utf16IndexOfAdjacentGrapheme(index, PREVIOUS); 253 log_attrs_[position].is_cursor_position);
245 } 254 }
246 255
247 size_t RenderTextLinux::GetIndexOfNextGrapheme(size_t position) { 256 size_t RenderTextLinux::IndexOfAdjacentGrapheme(size_t index, bool next) {
248 EnsureLayout(); 257 EnsureLayout();
249 size_t index = Utf16IndexToUtf8Index(position); 258 return Utf16IndexOfAdjacentGrapheme(Utf16IndexToUtf8Index(index), next);
250 return Utf16IndexOfAdjacentGrapheme(index, NEXT);
251 } 259 }
252 260
253 GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const { 261 GSList* RenderTextLinux::GetRunContainingPosition(size_t position) const {
254 GSList* run = current_line_->runs; 262 GSList* run = current_line_->runs;
255 while (run) { 263 while (run) {
256 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item; 264 PangoItem* item = reinterpret_cast<PangoLayoutRun*>(run->data)->item;
257 size_t run_start = Utf8IndexToUtf16Index(item->offset); 265 size_t run_start = Utf8IndexToUtf16Index(item->offset);
258 size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length); 266 size_t run_end = Utf8IndexToUtf16Index(item->offset + item->length);
259 267
260 if (position >= run_start && position < run_end) 268 if (position >= run_start && position < run_end)
261 return run; 269 return run;
262 run = run->next; 270 run = run->next;
263 } 271 }
264 return NULL; 272 return NULL;
265 } 273 }
266 274
267 size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme( 275 size_t RenderTextLinux::Utf8IndexOfAdjacentGrapheme(
268 size_t utf8_index_of_current_grapheme, 276 size_t utf8_index_of_current_grapheme, bool next) const {
msw 2011/09/16 17:39:08 |next| belongs on the following line, our style gu
xji 2011/09/16 20:29:24 Done.
269 RelativeLogicalPosition pos) const {
270 const char* ch = layout_text_ + utf8_index_of_current_grapheme; 277 const char* ch = layout_text_ + utf8_index_of_current_grapheme;
271 int char_offset = static_cast<int>(g_utf8_pointer_to_offset(layout_text_, 278 int char_offset = static_cast<int>(g_utf8_pointer_to_offset(layout_text_,
272 ch)); 279 ch));
273 int start_char_offset = char_offset; 280 int start_char_offset = char_offset;
274 if (pos == PREVIOUS) { 281 if (!next) {
275 if (char_offset > 0) { 282 if (char_offset > 0) {
276 do { 283 do {
277 --char_offset; 284 --char_offset;
278 } while (char_offset > 0 && !log_attrs_[char_offset].is_cursor_position); 285 } while (char_offset > 0 && !log_attrs_[char_offset].is_cursor_position);
279 } 286 }
280 } else { 287 } else {
281 if (char_offset < num_log_attrs_ - 1) { 288 if (char_offset < num_log_attrs_ - 1) {
282 do { 289 do {
283 ++char_offset; 290 ++char_offset;
284 } while (char_offset < num_log_attrs_ - 1 && 291 } while (char_offset < num_log_attrs_ - 1 &&
285 !log_attrs_[char_offset].is_cursor_position); 292 !log_attrs_[char_offset].is_cursor_position);
286 } 293 }
287 } 294 }
288 295
289 ch = g_utf8_offset_to_pointer(ch, char_offset - start_char_offset); 296 ch = g_utf8_offset_to_pointer(ch, char_offset - start_char_offset);
290 return static_cast<size_t>(ch - layout_text_); 297 return static_cast<size_t>(ch - layout_text_);
291 } 298 }
292 299
293 size_t RenderTextLinux::Utf16IndexOfAdjacentGrapheme( 300 size_t RenderTextLinux::Utf16IndexOfAdjacentGrapheme(
294 size_t utf8_index_of_current_grapheme, 301 size_t utf8_index_of_current_grapheme, bool next) const {
msw 2011/09/16 17:39:08 |next| on next line.
xji 2011/09/16 20:29:24 Done.
295 RelativeLogicalPosition pos) const {
296 size_t utf8_index = Utf8IndexOfAdjacentGrapheme( 302 size_t utf8_index = Utf8IndexOfAdjacentGrapheme(
297 utf8_index_of_current_grapheme, pos); 303 utf8_index_of_current_grapheme, next);
298 return Utf8IndexToUtf16Index(utf8_index); 304 return Utf8IndexToUtf16Index(utf8_index);
299 } 305 }
300 306
301 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun( 307 SelectionModel RenderTextLinux::FirstSelectionModelInsideRun(
302 const PangoItem* item) const { 308 const PangoItem* item) const {
303 size_t caret = Utf8IndexToUtf16Index(item->offset); 309 size_t caret = Utf8IndexToUtf16Index(item->offset);
304 size_t cursor = Utf16IndexOfAdjacentGrapheme(item->offset, NEXT); 310 size_t cursor = Utf16IndexOfAdjacentGrapheme(item->offset, true);
305 return SelectionModel(cursor, caret, SelectionModel::TRAILING); 311 return SelectionModel(cursor, caret, SelectionModel::TRAILING);
306 } 312 }
307 313
308 SelectionModel RenderTextLinux::LastSelectionModelInsideRun( 314 SelectionModel RenderTextLinux::LastSelectionModelInsideRun(
309 const PangoItem* item) const { 315 const PangoItem* item) const {
310 size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length, 316 size_t caret = Utf16IndexOfAdjacentGrapheme(item->offset + item->length,
311 PREVIOUS); 317 false);
312 return SelectionModel(caret, caret, SelectionModel::LEADING); 318 return SelectionModel(caret, caret, SelectionModel::LEADING);
313 } 319 }
314 320
315 // Assume caret_pos in |current| is n, 'l' represents leading in 321 // Assume caret_pos in |current| is n, 'l' represents leading in
316 // caret_placement and 't' represents trailing in caret_placement. Following 322 // caret_placement and 't' represents trailing in caret_placement. Following
317 // is the calculation from (caret_pos, caret_placement) in |current| to 323 // is the calculation from (caret_pos, caret_placement) in |current| to
318 // (selection_end, caret_pos, caret_placement) when moving cursor left by 324 // (selection_end, caret_pos, caret_placement) when moving cursor left by
319 // one grapheme (for simplicity, assume each grapheme is one character). 325 // one grapheme (for simplicity, assume each grapheme is one character).
320 // If n is in LTR run, 326 // If n is in LTR run,
321 // (n, t) ---> (n, n, l). 327 // (n, t) ---> (n, n, l).
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const { 587 size_t RenderTextLinux::Utf8IndexToUtf16Index(size_t index) const {
582 int32_t utf16_index = 0; 588 int32_t utf16_index = 0;
583 UErrorCode ec = U_ZERO_ERROR; 589 UErrorCode ec = U_ZERO_ERROR;
584 u_strFromUTF8(NULL, 0, &utf16_index, layout_text_, index, &ec); 590 u_strFromUTF8(NULL, 0, &utf16_index, layout_text_, index, &ec);
585 DCHECK(ec == U_BUFFER_OVERFLOW_ERROR || 591 DCHECK(ec == U_BUFFER_OVERFLOW_ERROR ||
586 ec == U_STRING_NOT_TERMINATED_WARNING); 592 ec == U_STRING_NOT_TERMINATED_WARNING);
587 return utf16_index; 593 return utf16_index;
588 } 594 }
589 595
590 } // namespace gfx 596 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698