summaryrefslogtreecommitdiffstats
path: root/gfx
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-18 17:45:01 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-18 17:45:01 +0000
commit37edba0810da1caae3ba493531e00834224c4cad (patch)
treea20fa46327ccf617150857e7b2f8d1228b0320e3 /gfx
parent65d52b9b218a016bb62067b3d495d430a7d4b3af (diff)
downloadchromium_src-37edba0810da1caae3ba493531e00834224c4cad.zip
chromium_src-37edba0810da1caae3ba493531e00834224c4cad.tar.gz
chromium_src-37edba0810da1caae3ba493531e00834224c4cad.tar.bz2
Add 1px black border for ChromeOS status button.
- Move Linux's CanvasSkia::DrawStringInt into DrawStringWithHalo and added code to support text halo and change DrawStringInt to use it; - Make views::TextButton support text halo; - Use the text halo for chromeos::StatusButton; BUG=chromium-os:8657 TEST=Verify 1px black border is added to ChromeOS status buttons. Review URL: http://codereview.chromium.org/5071002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gfx')
-rw-r--r--gfx/canvas_skia.h12
-rw-r--r--gfx/canvas_skia_linux.cc237
2 files changed, 180 insertions, 69 deletions
diff --git a/gfx/canvas_skia.h b/gfx/canvas_skia.h
index 27781ff..d309784 100644
--- a/gfx/canvas_skia.h
+++ b/gfx/canvas_skia.h
@@ -67,11 +67,13 @@ class CanvasSkia : public skia::PlatformCanvas,
void DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y);
#endif
-#ifdef OS_WIN // Only implemented on Windows for now.
- // Draws text with a 1-pixel halo around it of the given color. It allows
- // ClearType to be drawn to an otherwise transparenct bitmap for drag images.
- // Drag images have only 1-bit of transparency, so we don't do any fancy
- // blurring.
+#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
+ // Draws text with a 1-pixel halo around it of the given color.
+ // On Windows, it allows ClearType to be drawn to an otherwise transparenct
+ // bitmap for drag images. Drag images have only 1-bit of transparency, so
+ // we don't do any fancy blurring.
+ // On Linux, text with halo is created by stroking it with 2px |halo_color|
+ // then filling it with |text_color|.
void DrawStringWithHalo(const std::wstring& text,
const gfx::Font& font,
const SkColor& text_color,
diff --git a/gfx/canvas_skia_linux.cc b/gfx/canvas_skia_linux.cc
index 57705a6..02a2dfab 100644
--- a/gfx/canvas_skia_linux.cc
+++ b/gfx/canvas_skia_linux.cc
@@ -88,20 +88,6 @@ static void UpdateCairoFontOptions() {
g_free(rgba_style);
}
-} // namespace
-
-namespace gfx {
-
-CanvasSkia::CanvasSkia(int width, int height, bool is_opaque)
- : skia::PlatformCanvas(width, height, is_opaque) {
-}
-
-CanvasSkia::CanvasSkia() : skia::PlatformCanvas() {
-}
-
-CanvasSkia::~CanvasSkia() {
-}
-
// Pass a width > 0 to force wrapping and elliding.
static void SetupPangoLayout(PangoLayout* layout,
const std::wstring& text,
@@ -122,21 +108,21 @@ static void SetupPangoLayout(PangoLayout* layout,
if (width > 0)
pango_layout_set_width(layout, width * PANGO_SCALE);
- if (flags & Canvas::NO_ELLIPSIS) {
+ if (flags & gfx::Canvas::NO_ELLIPSIS) {
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_NONE);
} else {
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
}
- if (flags & Canvas::TEXT_ALIGN_CENTER) {
+ if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) {
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
- } else if (flags & Canvas::TEXT_ALIGN_RIGHT) {
+ } else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) {
pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
}
- if (flags & Canvas::MULTI_LINE) {
+ if (flags & gfx::Canvas::MULTI_LINE) {
pango_layout_set_wrap(layout,
- (flags & Canvas::CHARACTER_BREAK) ?
+ (flags & gfx::Canvas::CHARACTER_BREAK) ?
PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD);
}
@@ -172,6 +158,156 @@ static void SetupPangoLayout(PangoLayout* layout,
}
}
+// A class to encapsulate string drawing params and operations.
+class DrawStringContext {
+ public:
+ DrawStringContext(gfx::CanvasSkia* canvas,
+ const std::wstring& text,
+ const gfx::Font& font,
+ const gfx::Rect& bounds,
+ const gfx::Rect& clip,
+ int flags);
+ ~DrawStringContext();
+
+ void Draw(const SkColor& text_color);
+ void DrawWithHalo(const SkColor& text_color,
+ const SkColor& halo_color);
+
+ private:
+ const gfx::Rect& bounds_;
+ int flags_;
+ const gfx::Font& font_;
+
+ gfx::CanvasSkia* canvas_;
+ cairo_t* cr_;
+ PangoLayout* layout_;
+
+ int text_x_;
+ int text_y_;
+ int text_width_;
+ int text_height_;
+
+ DISALLOW_COPY_AND_ASSIGN(DrawStringContext);
+};
+
+DrawStringContext::DrawStringContext(gfx::CanvasSkia* canvas,
+ const std::wstring& text,
+ const gfx::Font& font,
+ const gfx::Rect& bounds,
+ const gfx::Rect& clip,
+ int flags)
+ : bounds_(bounds),
+ flags_(flags),
+ font_(font),
+ canvas_(canvas),
+ cr_(NULL),
+ layout_(NULL),
+ text_x_(bounds.x()),
+ text_y_(bounds.y()),
+ text_width_(0),
+ text_height_(0) {
+ DCHECK(!bounds_.IsEmpty());
+
+ cr_ = canvas_->beginPlatformPaint();
+ layout_ = pango_cairo_create_layout(cr_);
+
+ SetupPangoLayout(layout_, text, font, bounds_.width(), 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_);
+
+ pango_layout_get_pixel_size(layout_, &text_width_, &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_y_ += (bounds.height() - text_height_);
+ } else {
+ // Vertically centered.
+ text_y_ += ((bounds.height() - text_height_) / 2);
+ }
+}
+
+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_);
+
+ g_object_unref(layout_);
+ // NOTE: beginPlatformPaint returned its surface, we shouldn't destroy it.
+}
+
+void DrawStringContext::Draw(const SkColor& text_color) {
+ cairo_set_source_rgba(cr_,
+ SkColorGetR(text_color) / 255.0,
+ SkColorGetG(text_color) / 255.0,
+ SkColorGetB(text_color) / 255.0,
+ SkColorGetA(text_color) / 255.0);
+ cairo_move_to(cr_, text_x_, text_y_);
+ pango_cairo_show_layout(cr_, layout_);
+}
+
+void DrawStringContext::DrawWithHalo(const SkColor& text_color,
+ const SkColor& halo_color) {
+ gfx::CanvasSkia text_canvas(bounds_.width() + 2, bounds_.height() + 2, false);
+ text_canvas.FillRectInt(static_cast<SkColor>(0),
+ 0, 0, bounds_.width() + 2, bounds_.height() + 2);
+
+ cairo_t* text_cr = text_canvas.beginPlatformPaint();
+
+ cairo_move_to(text_cr, 1, 1);
+ pango_cairo_layout_path(text_cr, layout_);
+
+ 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);
+ cairo_stroke_preserve(text_cr);
+
+ cairo_set_operator(text_cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba(text_cr,
+ SkColorGetR(text_color) / 255.0,
+ SkColorGetG(text_color) / 255.0,
+ SkColorGetB(text_color) / 255.0,
+ SkColorGetA(text_color) / 255.0);
+ cairo_fill(text_cr);
+
+ text_canvas.endPlatformPaint();
+
+ const SkBitmap& text_bitmap = const_cast<SkBitmap&>(
+ text_canvas.getTopPlatformDevice().accessBitmap(false));
+ canvas_->DrawBitmapInt(text_bitmap, text_x_ - 1, text_y_ - 1);
+}
+
+} // namespace
+
+namespace gfx {
+
+CanvasSkia::CanvasSkia(int width, int height, bool is_opaque)
+ : skia::PlatformCanvas(width, height, is_opaque) {
+}
+
+CanvasSkia::CanvasSkia() : skia::PlatformCanvas() {
+}
+
+CanvasSkia::~CanvasSkia() {
+}
+
// static
void CanvasSkia::SizeStringInt(const std::wstring& text,
const gfx::Font& font,
@@ -208,6 +344,21 @@ void CanvasSkia::SizeStringInt(const std::wstring& text,
cairo_surface_destroy(surface);
}
+void CanvasSkia::DrawStringWithHalo(const std::wstring& text,
+ const gfx::Font& font,
+ const SkColor& text_color,
+ const SkColor& halo_color,
+ int x, int y, int w, int h,
+ int flags) {
+ if (w <= 0 || h <= 0)
+ return;
+
+ gfx::Rect bounds(x, y, w, h);
+ gfx::Rect clip(x - 1, y - 1, w + 2, h + 2); // Bigger clip for halo
+ DrawStringContext context(this, text, font, bounds, clip,flags);
+ context.DrawWithHalo(text_color, halo_color);
+}
+
void CanvasSkia::DrawStringInt(const std::wstring& text,
const gfx::Font& font,
const SkColor& color,
@@ -216,51 +367,9 @@ void CanvasSkia::DrawStringInt(const std::wstring& text,
if (w <= 0 || h <= 0)
return;
- cairo_t* cr = beginPlatformPaint();
- PangoLayout* layout = pango_cairo_create_layout(cr);
-
- SetupPangoLayout(layout, text, font, w, flags);
-
- pango_layout_set_height(layout, h * PANGO_SCALE);
-
- cairo_save(cr);
- cairo_set_source_rgba(cr,
- SkColorGetR(color) / 255.0,
- SkColorGetG(color) / 255.0,
- SkColorGetB(color) / 255.0,
- SkColorGetA(color) / 255.0);
-
- int width, height;
- pango_layout_get_pixel_size(layout, &width, &height);
-
- cairo_rectangle(cr, x, y, w, h);
- cairo_clip(cr);
-
- if (flags & Canvas::TEXT_VALIGN_TOP) {
- // Cairo should draw from the top left corner already.
- } else if (flags & Canvas::TEXT_VALIGN_BOTTOM) {
- y += (h - height);
- } else {
- // Vertically centered.
- y += ((h - height) / 2);
- }
-
- cairo_move_to(cr, x, y);
- pango_cairo_show_layout(cr, layout);
- if (font.GetStyle() & gfx::Font::UNDERLINED) {
- gfx::PlatformFontGtk* platform_font =
- static_cast<gfx::PlatformFontGtk*>(font.platform_font());
- double underline_y =
- static_cast<double>(y) + height + platform_font->underline_position();
- cairo_set_line_width(cr, platform_font->underline_thickness());
- cairo_move_to(cr, x, underline_y);
- cairo_line_to(cr, x + width, underline_y);
- cairo_stroke(cr);
- }
- cairo_restore(cr);
-
- g_object_unref(layout);
- // NOTE: beginPlatformPaint returned its surface, we shouldn't destroy it.
+ gfx::Rect bounds(x, y, w, h);
+ DrawStringContext context(this, text, font, bounds, bounds, flags);
+ context.Draw(color);
}
void CanvasSkia::DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y) {