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); | |
msw
2012/06/06 18:35:25
Does this work ok with DIP / high dpi?
Alexei Svitkine (slow)
2012/06/06 18:46:23
It shouldn't cause any problems - though it will s
| |
82 renderer->SetUnderlineMetrics(PANGO_PIXELS(thickness), | |
msw
2012/06/06 18:35:25
Should these still use pango_units_to_double as a
Alexei Svitkine (slow)
2012/06/06 18:46:23
Since pango_quantize_line_geometry() guarantees pi
msw
2012/06/06 18:51:52
I guess my point was why not use pango_units_to_do
Alexei Svitkine (slow)
2012/06/06 19:03:05
I've added a comment about it.
| |
83 PANGO_PIXELS(position)); | |
84 } | |
85 | |
73 } // namespace | 86 } // namespace |
74 | 87 |
75 // TODO(xji): index saved in upper layer is utf16 index. Pango uses utf8 index. | 88 // 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 | 89 // Since caret_pos is used internally, we could save utf8 index for caret_pos |
77 // to avoid conversion. | 90 // to avoid conversion. |
78 | 91 |
79 RenderTextLinux::RenderTextLinux() | 92 RenderTextLinux::RenderTextLinux() |
80 : layout_(NULL), | 93 : layout_(NULL), |
81 current_line_(NULL), | 94 current_line_(NULL), |
82 log_attrs_(NULL), | 95 log_attrs_(NULL), |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 DCHECK_GE(style, 0); | 451 DCHECK_GE(style, 0); |
439 DCHECK_LT(style, static_cast<int>(styles.size())); | 452 DCHECK_LT(style, static_cast<int>(styles.size())); |
440 if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) { | 453 if (!IndexInRange(style_ranges_utf8[style], glyph_byte_index)) { |
441 // TODO(asvitkine): For cases like "fi", where "fi" is a single glyph | 454 // TODO(asvitkine): For cases like "fi", where "fi" is a single glyph |
442 // but can span multiple styles, Pango splits the | 455 // but can span multiple styles, Pango splits the |
443 // styles evenly over the glyph. We can do this too by | 456 // styles evenly over the glyph. We can do this too by |
444 // clipping and drawing the glyph several times. | 457 // clipping and drawing the glyph several times. |
445 renderer.SetForegroundColor(styles[style].foreground); | 458 renderer.SetForegroundColor(styles[style].foreground); |
446 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); | 459 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); |
447 renderer.DrawPosText(&pos[start], &glyphs[start], i - start); | 460 renderer.DrawPosText(&pos[start], &glyphs[start], i - start); |
461 if (styles[style].underline) | |
462 SetPangoUnderlineMetrics(desc.get(), &renderer); | |
448 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); | 463 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); |
449 | 464 |
450 start = i; | 465 start = i; |
451 start_x = glyph_x; | 466 start_x = glyph_x; |
452 // Loop to find the next style, in case the glyph spans multiple styles. | 467 // Loop to find the next style, in case the glyph spans multiple styles. |
453 do { | 468 do { |
454 style += style_increment; | 469 style += style_increment; |
455 } while (style >= 0 && style < static_cast<int>(styles.size()) && | 470 } while (style >= 0 && style < static_cast<int>(styles.size()) && |
456 !IndexInRange(style_ranges_utf8[style], glyph_byte_index)); | 471 !IndexInRange(style_ranges_utf8[style], glyph_byte_index)); |
457 } | 472 } |
458 } | 473 } |
459 | 474 |
460 // Draw the remaining glyphs. | 475 // Draw the remaining glyphs. |
461 renderer.SetForegroundColor(styles[style].foreground); | 476 renderer.SetForegroundColor(styles[style].foreground); |
462 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); | 477 renderer.SetFontFamilyWithStyle(family_name, styles[style].font_style); |
463 renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start); | 478 renderer.DrawPosText(&pos[start], &glyphs[start], glyph_count - start); |
479 if (styles[style].underline) | |
480 SetPangoUnderlineMetrics(desc.get(), &renderer); | |
464 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); | 481 renderer.DrawDecorations(start_x, y, glyph_x - start_x, styles[style]); |
465 x = glyph_x; | 482 x = glyph_x; |
466 } | 483 } |
467 } | 484 } |
468 | 485 |
469 GSList* RenderTextLinux::GetRunContainingCaret( | 486 GSList* RenderTextLinux::GetRunContainingCaret( |
470 const SelectionModel& caret) const { | 487 const SelectionModel& caret) const { |
471 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); | 488 size_t position = TextIndexToLayoutIndex(caret.caret_pos()); |
472 LogicalCursorDirection affinity = caret.caret_affinity(); | 489 LogicalCursorDirection affinity = caret.caret_affinity(); |
473 GSList* run = current_line_->runs; | 490 GSList* run = current_line_->runs; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 return bounds; | 558 return bounds; |
542 } | 559 } |
543 | 560 |
544 std::vector<Rect> RenderTextLinux::GetSelectionBounds() { | 561 std::vector<Rect> RenderTextLinux::GetSelectionBounds() { |
545 if (selection_visual_bounds_.empty()) | 562 if (selection_visual_bounds_.empty()) |
546 selection_visual_bounds_ = CalculateSubstringBounds(selection()); | 563 selection_visual_bounds_ = CalculateSubstringBounds(selection()); |
547 return selection_visual_bounds_; | 564 return selection_visual_bounds_; |
548 } | 565 } |
549 | 566 |
550 } // namespace gfx | 567 } // namespace gfx |
OLD | NEW |