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

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

Issue 252563003: Fix Views inline autocomplete with multi-char graphemes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Extrapolate on the comment. Created 6 years, 7 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 | « ui/gfx/render_text_pango.h ('k') | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "ui/gfx/render_text_pango.h" 5 #include "ui/gfx/render_text_pango.h"
6 6
7 #include <pango/pangocairo.h> 7 #include <pango/pangocairo.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
(...skipping 22 matching lines...) Expand all
33 } 33 }
34 34
35 // Returns true if the given visual cursor |direction| is logically forward 35 // Returns true if the given visual cursor |direction| is logically forward
36 // motion in the given Pango |item|. 36 // motion in the given Pango |item|.
37 bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) { 37 bool IsForwardMotion(VisualCursorDirection direction, const PangoItem* item) {
38 bool rtl = item->analysis.level & 1; 38 bool rtl = item->analysis.level & 1;
39 return rtl == (direction == CURSOR_LEFT); 39 return rtl == (direction == CURSOR_LEFT);
40 } 40 }
41 41
42 // Checks whether |range| contains |index|. This is not the same as calling 42 // Checks whether |range| contains |index|. This is not the same as calling
43 // |range.Contains(gfx::Range(index))| - as that would return true when 43 // range.Contains(Range(index)), which returns true if |index| == |range.end()|.
44 // |index| == |range.end()|.
45 bool IndexInRange(const Range& range, size_t index) { 44 bool IndexInRange(const Range& range, size_t index) {
46 return index >= range.start() && index < range.end(); 45 return index >= range.start() && index < range.end();
47 } 46 }
48 47
49 // Sets underline metrics on |renderer| according to Pango font |desc|. 48 // Sets underline metrics on |renderer| according to Pango font |desc|.
50 void SetPangoUnderlineMetrics(PangoFontDescription *desc, 49 void SetPangoUnderlineMetrics(PangoFontDescription *desc,
51 internal::SkiaTextRenderer* renderer) { 50 internal::SkiaTextRenderer* renderer) {
52 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); 51 PangoFontMetrics* metrics = GetPangoFontMetrics(desc);
53 int thickness = pango_font_metrics_get_underline_thickness(metrics); 52 int thickness = pango_font_metrics_get_underline_thickness(metrics);
54 // Pango returns the position "above the baseline". Change its sign to convert 53 // Pango returns the position "above the baseline". Change its sign to convert
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 Rect rect(x, 0, width, height); 241 Rect rect(x, 0, width, height);
243 rect.set_origin(ToViewPoint(rect.origin())); 242 rect.set_origin(ToViewPoint(rect.origin()));
244 bounds.push_back(rect); 243 bounds.push_back(rect);
245 } 244 }
246 g_free(ranges); 245 g_free(ranges);
247 return bounds; 246 return bounds;
248 } 247 }
249 248
250 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const { 249 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const {
251 DCHECK(layout_); 250 DCHECK(layout_);
252 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index); 251 ptrdiff_t offset = UTF16IndexToOffset(text(), 0, index);
253 // Clamp layout indices to the length of the text actually used for layout. 252 // Clamp layout indices to the length of the text actually used for layout.
254 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); 253 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1));
255 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); 254 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset);
256 return (layout_pointer - layout_text_); 255 return (layout_pointer - layout_text_);
257 } 256 }
258 257
259 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const { 258 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const {
260 DCHECK(layout_); 259 DCHECK(layout_);
261 const char* layout_pointer = layout_text_ + index; 260 const char* layout_pointer = layout_text_ + index;
262 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); 261 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer);
263 return gfx::UTF16OffsetToIndex(text(), 0, offset); 262 return UTF16OffsetToIndex(text(), 0, offset);
264 } 263 }
265 264
266 bool RenderTextPango::IsCursorablePosition(size_t position) { 265 bool RenderTextPango::IsValidCursorIndex(size_t index) {
267 if (position == 0 && text().empty()) 266 if (index == 0 || index == text().length())
268 return true; 267 return true;
269 if (position >= text().length()) 268 if (!IsValidLogicalIndex(index))
270 return position == text().length();
271 if (!gfx::IsValidCodePointIndex(text(), position))
272 return false; 269 return false;
273 270
274 EnsureLayout(); 271 EnsureLayout();
275 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position); 272 ptrdiff_t offset = UTF16IndexToOffset(text(), 0, index);
276 // Check that the index corresponds with a valid text code point, that it is 273 // Check that the index is marked as a legitimate cursor position by Pango.
277 // marked as a legitimate cursor position by Pango, and that it is not 274 return offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position;
278 // truncated from layout text (its glyph is shown on screen).
279 return (offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position &&
280 offset < g_utf8_strlen(layout_text_, -1));
281 } 275 }
282 276
283 void RenderTextPango::ResetLayout() { 277 void RenderTextPango::ResetLayout() {
284 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every 278 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every
285 // operation that triggers ResetLayout(). 279 // operation that triggers ResetLayout().
286 if (layout_) { 280 if (layout_) {
287 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. 281 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used.
288 g_object_unref(layout_); 282 g_object_unref(layout_);
289 layout_ = NULL; 283 layout_ = NULL;
290 } 284 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 SkScalar y = SkIntToScalar(offset.y()); 378 SkScalar y = SkIntToScalar(offset.y());
385 379
386 std::vector<SkPoint> pos; 380 std::vector<SkPoint> pos;
387 std::vector<uint16> glyphs; 381 std::vector<uint16> glyphs;
388 382
389 internal::SkiaTextRenderer renderer(canvas); 383 internal::SkiaTextRenderer renderer(canvas);
390 ApplyFadeEffects(&renderer); 384 ApplyFadeEffects(&renderer);
391 ApplyTextShadows(&renderer); 385 ApplyTextShadows(&renderer);
392 386
393 // TODO(derat): Use font-specific params: http://crbug.com/125235 387 // TODO(derat): Use font-specific params: http://crbug.com/125235
394 const gfx::FontRenderParams& render_params = 388 const FontRenderParams& render_params = GetDefaultFontRenderParams();
395 gfx::GetDefaultFontRenderParams();
396 const bool use_subpixel_rendering = 389 const bool use_subpixel_rendering =
397 render_params.subpixel_rendering != 390 render_params.subpixel_rendering !=
398 gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; 391 FontRenderParams::SUBPIXEL_RENDERING_NONE;
399 renderer.SetFontSmoothingSettings( 392 renderer.SetFontSmoothingSettings(
400 render_params.antialiasing, 393 render_params.antialiasing,
401 use_subpixel_rendering && !background_is_transparent(), 394 use_subpixel_rendering && !background_is_transparent(),
402 render_params.subpixel_positioning); 395 render_params.subpixel_positioning);
403 396
404 SkPaint::Hinting skia_hinting = SkPaint::kNormal_Hinting; 397 SkPaint::Hinting skia_hinting = SkPaint::kNormal_Hinting;
405 switch (render_params.hinting) { 398 switch (render_params.hinting) {
406 case gfx::FontRenderParams::HINTING_NONE: 399 case FontRenderParams::HINTING_NONE:
407 skia_hinting = SkPaint::kNo_Hinting; 400 skia_hinting = SkPaint::kNo_Hinting;
408 break; 401 break;
409 case gfx::FontRenderParams::HINTING_SLIGHT: 402 case FontRenderParams::HINTING_SLIGHT:
410 skia_hinting = SkPaint::kSlight_Hinting; 403 skia_hinting = SkPaint::kSlight_Hinting;
411 break; 404 break;
412 case gfx::FontRenderParams::HINTING_MEDIUM: 405 case FontRenderParams::HINTING_MEDIUM:
413 skia_hinting = SkPaint::kNormal_Hinting; 406 skia_hinting = SkPaint::kNormal_Hinting;
414 break; 407 break;
415 case gfx::FontRenderParams::HINTING_FULL: 408 case FontRenderParams::HINTING_FULL:
416 skia_hinting = SkPaint::kFull_Hinting; 409 skia_hinting = SkPaint::kFull_Hinting;
417 break; 410 break;
418 } 411 }
419 renderer.SetFontHinting(skia_hinting); 412 renderer.SetFontHinting(skia_hinting);
420 413
421 // Temporarily apply composition underlines and selection colors. 414 // Temporarily apply composition underlines and selection colors.
422 ApplyCompositionAndSelectionStyles(); 415 ApplyCompositionAndSelectionStyles();
423 416
424 internal::StyleIterator style(colors(), styles()); 417 internal::StyleIterator style(colors(), styles());
425 for (GSList* it = current_line_->runs; it; it = it->next) { 418 for (GSList* it = current_line_->runs; it; it = it->next) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 int glyph_index) const { 519 int glyph_index) const {
527 return LayoutIndexToTextIndex(run->item->offset + 520 return LayoutIndexToTextIndex(run->item->offset +
528 run->glyphs->log_clusters[glyph_index]); 521 run->glyphs->log_clusters[glyph_index]);
529 } 522 }
530 523
531 RenderText* RenderText::CreateInstance() { 524 RenderText* RenderText::CreateInstance() {
532 return new RenderTextPango; 525 return new RenderTextPango;
533 } 526 }
534 527
535 } // namespace gfx 528 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/render_text_pango.h ('k') | ui/gfx/render_text_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698