diff options
author | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 06:15:43 +0000 |
---|---|---|
committer | derat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-22 06:15:43 +0000 |
commit | 4d4f41013ef967fc97d3d362f22bb2350ad9c3c8 (patch) | |
tree | bdaeec5a42a95c0d3e77fad6b171ecd92a14aed3 /ui/gfx | |
parent | 631cfecf211bb9d50fe22c274df79769defa95df (diff) | |
download | chromium_src-4d4f41013ef967fc97d3d362f22bb2350ad9c3c8.zip chromium_src-4d4f41013ef967fc97d3d362f22bb2350ad9c3c8.tar.gz chromium_src-4d4f41013ef967fc97d3d362f22bb2350ad9c3c8.tar.bz2 |
linux: Fix text underline color/halo in Skia canvas.
This makes us use the correct color for underlined text and
draw a halo around the underlining when needed.
Manual testing:
- Checked that the underlining on the screen locker sign out
link is white.
- Hacked up status area text to be underlined and checked
that things are mostly reasonable when drawing normal,
embossed, or haloed text. (Actually,
underlined-and-haloed text can get clipped in some cases,
but I don't think that we use it anywhere and this is hard
to fix without a lot of refactoring -- we don't specify
whether text is going to be drawn with a halo or not when
requesting its size.)
- Turned on underlining on tab titles and checked that the
underline also fades out to the right on long, elided
titles.
BUG=chromium-os:16490
TEST=manual; see above
Review URL: http://codereview.chromium.org/7466025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93559 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r-- | ui/gfx/canvas_skia_linux.cc | 97 |
1 files changed, 70 insertions, 27 deletions
diff --git a/ui/gfx/canvas_skia_linux.cc b/ui/gfx/canvas_skia_linux.cc index 9887d2a..17da4fc 100644 --- a/ui/gfx/canvas_skia_linux.cc +++ b/ui/gfx/canvas_skia_linux.cc @@ -4,6 +4,8 @@ #include "ui/gfx/canvas_skia.h" +#include <algorithm> + #include <cairo/cairo.h> #include <gtk/gtk.h> #include <pango/pango.h> @@ -18,6 +20,8 @@ #include "ui/gfx/rect.h" #include "ui/gfx/skia_util.h" +using std::max; + namespace { const gunichar kAcceleratorChar = '&'; @@ -29,12 +33,15 @@ const double kFadeWidthFactor = 1.5; // End state of the elliding fade. const double kFadeFinalAlpha = 0.15; +// Width of the border drawn around haloed text. +const double kTextHaloWidth = 1.0; + // Font settings that we initialize once and then use when drawing text in // DrawStringInt(). -static cairo_font_options_t* cairo_font_options = NULL; +cairo_font_options_t* cairo_font_options = NULL; // Update |cairo_font_options| based on GtkSettings, allocating it if needed. -static void UpdateCairoFontOptions() { +void UpdateCairoFontOptions() { if (!cairo_font_options) cairo_font_options = cairo_font_options_create(); @@ -98,12 +105,12 @@ static void UpdateCairoFontOptions() { } // Pass a width > 0 to force wrapping and elliding. -static void SetupPangoLayout(PangoLayout* layout, - const string16& text, - const gfx::Font& font, - int width, - base::i18n::TextDirection text_direction, - int flags) { +void SetupPangoLayout(PangoLayout* layout, + const string16& text, + const gfx::Font& font, + int width, + base::i18n::TextDirection text_direction, + int flags) { if (!cairo_font_options) UpdateCairoFontOptions(); // This needs to be done early on; it has no effect when called just before @@ -189,10 +196,14 @@ class DrawStringContext { ~DrawStringContext(); void Draw(const SkColor& text_color); - void DrawWithHalo(const SkColor& text_color, - const SkColor& halo_color); + void DrawWithHalo(const SkColor& text_color, const SkColor& halo_color); private: + // Draw an underline under the text using |cr|, which must already be + // initialized with the correct source. |extra_edge_width| is added to the + // outer edge of the line. Helper method for Draw() and DrawWithHalo(). + void DrawUnderline(cairo_t* cr, double extra_edge_width); + const gfx::Rect& bounds_; int flags_; const gfx::Font& font_; @@ -256,21 +267,8 @@ DrawStringContext::DrawStringContext(gfx::CanvasSkia* canvas, } DrawStringContext::~DrawStringContext() { - if (font_.GetStyle() & gfx::Font::UNDERLINED) { - gfx::PlatformFontGtk* platform_font = - static_cast<gfx::PlatformFontGtk*>(font_.platform_font()); - double underline_y = - static_cast<double>(text_y_) + text_height_ + - platform_font->underline_position(); - cairo_set_line_width(cr_, platform_font->underline_thickness()); - cairo_move_to(cr_, text_x_, underline_y); - cairo_line_to(cr_, text_x_ + text_width_, underline_y); - cairo_stroke(cr_); - } cairo_restore(cr_); - skia::EndPlatformPaint(canvas_); - g_object_unref(layout_); // NOTE: BeginPlatformPaint returned its surface, we shouldn't destroy it. } @@ -310,6 +308,9 @@ void DrawStringContext::Draw(const SkColor& text_color) { cairo_move_to(cr_, text_x_, text_y_); pango_cairo_show_layout(cr_, layout_); + if (font_.GetStyle() & gfx::Font::UNDERLINED) + DrawUnderline(cr_, 0.0); + if (pattern) cairo_pattern_destroy(pattern); @@ -326,15 +327,27 @@ void DrawStringContext::DrawWithHalo(const SkColor& text_color, skia::ScopedPlatformPaint scoped_platform_paint(&text_canvas); cairo_t* text_cr = scoped_platform_paint.GetPlatformSurface(); - cairo_move_to(text_cr, 2, 1); - pango_cairo_layout_path(text_cr, layout_); - + // TODO: The current approach (stroking the text path to generate the halo + // and then filling it for the main text) won't work if |text_color| is + // non-opaque. If we need to do this at some later point, + // http://lists.freedesktop.org/archives/cairo/2004-September/001829.html + // suggests "do[ing] the stroke and fill with opaque paint onto an + // intermediate surface, and then us[ing] cairo_show_surface to composite + // that intermediate result with the desired compositing operator." cairo_set_source_rgba(text_cr, SkColorGetR(halo_color) / 255.0, SkColorGetG(halo_color) / 255.0, SkColorGetB(halo_color) / 255.0, SkColorGetA(halo_color) / 255.0); - cairo_set_line_width(text_cr, 2.0); + + // Draw the halo underline first so that we can use the same path for the + // outer/halo text and inner text. + if (font_.GetStyle() & gfx::Font::UNDERLINED) + DrawUnderline(text_cr, kTextHaloWidth); + + cairo_move_to(text_cr, 2, 1); + pango_cairo_layout_path(text_cr, layout_); + cairo_set_line_width(text_cr, 2 * kTextHaloWidth); cairo_set_line_join(text_cr, CAIRO_LINE_JOIN_ROUND); cairo_stroke_preserve(text_cr); @@ -345,6 +358,9 @@ void DrawStringContext::DrawWithHalo(const SkColor& text_color, SkColorGetB(text_color) / 255.0, SkColorGetA(text_color) / 255.0); cairo_fill(text_cr); + + if (font_.GetStyle() & gfx::Font::UNDERLINED) + DrawUnderline(text_cr, 0.0); } const SkBitmap& text_bitmap = const_cast<SkBitmap&>( @@ -352,6 +368,19 @@ void DrawStringContext::DrawWithHalo(const SkColor& text_color, canvas_->DrawBitmapInt(text_bitmap, text_x_ - 1, text_y_ - 1); } +void DrawStringContext::DrawUnderline(cairo_t* cr, double extra_edge_width) { + gfx::PlatformFontGtk* platform_font = + static_cast<gfx::PlatformFontGtk*>(font_.platform_font()); + const double underline_y = + static_cast<double>(text_y_) + text_height_ + + platform_font->underline_position(); + cairo_set_line_width( + cr, platform_font->underline_thickness() + 2 * extra_edge_width); + cairo_move_to(cr, text_x_ - extra_edge_width, underline_y); + cairo_line_to(cr, text_x_ + text_width_ + extra_edge_width, underline_y); + cairo_stroke(cr); +} + } // namespace namespace gfx { @@ -387,6 +416,20 @@ void CanvasSkia::SizeStringInt(const string16& text, pango_layout_get_pixel_size(layout, width, height); + if (font.GetStyle() & gfx::Font::UNDERLINED) { + gfx::PlatformFontGtk* platform_font = + static_cast<gfx::PlatformFontGtk*>(font.platform_font()); + *height += max(platform_font->underline_position() + + platform_font->underline_thickness(), 0.0); + } + + // TODO: If the text is being drawn with a halo, we should also pad each of + // the edges by |kTextHaloWidth|... except haloing is currently a drawing-time + // thing, and we don't know how the text will be drawn here. :-( This only + // seems to come into play at present if the text is both haloed and + // underlined; otherwise, the size returned by Pango is (at least sometimes) + // large enough to include the halo. + if (org_width > 0 && flags & Canvas::MULTI_LINE && pango_layout_is_wrapped(layout)) { // The text wrapped. There seems to be a bug in Pango when this happens |