Index: gfx/canvas_skia_linux.cc |
diff --git a/gfx/canvas_skia_linux.cc b/gfx/canvas_skia_linux.cc |
index 57705a68618fa83359b5bb03a7efa5a88371b86d..02a2dfabac1aa28a5befc4bb654094bcc8930beb 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) { |