OLD | NEW |
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 Loading... |
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(Range(index)), which returns true if |index| == |range.end()|. | 43 // |range.Contains(gfx::Range(index))| - as that would return true when |
| 44 // |index| == |range.end()|. |
44 bool IndexInRange(const Range& range, size_t index) { | 45 bool IndexInRange(const Range& range, size_t index) { |
45 return index >= range.start() && index < range.end(); | 46 return index >= range.start() && index < range.end(); |
46 } | 47 } |
47 | 48 |
48 // Sets underline metrics on |renderer| according to Pango font |desc|. | 49 // Sets underline metrics on |renderer| according to Pango font |desc|. |
49 void SetPangoUnderlineMetrics(PangoFontDescription *desc, | 50 void SetPangoUnderlineMetrics(PangoFontDescription *desc, |
50 internal::SkiaTextRenderer* renderer) { | 51 internal::SkiaTextRenderer* renderer) { |
51 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); | 52 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); |
52 int thickness = pango_font_metrics_get_underline_thickness(metrics); | 53 int thickness = pango_font_metrics_get_underline_thickness(metrics); |
53 // Pango returns the position "above the baseline". Change its sign to convert | 54 // Pango returns the position "above the baseline". Change its sign to convert |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 Rect rect(x, 0, width, height); | 242 Rect rect(x, 0, width, height); |
242 rect.set_origin(ToViewPoint(rect.origin())); | 243 rect.set_origin(ToViewPoint(rect.origin())); |
243 bounds.push_back(rect); | 244 bounds.push_back(rect); |
244 } | 245 } |
245 g_free(ranges); | 246 g_free(ranges); |
246 return bounds; | 247 return bounds; |
247 } | 248 } |
248 | 249 |
249 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const { | 250 size_t RenderTextPango::TextIndexToLayoutIndex(size_t index) const { |
250 DCHECK(layout_); | 251 DCHECK(layout_); |
251 ptrdiff_t offset = UTF16IndexToOffset(text(), 0, index); | 252 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, index); |
252 // Clamp layout indices to the length of the text actually used for layout. | 253 // Clamp layout indices to the length of the text actually used for layout. |
253 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); | 254 offset = std::min<size_t>(offset, g_utf8_strlen(layout_text_, -1)); |
254 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); | 255 const char* layout_pointer = g_utf8_offset_to_pointer(layout_text_, offset); |
255 return (layout_pointer - layout_text_); | 256 return (layout_pointer - layout_text_); |
256 } | 257 } |
257 | 258 |
258 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const { | 259 size_t RenderTextPango::LayoutIndexToTextIndex(size_t index) const { |
259 DCHECK(layout_); | 260 DCHECK(layout_); |
260 const char* layout_pointer = layout_text_ + index; | 261 const char* layout_pointer = layout_text_ + index; |
261 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); | 262 const long offset = g_utf8_pointer_to_offset(layout_text_, layout_pointer); |
262 return UTF16OffsetToIndex(text(), 0, offset); | 263 return gfx::UTF16OffsetToIndex(text(), 0, offset); |
263 } | 264 } |
264 | 265 |
265 bool RenderTextPango::IsValidCursorIndex(size_t index) { | 266 bool RenderTextPango::IsCursorablePosition(size_t position) { |
266 if (index == 0 || index == text().length()) | 267 if (position == 0 && text().empty()) |
267 return true; | 268 return true; |
268 if (!IsValidLogicalIndex(index)) | 269 if (position >= text().length()) |
| 270 return position == text().length(); |
| 271 if (!gfx::IsValidCodePointIndex(text(), position)) |
269 return false; | 272 return false; |
270 | 273 |
271 EnsureLayout(); | 274 EnsureLayout(); |
272 ptrdiff_t offset = UTF16IndexToOffset(text(), 0, index); | 275 ptrdiff_t offset = gfx::UTF16IndexToOffset(text(), 0, position); |
273 // Check that the index is marked as a legitimate cursor position by Pango. | 276 // Check that the index corresponds with a valid text code point, that it is |
274 return offset < num_log_attrs_ && log_attrs_[offset].is_cursor_position; | 277 // marked as a legitimate cursor position by Pango, and that it is not |
| 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)); |
275 } | 281 } |
276 | 282 |
277 void RenderTextPango::ResetLayout() { | 283 void RenderTextPango::ResetLayout() { |
278 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every | 284 // set_cached_bounds_and_offset_valid(false) is done in RenderText for every |
279 // operation that triggers ResetLayout(). | 285 // operation that triggers ResetLayout(). |
280 if (layout_) { | 286 if (layout_) { |
281 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. | 287 // TODO(msw): Keep |layout_| across text changes, etc.; it can be re-used. |
282 g_object_unref(layout_); | 288 g_object_unref(layout_); |
283 layout_ = NULL; | 289 layout_ = NULL; |
284 } | 290 } |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 SkScalar y = SkIntToScalar(offset.y()); | 384 SkScalar y = SkIntToScalar(offset.y()); |
379 | 385 |
380 std::vector<SkPoint> pos; | 386 std::vector<SkPoint> pos; |
381 std::vector<uint16> glyphs; | 387 std::vector<uint16> glyphs; |
382 | 388 |
383 internal::SkiaTextRenderer renderer(canvas); | 389 internal::SkiaTextRenderer renderer(canvas); |
384 ApplyFadeEffects(&renderer); | 390 ApplyFadeEffects(&renderer); |
385 ApplyTextShadows(&renderer); | 391 ApplyTextShadows(&renderer); |
386 | 392 |
387 // TODO(derat): Use font-specific params: http://crbug.com/125235 | 393 // TODO(derat): Use font-specific params: http://crbug.com/125235 |
388 const FontRenderParams& render_params = GetDefaultFontRenderParams(); | 394 const gfx::FontRenderParams& render_params = |
| 395 gfx::GetDefaultFontRenderParams(); |
389 const bool use_subpixel_rendering = | 396 const bool use_subpixel_rendering = |
390 render_params.subpixel_rendering != | 397 render_params.subpixel_rendering != |
391 FontRenderParams::SUBPIXEL_RENDERING_NONE; | 398 gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE; |
392 renderer.SetFontSmoothingSettings( | 399 renderer.SetFontSmoothingSettings( |
393 render_params.antialiasing, | 400 render_params.antialiasing, |
394 use_subpixel_rendering && !background_is_transparent(), | 401 use_subpixel_rendering && !background_is_transparent(), |
395 render_params.subpixel_positioning); | 402 render_params.subpixel_positioning); |
396 | 403 |
397 SkPaint::Hinting skia_hinting = SkPaint::kNormal_Hinting; | 404 SkPaint::Hinting skia_hinting = SkPaint::kNormal_Hinting; |
398 switch (render_params.hinting) { | 405 switch (render_params.hinting) { |
399 case FontRenderParams::HINTING_NONE: | 406 case gfx::FontRenderParams::HINTING_NONE: |
400 skia_hinting = SkPaint::kNo_Hinting; | 407 skia_hinting = SkPaint::kNo_Hinting; |
401 break; | 408 break; |
402 case FontRenderParams::HINTING_SLIGHT: | 409 case gfx::FontRenderParams::HINTING_SLIGHT: |
403 skia_hinting = SkPaint::kSlight_Hinting; | 410 skia_hinting = SkPaint::kSlight_Hinting; |
404 break; | 411 break; |
405 case FontRenderParams::HINTING_MEDIUM: | 412 case gfx::FontRenderParams::HINTING_MEDIUM: |
406 skia_hinting = SkPaint::kNormal_Hinting; | 413 skia_hinting = SkPaint::kNormal_Hinting; |
407 break; | 414 break; |
408 case FontRenderParams::HINTING_FULL: | 415 case gfx::FontRenderParams::HINTING_FULL: |
409 skia_hinting = SkPaint::kFull_Hinting; | 416 skia_hinting = SkPaint::kFull_Hinting; |
410 break; | 417 break; |
411 } | 418 } |
412 renderer.SetFontHinting(skia_hinting); | 419 renderer.SetFontHinting(skia_hinting); |
413 | 420 |
414 // Temporarily apply composition underlines and selection colors. | 421 // Temporarily apply composition underlines and selection colors. |
415 ApplyCompositionAndSelectionStyles(); | 422 ApplyCompositionAndSelectionStyles(); |
416 | 423 |
417 internal::StyleIterator style(colors(), styles()); | 424 internal::StyleIterator style(colors(), styles()); |
418 for (GSList* it = current_line_->runs; it; it = it->next) { | 425 for (GSList* it = current_line_->runs; it; it = it->next) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
519 int glyph_index) const { | 526 int glyph_index) const { |
520 return LayoutIndexToTextIndex(run->item->offset + | 527 return LayoutIndexToTextIndex(run->item->offset + |
521 run->glyphs->log_clusters[glyph_index]); | 528 run->glyphs->log_clusters[glyph_index]); |
522 } | 529 } |
523 | 530 |
524 RenderText* RenderText::CreateInstance() { | 531 RenderText* RenderText::CreateInstance() { |
525 return new RenderTextPango; | 532 return new RenderTextPango; |
526 } | 533 } |
527 | 534 |
528 } // namespace gfx | 535 } // namespace gfx |
OLD | NEW |