summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 06:15:43 +0000
committerderat@chromium.org <derat@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-22 06:15:43 +0000
commit4d4f41013ef967fc97d3d362f22bb2350ad9c3c8 (patch)
treebdaeec5a42a95c0d3e77fad6b171ecd92a14aed3 /ui/gfx
parent631cfecf211bb9d50fe22c274df79769defa95df (diff)
downloadchromium_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.cc97
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