Chromium Code Reviews| Index: ui/gfx/pango_util.cc |
| diff --git a/ui/gfx/pango_util.cc b/ui/gfx/pango_util.cc |
| index 75043f4a23aadcb5b09c55602624fe9d7224d1f7..f3ede04015c7aa3fa03ac29209da2bee2f6c8eca 100644 |
| --- a/ui/gfx/pango_util.cc |
| +++ b/ui/gfx/pango_util.cc |
| @@ -12,6 +12,8 @@ |
| #include "base/utf_string_conversions.h" |
| #include "ui/gfx/canvas.h" |
| #include "ui/gfx/font.h" |
| +#include "ui/gfx/platform_font_pango.h" |
| +#include "ui/gfx/rect.h" |
| #if !defined(USE_WAYLAND) && defined(TOOLKIT_USES_GTK) |
| #include <gtk/gtk.h> |
| @@ -27,6 +29,13 @@ namespace { |
| // Marker for accelerators in the text. |
| const gunichar kAcceleratorChar = '&'; |
| +// Multiply by the text height to determine how much text should be faded |
| +// when elliding. |
| +const double kFadeWidthFactor = 1.5; |
| + |
| +// End state of the elliding fade. |
| +const double kFadeFinalAlpha = 0.15; |
| + |
| // Return |cairo_font_options|. If needed, allocate and update it based on |
| // GtkSettings. |
| cairo_font_options_t* GetCairoFontOptions() { |
| @@ -107,6 +116,38 @@ cairo_font_options_t* GetCairoFontOptions() { |
| namespace gfx { |
| +void DrawTextOntoCairoSurface(cairo_t* cr, |
| + const string16& text, |
| + const gfx::Font& font, |
| + const gfx::Rect& bounds, |
| + const gfx::Rect& clip, |
| + const SkColor& text_color, |
| + int flags) { |
| + PangoLayout* layout = pango_cairo_create_layout(cr); |
| + base::i18n::TextDirection text_direction = |
| + base::i18n::GetFirstStrongCharacterDirection(text); |
| + Rect text_rect(bounds.x(), bounds.y(), 0, 0); |
| + DCHECK(!bounds.IsEmpty()); |
| + |
| + gfx::SetupPangoLayout( |
| + layout, text, font, bounds.width(), text_direction, flags); |
| + |
| + pango_layout_set_height(layout, bounds.height() * PANGO_SCALE); |
| + |
| + cairo_save(cr); |
| + cairo_rectangle(cr, clip.x(), clip.y(), clip.width(), clip.height()); |
| + cairo_clip(cr); |
| + |
| + AdjustTextRectBasedOnLayout(layout, bounds, flags, &text_rect); |
| + |
| + DrawPangoLayout(cr, layout, font, bounds, text_rect, |
| + text_color, text_direction, flags); |
| + |
| + cairo_restore(cr); |
| + g_object_unref(layout); |
| +} |
| + |
|
Evan Stade
2011/10/26 21:46:05
^H
|
| + |
| // Pass a width greater than 0 to force wrapping and eliding. |
| void SetupPangoLayout(PangoLayout* layout, |
| const string16& text, |
| @@ -193,4 +234,96 @@ void SetupPangoLayout(PangoLayout* layout, |
| } |
| } |
| +void AdjustTextRectBasedOnLayout(PangoLayout* layout, |
| + const gfx::Rect& bounds, |
| + int flags, |
| + gfx::Rect* text_rect) { |
| + int text_width, text_height; |
| + pango_layout_get_pixel_size(layout, &text_width, &text_height); |
| + text_rect->set_width(text_width); |
| + text_rect->set_height(text_height); |
| + |
| + if (flags & gfx::Canvas::TEXT_VALIGN_TOP) { |
| + // Cairo should draw from the top left corner already. |
| + } else if (flags & gfx::Canvas::TEXT_VALIGN_BOTTOM) { |
| + text_rect->set_y(text_rect->y() + bounds.height() - text_rect->height()); |
| + } else { |
| + // Vertically centered. |
| + text_rect->set_y(text_rect->y() + |
| + ((bounds.height() - text_rect->height()) / 2)); |
| + } |
| +} |
| + |
| +void DrawPangoLayout(cairo_t* cr, |
| + PangoLayout* layout, |
| + const Font& font, |
| + const gfx::Rect& bounds, |
| + const gfx::Rect& text_rect, |
| + const SkColor& text_color, |
| + base::i18n::TextDirection text_direction, |
| + int flags) { |
| + double r = SkColorGetR(text_color) / 255.0, |
| + g = SkColorGetG(text_color) / 255.0, |
| + b = SkColorGetB(text_color) / 255.0, |
| + a = SkColorGetA(text_color) / 255.0; |
| + |
| + cairo_pattern_t* pattern = NULL; |
| + |
| + cairo_save(cr); |
| + |
| + // If we're not eliding, use a fixed color. |
| + // Otherwise, create a gradient pattern to use as the source. |
| + if (text_direction == base::i18n::RIGHT_TO_LEFT || |
| + (flags & gfx::Canvas::NO_ELLIPSIS) || |
| + text_rect.width() <= bounds.width()) { |
| + cairo_set_source_rgba(cr, r, g, b, a); |
| + } else { |
| + // Fade to semi-transparent to elide. |
| + int fade_width = static_cast<double>(text_rect.height()) * kFadeWidthFactor; |
| + if (fade_width > (bounds.width() / 2)) { |
| + // Don't fade more than half the text. |
| + fade_width = bounds.width() / 2; |
| + } |
| + int fade_x = bounds.x() + bounds.width() - fade_width; |
| + |
| + pattern = cairo_pattern_create_linear( |
| + fade_x, bounds.y(), bounds.x() + bounds.width(), bounds.y()); |
| + cairo_pattern_add_color_stop_rgba(pattern, 0, r, g, b, a); |
| + cairo_pattern_add_color_stop_rgba(pattern, 1, r, g, b, kFadeFinalAlpha); |
| + cairo_set_source(cr, pattern); |
| + } |
| + |
| + cairo_move_to(cr, text_rect.x(), text_rect.y()); |
| + pango_cairo_show_layout(cr, layout); |
| + |
| + if (font.GetStyle() & gfx::Font::UNDERLINED) { |
| + gfx::PlatformFontPango* platform_font = |
| + static_cast<gfx::PlatformFontPango*>(font.platform_font()); |
| + DrawPangoTextUnderline(cr, platform_font, 0.0, text_rect); |
| + } |
| + |
| + if (pattern) |
| + cairo_pattern_destroy(pattern); |
| + |
| + cairo_restore(cr); |
| +} |
| + |
| +void DrawPangoTextUnderline(cairo_t* cr, |
| + gfx::PlatformFontPango* platform_font, |
| + double extra_edge_width, |
| + const Rect& text_rect) { |
| + const double underline_y = |
| + static_cast<double>(text_rect.y()) + text_rect.height() + |
| + platform_font->underline_position(); |
| + cairo_set_line_width( |
| + cr, platform_font->underline_thickness() + 2 * extra_edge_width); |
| + cairo_move_to(cr, |
| + text_rect.x() - extra_edge_width, |
| + underline_y); |
| + cairo_line_to(cr, |
| + text_rect.x() + text_rect.width() + extra_edge_width, |
| + underline_y); |
| + cairo_stroke(cr); |
| +} |
| + |
| } // namespace gfx |