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_linux.h" | 5 #include "ui/gfx/render_text_linux.h" |
6 | 6 |
7 #include <fontconfig/fontconfig.h> | 7 #include <fontconfig/fontconfig.h> |
8 #include <pango/pangocairo.h> | 8 #include <pango/pangocairo.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <string> | 10 #include <string> |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 int fc_rgba = FC_RGBA_RGB; | 63 int fc_rgba = FC_RGBA_RGB; |
64 FcPatternGetInteger(match, FC_RGBA, 0, &fc_rgba); | 64 FcPatternGetInteger(match, FC_RGBA, 0, &fc_rgba); |
65 FcPatternDestroy(pattern); | 65 FcPatternDestroy(pattern); |
66 FcPatternDestroy(match); | 66 FcPatternDestroy(match); |
67 | 67 |
68 already_queried = true; | 68 already_queried = true; |
69 subpixel_enabled = (fc_rgba != FC_RGBA_NONE); | 69 subpixel_enabled = (fc_rgba != FC_RGBA_NONE); |
70 return subpixel_enabled; | 70 return subpixel_enabled; |
71 } | 71 } |
72 | 72 |
| 73 // Sets underline metrics on |renderer| according to Pango font |desc|. |
| 74 void SetPangoUnderlineMetrics(PangoFontDescription *desc, |
| 75 internal::SkiaTextRenderer* renderer) { |
| 76 PangoFontMetrics* metrics = GetPangoFontMetrics(desc); |
| 77 int thickness = pango_font_metrics_get_underline_thickness(metrics); |
| 78 // Pango returns the position "above the baseline". Change its sign to convert |
| 79 // it to a vertical offset from the baseline. |
| 80 int position = -pango_font_metrics_get_underline_position(metrics); |
| 81 pango_quantize_line_geometry(&thickness, &position); |
| 82 // Note: pango_quantize_line_geometry() guarantees pixel boundaries, so |
| 83 // PANGO_PIXELS() is safe to use. |
| 84 renderer->SetUnderlineMetrics(PANGO_PIXELS(thickness), |
| 85 PANGO_PIXELS(position)); |
| 86 } |
| 87 |
73 } // namespace | 88 } // namespace |
74 | 89 |
75 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index. | 90 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index. |
76 // Since caret_pos is used internally, we could save utf8 index for caret_pos | 91 // Since caret_pos is used internally, we could save utf8 index for caret_pos |
77 // to avoid conversion. | 92 // to avoid conversion. |
78 | 93 |
79 RenderTextLinux::RenderTextLinux() | 94 RenderTextLinux::RenderTextLinux() |
80 : layout_(NULL), | 95 : layout_(NULL), |
81 current_line_(NULL), | 96 current_line_(NULL), |
82 log_attrs_(NULL), | 97 log_attrs_(NULL), |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 DCHECK_GE(style, 0); | 453 DCHECK_GE(style, 0); |
439 DCHECK_LT(style, static_cast<int>(styles.size())); | 454 DCHECK_LT(style, static_cast<int>(styles.size())); |
440 if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) { | 455 if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) { |
441 // TODO(asvitkine): For cases like "fi", where "fi" is a single glyph | 456 // TODO(asvitkine): For cases like "fi", where "fi" is a single glyph |
442 // but can span multiple styles, Pango splits the | 457 // but can span multiple styles, Pango splits the |
443 // styles evenly over the glyph. We can do this too by | 458 // styles evenly over the glyph. We can do this too by |
444 // clipping and drawing the glyph several times. | 459 // clipping and drawing the glyph several times. |
445 renderer.SetForegroundColor(styles[style].foreground); | 460 renderer.SetForegroundColor(styles[style].foreground); |
446 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); | 461 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); |
447 renderer.DrawPosText(&pos[start], &glyphs[start], i - start); | 462 renderer.DrawPosText(&pos[start], &glyphs[start], i - start); |
| 463 if (styles[style].underline) |
| 464 SetPangoUnderlineMetrics(desc.get(), &renderer); |
448 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); | 465 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); |
449 | 466 |
450 start = i; | 467 start = i; |
451 start_x = glyph_x; | 468 start_x = glyph_x; |
452 // Loop to find the next style, in case the glyph spans multiple styles. | 469 // Loop to find the next style, in case the glyph spans multiple styles. |
453 do { | 470 do { |
454 style += style_increment; | 471 style += style_increment; |
455 } while (style >= 0 && style < static_cast<int>(styles.size()) && | 472 } while (style >= 0 && style < static_cast<int>(styles.size()) && |
456 !IndexInRange(style_ranges_utf8[style], glyph_byte_index)); | 473 !IndexInRange(style_ranges_utf8[style], glyph_byte_index)); |
457 } | 474 } |
458 } | 475 } |
459 | 476 |
460 // Draw the remaining glyphs. | 477 // Draw the remaining glyphs. |
461 renderer.SetForegroundColor(styles[style].foreground); | 478 renderer.SetForegroundColor(styles[style].foreground); |
462 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); | 479 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); |
463 renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start); | 480 renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start); |
| 481 if (styles[style].underline) |
| 482 SetPangoUnderlineMetrics(desc.get(), &renderer); |
464 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); | 483 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); |
465 x = glyph_x; | 484 x = glyph_x; |
466 } | 485 } |
467 } | 486 } |
468 | 487 |
469 GSList* RenderTextLinux::GetRunContainingCaret( | 488 GSList* RenderTextLinux::GetRunContainingCaret( |
470 const SelectionModel& caret) const { | 489 const SelectionModel& caret) const { |
471 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); | 490 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); |
472 LogicalCursorDirection affinity = caret.caret_affinity(); | 491 LogicalCursorDirection affinity = caret.caret_affinity(); |
473 GSList* run = current_line_->runs; | 492 GSList* run = current_line_->runs; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 return bounds; | 560 return bounds; |
542 } | 561 } |
543 | 562 |
544 std::vector<Rect> RenderTextLinux::GetSelectionBounds() { | 563 std::vector<Rect> RenderTextLinux::GetSelectionBounds() { |
545 if (selection_visual_bounds_.empty()) | 564 if (selection_visual_bounds_.empty()) |
546 selection_visual_bounds_ = CalculateSubstringBounds(selection()); | 565 selection_visual_bounds_ = CalculateSubstringBounds(selection()); |
547 return selection_visual_bounds_; | 566 return selection_visual_bounds_; |
548 } | 567 } |
549 | 568 |
550 } // namespace gfx | 569 } // namespace gfx |
OLD | NEW |