From 3024338797b31cd0e0357878bcd5b084e4a8af69 Mon Sep 17 00:00:00 2001 From: "ben@chromium.org" Date: Wed, 23 Jun 2010 23:04:23 +0000 Subject: Canvas refactoring part 2. - Rename Canvas to CanvasSkia. - Create a subclass Canvas that inherits from CanvasSkia for compatibility. BUG=none TEST=none Review URL: http://codereview.chromium.org/2862025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50664 0039d316-1c4b-4281-b951-d872f2087c98 --- build/common.gypi | 5 - .../autocomplete/autocomplete_edit_view_win.cc | 3 +- chrome/browser/cocoa/bookmark_bar_toolbar_view.mm | 6 +- chrome/browser/cocoa/download_item_cell.mm | 6 +- .../cocoa/extensions/browser_action_button.mm | 4 +- chrome/browser/gtk/bookmark_bar_gtk.cc | 4 +- chrome/browser/gtk/bookmark_utils_gtk.cc | 4 +- chrome/browser/gtk/browser_actions_toolbar_gtk.cc | 4 +- chrome/browser/gtk/browser_toolbar_gtk.cc | 4 +- chrome/browser/gtk/download_item_gtk.cc | 4 +- chrome/browser/gtk/location_bar_view_gtk.cc | 4 +- chrome/browser/gtk/tabs/dragged_tab_gtk.cc | 1 - chrome/browser/gtk/tabs/tab_renderer_gtk.cc | 6 +- chrome/browser/gtk/tabs/tab_strip_gtk.cc | 1 - .../renderer_host/render_widget_host_view_win.cc | 11 +- .../autocomplete_popup_contents_view.cc | 2 + chrome/browser/views/bookmark_bar_view.cc | 6 +- chrome/browser/views/browser_actions_container.cc | 5 +- chrome/browser/views/browser_actions_container.h | 4 + .../browser_action_overflow_menu_controller.cc | 2 +- chrome/browser/views/infobars/extension_infobar.cc | 9 +- chrome/browser/views/sad_tab_view.cc | 3 +- .../views/tab_contents/tab_contents_view_gtk.cc | 4 +- .../views/tab_contents/tab_contents_view_win.cc | 4 +- chrome/browser/views/tabs/dragged_tab_view.cc | 2 + chrome/browser/views/tabs/tab.cc | 3 +- chrome/browser/views/theme_helpers.cc | 4 +- chrome/browser/views/toolbar_view.cc | 5 +- chrome/renderer/webplugin_delegate_proxy.cc | 4 +- gfx/canvas.cc | 325 --------------------- gfx/canvas.h | 124 +------- gfx/canvas_linux.cc | 269 ----------------- gfx/canvas_mac.mm | 84 ------ gfx/canvas_paint.h | 20 -- gfx/canvas_skia.cc | 324 ++++++++++++++++++++ gfx/canvas_skia.h | 135 +++++++++ gfx/canvas_skia_linux.cc | 269 +++++++++++++++++ gfx/canvas_skia_mac.mm | 84 ++++++ gfx/canvas_skia_paint.h | 20 ++ gfx/canvas_skia_win.cc | 293 +++++++++++++++++++ gfx/canvas_win.cc | 293 ------------------- gfx/gfx.gyp | 13 +- views/controls/menu/menu_controller.cc | 1 + views/controls/menu/menu_win.cc | 4 +- views/controls/menu/native_menu_win.cc | 4 +- views/controls/table/native_table_win.cc | 8 +- views/controls/table/table_view.cc | 8 +- views/controls/textfield/gtk_views_entry.cc | 4 +- views/controls/textfield/gtk_views_textview.cc | 4 +- views/controls/tree/tree_view.cc | 16 +- views/drag_utils.cc | 3 + views/widget/root_view_gtk.cc | 4 +- views/widget/root_view_win.cc | 3 +- views/widget/widget_win.cc | 1 + views/window/window_win.cc | 13 +- 55 files changed, 1251 insertions(+), 1199 deletions(-) delete mode 100644 gfx/canvas.cc delete mode 100644 gfx/canvas_linux.cc delete mode 100644 gfx/canvas_mac.mm delete mode 100644 gfx/canvas_paint.h create mode 100644 gfx/canvas_skia.cc create mode 100644 gfx/canvas_skia.h create mode 100644 gfx/canvas_skia_linux.cc create mode 100644 gfx/canvas_skia_mac.mm create mode 100644 gfx/canvas_skia_paint.h create mode 100644 gfx/canvas_skia_win.cc delete mode 100644 gfx/canvas_win.cc diff --git a/build/common.gypi b/build/common.gypi index afc6e29..51a8b51 100644 --- a/build/common.gypi +++ b/build/common.gypi @@ -584,11 +584,6 @@ }, }, }], - # Though Skia is conceptually shared by Linux and Windows, - # the only _skia files in our tree are Linux-specific. - ['OS!="linux" and OS!="freebsd" and OS!="openbsd"', { - 'sources/': [ ['exclude', '_skia\\.cc$'] ], - }], ['chromeos!=1', { 'sources/': [ ['exclude', '_chromeos\\.cc$'] ] }], diff --git a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc index 2795e6e..55b7530 100644 --- a/chrome/browser/autocomplete/autocomplete_edit_view_win.cc +++ b/chrome/browser/autocomplete/autocomplete_edit_view_win.cc @@ -44,6 +44,7 @@ #include "chrome/common/notification_service.h" #include "googleurl/src/url_util.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "grit/generated_resources.h" #include "net/base/escape.h" #include "skia/ext/skia_utils_win.h" @@ -2176,7 +2177,7 @@ void AutocompleteEditViewWin::DrawSlashForInsecureScheme( // Create a canvas as large as |scheme_rect| to do our drawing, and initialize // it to fully transparent so any antialiasing will look nice when painted // atop the edit. - gfx::Canvas canvas(scheme_rect.Width(), scheme_rect.Height(), false); + gfx::CanvasSkia canvas(scheme_rect.Width(), scheme_rect.Height(), false); canvas.getDevice()->accessBitmap(true).eraseARGB(0, 0, 0, 0); // Calculate the start and end of the stroke, which are just the lower left diff --git a/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm b/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm index 964a76e..9f50222 100644 --- a/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm +++ b/chrome/browser/cocoa/bookmark_bar_toolbar_view.mm @@ -12,7 +12,7 @@ #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/themed_window.h" #include "chrome/browser/ntp_background_util.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" const CGFloat kBorderRadius = 3.0; @@ -54,7 +54,7 @@ const CGFloat kBorderRadius = 3.0; // Draw the background. { - // CanvasPaint draws to the NSGraphicsContext during its destructor, so + // CanvasSkiaPaint draws to the NSGraphicsContext during its destructor, so // explicitly scope this. // // Paint the entire bookmark bar, even if the damage rect is much smaller @@ -66,7 +66,7 @@ const CGFloat kBorderRadius = 3.0; // already repainting the rest of the bookmark bar below without setting a // clip area, anyway. Also, the only time we weren't asked to redraw the // whole bookmark bar is when the find bar is drawn over it. - gfx::CanvasPaint canvas(bounds, true); + gfx::CanvasSkiaPaint canvas(bounds, true); gfx::Rect area(0, 0, NSWidth(bounds), NSHeight(bounds)); NtpBackgroundUtil::PaintBackgroundDetachedMode(themeProvider, &canvas, diff --git a/chrome/browser/cocoa/download_item_cell.mm b/chrome/browser/cocoa/download_item_cell.mm index 6e14a27..c9843aba 100644 --- a/chrome/browser/cocoa/download_item_cell.mm +++ b/chrome/browser/cocoa/download_item_cell.mm @@ -15,7 +15,7 @@ #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_util.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "grit/theme_resources.h" #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" @@ -562,7 +562,7 @@ NSGradient* BackgroundTheme::GetNSGradient(int id) const { // Draw progress disk { - // CanvasPaint draws its content to the current NSGraphicsContext in its + // CanvasSkiaPaint draws its content to the current NSGraphicsContext in its // destructor, which needs to be invoked before the icon is drawn below - // hence this nested block. @@ -575,7 +575,7 @@ NSGradient* BackgroundTheme::GetNSGradient(int id) const { download_util::kSmallProgressIconSize, download_util::kSmallProgressIconSize); - gfx::CanvasPaint canvas(dirtyRect, false); + gfx::CanvasSkiaPaint canvas(dirtyRect, false); canvas.set_composite_alpha(true); if (completionAnimation_.get()) { if ([completionAnimation_ isAnimating]) { diff --git a/chrome/browser/cocoa/extensions/browser_action_button.mm b/chrome/browser/cocoa/extensions/browser_action_button.mm index 914f11d..0a7dc46 100644 --- a/chrome/browser/cocoa/extensions/browser_action_button.mm +++ b/chrome/browser/cocoa/extensions/browser_action_button.mm @@ -19,7 +19,7 @@ #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/rect.h" #include "gfx/size.h" #include "skia/ext/skia_utils_mac.h" @@ -326,7 +326,7 @@ class ExtensionImageTrackerBridge : public NotificationObserver, } - (void)drawBadgeWithinFrame:(NSRect)frame { - gfx::CanvasPaint canvas(frame, false); + gfx::CanvasSkiaPaint canvas(frame, false); canvas.set_composite_alpha(true); gfx::Rect boundingRect(NSRectToCGRect(frame)); extensionAction_->PaintBadge(&canvas, boundingRect, tabId_); diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc index f5c9f53..b4a6d77 100644 --- a/chrome/browser/gtk/bookmark_bar_gtk.cc +++ b/chrome/browser/gtk/bookmark_bar_gtk.cc @@ -41,7 +41,7 @@ #include "chrome/browser/tab_contents/tab_contents_view.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/gtk_util.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" @@ -1267,7 +1267,7 @@ gboolean BookmarkBarGtk::OnEventBoxExpose(GtkWidget* widget, gfx::Size tab_contents_size; if (!GetTabContentsSize(&tab_contents_size)) return FALSE; - gfx::CanvasPaint canvas(event, true); + gfx::CanvasSkiaPaint canvas(event, true); gfx::Rect area = GTK_WIDGET_NO_WINDOW(widget) ? gfx::Rect(widget->allocation) : diff --git a/chrome/browser/gtk/bookmark_utils_gtk.cc b/chrome/browser/gtk/bookmark_utils_gtk.cc index 4c4fb04..3b5c3b5 100644 --- a/chrome/browser/gtk/bookmark_utils_gtk.cc +++ b/chrome/browser/gtk/bookmark_utils_gtk.cc @@ -16,7 +16,7 @@ #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/profile.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/font.h" #include "gfx/gtk_util.h" @@ -135,7 +135,7 @@ gboolean OnDragIconExpose(GtkWidget* sender, cairo_destroy(cr); // Paint the title text. - gfx::CanvasPaint canvas(event, false); + gfx::CanvasSkiaPaint canvas(event, false); int text_x = gdk_pixbuf_get_width(data->favicon) + kBarButtonPadding; int text_width = sender->allocation.width - text_x; ResourceBundle& rb = ResourceBundle::GetSharedInstance(); diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc index 2e023b2..f19c720 100644 --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc @@ -30,7 +30,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/gtk_util.h" #include "grit/app_resources.h" @@ -278,7 +278,7 @@ class BrowserActionButton : public NotificationObserver, if (action->GetBadgeText(tab_id).empty()) return FALSE; - gfx::CanvasPaint canvas(event, false); + gfx::CanvasSkiaPaint canvas(event, false); gfx::Rect bounding_rect(widget->allocation); action->PaintBadge(&canvas, bounding_rect, tab_id); return FALSE; diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index a3cd9cd..6653b22 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -48,7 +48,7 @@ #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/gtk_util.h" #include "gfx/skbitmap_operations.h" #include "grit/chromium_strings.h" @@ -799,7 +799,7 @@ gboolean BrowserToolbarGtk::OnAppMenuImageExpose(GtkWidget* sender, } // Draw the chrome app menu icon onto the canvas. - gfx::CanvasPaint canvas(expose, false); + gfx::CanvasSkiaPaint canvas(expose, false); int x_offset = base::i18n::IsRTL() ? sender->allocation.width - kUpgradeDotOffset - badge.width() : kUpgradeDotOffset; diff --git a/chrome/browser/gtk/download_item_gtk.cc b/chrome/browser/gtk/download_item_gtk.cc index f64b30f..1a4c9b9 100644 --- a/chrome/browser/gtk/download_item_gtk.cc +++ b/chrome/browser/gtk/download_item_gtk.cc @@ -27,7 +27,7 @@ #include "chrome/browser/gtk/menu_gtk.h" #include "chrome/browser/gtk/nine_box.h" #include "chrome/common/notification_service.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/color_utils.h" #include "gfx/font.h" #include "gfx/skia_utils_gtk.h" @@ -789,7 +789,7 @@ void DownloadItemGtk::OnClick(GtkWidget* widget) { gboolean DownloadItemGtk::OnProgressAreaExpose(GtkWidget* widget, GdkEventExpose* event) { // Create a transparent canvas. - gfx::CanvasPaint canvas(event, false); + gfx::CanvasSkiaPaint canvas(event, false); if (complete_animation_.get()) { if (complete_animation_->is_animating()) { download_util::PaintDownloadComplete(&canvas, diff --git a/chrome/browser/gtk/location_bar_view_gtk.cc b/chrome/browser/gtk/location_bar_view_gtk.cc index 421bd46..3972ab6 100644 --- a/chrome/browser/gtk/location_bar_view_gtk.cc +++ b/chrome/browser/gtk/location_bar_view_gtk.cc @@ -49,7 +49,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/page_transition_types.h" #include "chrome/common/pref_names.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/font.h" #include "gfx/gtk_util.h" #include "grit/generated_resources.h" @@ -1395,7 +1395,7 @@ gboolean LocationBarViewGtk::PageActionViewGtk::OnExposeEvent( if (badge_text.empty()) return FALSE; - gfx::CanvasPaint canvas(event, false); + gfx::CanvasSkiaPaint canvas(event, false); gfx::Rect bounding_rect(widget->allocation); page_action_->PaintBadge(&canvas, bounding_rect, tab_id); return FALSE; diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc index 426ab43..52cb110 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.cc +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.cc @@ -18,7 +18,6 @@ #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" -#include "gfx/canvas_paint.h" #include "gfx/gtk_util.h" #include "third_party/skia/include/core/SkShader.h" diff --git a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc index df16d83..7ab29e6 100644 --- a/chrome/browser/gtk/tabs/tab_renderer_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_renderer_gtk.cc @@ -19,7 +19,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_service.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/favicon_size.h" #include "gfx/skbitmap_operations.h" #include "grit/app_resources.h" @@ -361,7 +361,7 @@ void TabRendererGtk::PaintFavIconArea(GdkEventExpose* event) { event->area.y = y() + favicon_bounds_.y(); event->area.width = favicon_bounds_.width(); event->area.height = favicon_bounds_.height(); - gfx::CanvasPaint canvas(event, false); + gfx::CanvasSkiaPaint canvas(event, false); // The actual paint methods expect 0, 0 to be the tab top left (see // PaintTab). @@ -767,7 +767,7 @@ SkBitmap* TabRendererGtk::GetMaskedBitmap(const SkBitmap* mask, } void TabRendererGtk::PaintTab(GdkEventExpose* event) { - gfx::CanvasPaint canvas(event, false); + gfx::CanvasSkiaPaint canvas(event, false); if (canvas.is_empty()) return; diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 9c4019e..a05105a 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -22,7 +22,6 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" -#include "gfx/canvas_paint.h" #include "gfx/gtk_util.h" #include "gfx/point.h" #include "grit/app_resources.h" diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index 5090b38..06292e5 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -31,6 +31,7 @@ #include "chrome/common/plugin_messages.h" #include "chrome/common/render_messages.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/gdi_util.h" #include "gfx/rect.h" #include "grit/webkit_resources.h" @@ -235,7 +236,7 @@ BOOL CALLBACK DetachPluginWindowsCallback(HWND window, LPARAM param) { void DrawDeemphasized(const gfx::Rect& paint_rect, HDC backing_store_dc, HDC paint_dc) { - gfx::Canvas canvas(paint_rect.width(), paint_rect.height(), true); + gfx::CanvasSkia canvas(paint_rect.width(), paint_rect.height(), true); HDC dc = canvas.beginPlatformPaint(); BitBlt(dc, 0, @@ -685,7 +686,7 @@ void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect, if (!paint_rect.Intersect(resize_corner_rect).IsEmpty()) { SkBitmap* bitmap = ResourceBundle::GetSharedInstance(). GetBitmapNamed(IDR_TEXTAREA_RESIZER); - gfx::Canvas canvas(bitmap->width(), bitmap->height(), false); + gfx::CanvasSkia canvas(bitmap->width(), bitmap->height(), false); canvas.getDevice()->accessBitmap(true).eraseARGB(0, 0, 0, 0); int x = resize_corner_rect.x() + resize_corner_rect.width() - bitmap->width(); @@ -999,9 +1000,9 @@ void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) { void RenderWidgetHostViewWin::DrawBackground(const RECT& dirty_rect, CPaintDC* dc) { if (!background_.empty()) { - gfx::Canvas canvas(dirty_rect.right - dirty_rect.left, - dirty_rect.bottom - dirty_rect.top, - true); // opaque + gfx::CanvasSkia canvas(dirty_rect.right - dirty_rect.left, + dirty_rect.bottom - dirty_rect.top, + true); // opaque canvas.TranslateInt(-dirty_rect.left, -dirty_rect.top); const RECT& dc_rect = dc->m_ps.rcPaint; diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc index 8f9334f2e..df9565c 100644 --- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc +++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc @@ -16,6 +16,7 @@ #include "chrome/browser/views/bubble_border.h" #include "chrome/browser/views/location_bar/location_bar_view.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/color_utils.h" #include "gfx/insets.h" #include "gfx/path.h" @@ -764,6 +765,7 @@ void AutocompletePopupContentsView::Paint(gfx::Canvas* canvas) { // Instead, we paint all our children into a second canvas and use that as a // shader to fill a path representing the round-rect clipping region. This // yields a nice anti-aliased edge. + // TODO(beng): Convert to CanvasSkia gfx::Canvas contents_canvas(width(), height(), true); contents_canvas.drawColor(GetColor(NORMAL, BACKGROUND)); View::PaintChildren(&contents_canvas); diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index 1723f9f..0b97017 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -38,6 +38,7 @@ #include "chrome/common/page_transition_types.h" #include "chrome/common/pref_names.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -1110,10 +1111,11 @@ void BookmarkBarView::WriteDragData(View* sender, for (int i = 0; i < GetBookmarkButtonCount(); ++i) { if (sender == GetBookmarkButton(i)) { views::TextButton* button = GetBookmarkButton(i); + // TODO(beng): convert to CanvasSkia gfx::Canvas canvas(button->width(), button->height(), false); button->Paint(&canvas, true); - drag_utils::SetDragImageOnDataObject(canvas, button->size(), press_pt, - data); + drag_utils::SetDragImageOnDataObject(canvas, button->size(), + press_pt, data); WriteDragData(model_->GetBookmarkBarNode()->GetChild(i), data); return; } diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 18eef4e..e472de6 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -31,6 +31,7 @@ #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "grit/app_resources.h" #include "grit/generated_resources.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -322,13 +323,15 @@ gfx::Canvas* BrowserActionView::GetIconWithBadge() { if (icon.isNull()) icon = button_->default_icon(); + // TODO(beng): Convert to CanvasSkia gfx::Canvas* canvas = new gfx::Canvas(icon.width(), icon.height(), false); canvas->DrawBitmapInt(icon, 0, 0); if (tab_id >= 0) { gfx::Rect bounds = gfx::Rect(icon.width(), icon.height() + kControlVertOffset); - button_->extension()->browser_action()->PaintBadge(canvas, bounds, tab_id); + button_->extension()->browser_action()->PaintBadge(canvas, + bounds, tab_id); } return canvas; diff --git a/chrome/browser/views/browser_actions_container.h b/chrome/browser/views/browser_actions_container.h index 1b7dbed..ce7ed70 100644 --- a/chrome/browser/views/browser_actions_container.h +++ b/chrome/browser/views/browser_actions_container.h @@ -34,6 +34,10 @@ class ExtensionPopup; class PrefService; class Profile; +namespace gfx { +class CanvasSkia; +} + namespace views { class Menu2; } diff --git a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc index 894f159..0b66c13 100644 --- a/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc +++ b/chrome/browser/views/extensions/browser_action_overflow_menu_controller.cc @@ -34,7 +34,7 @@ BrowserActionOverflowMenuController::BrowserActionOverflowMenuController( size_t command_id = 1; // Menu id 0 is reserved, start with 1. for (size_t i = start_index; i < views_->size(); ++i) { BrowserActionView* view = (*views_)[i]; - scoped_ptr canvas(view->GetIconWithBadge()); + scoped_ptr canvas(view->GetIconWithBadge()); menu_->AppendMenuItemWithIcon( command_id, UTF8ToWide(view->button()->extension()->name()), diff --git a/chrome/browser/views/infobars/extension_infobar.cc b/chrome/browser/views/infobars/extension_infobar.cc index 4f0f857..6a6be3f 100644 --- a/chrome/browser/views/infobars/extension_infobar.cc +++ b/chrome/browser/views/infobars/extension_infobar.cc @@ -13,7 +13,7 @@ #include "chrome/browser/views/frame/browser_view.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_resource.h" -#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "grit/theme_resources.h" #include "views/controls/button/menu_button.h" #include "views/controls/menu/menu_2.h" @@ -115,9 +115,10 @@ void ExtensionInfoBar::OnImageLoaded( SkBitmap* drop_image = rb.GetBitmapNamed(IDR_APP_DROPARROW); int image_size = Extension::EXTENSION_ICON_BITTY; - scoped_ptr canvas( - new gfx::Canvas(image_size + kDropArrowLeftMargin + drop_image->width(), - image_size, false)); + scoped_ptr canvas( + new gfx::CanvasSkia( + image_size + kDropArrowLeftMargin + drop_image->width(), + image_size, false)); canvas->DrawBitmapInt(*icon, 0, 0, icon->width(), icon->height(), 0, 0, image_size, image_size, diff --git a/chrome/browser/views/sad_tab_view.cc b/chrome/browser/views/sad_tab_view.cc index 0e626d6..fbaa37d5 100644 --- a/chrome/browser/views/sad_tab_view.cc +++ b/chrome/browser/views/sad_tab_view.cc @@ -8,6 +8,7 @@ #include "app/resource_bundle.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/size.h" #include "gfx/skia_util.h" #include "grit/generated_resources.h" @@ -89,7 +90,7 @@ void SadTabView::Layout() { int title_height = title_font_->height(); title_bounds_.SetRect(title_x, title_y, title_width_, title_height); - gfx::Canvas cc(0, 0, true); + gfx::CanvasSkia cc(0, 0, true); int message_width = static_cast(width() * kMessageSize); int message_height = 0; cc.SizeStringInt(message_, *message_font_, &message_width, &message_height, diff --git a/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc index 55f2a32..b3e8194d 100644 --- a/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/views/tab_contents/tab_contents_view_gtk.cc @@ -21,7 +21,7 @@ #include "chrome/browser/tab_contents/web_drag_dest_gtk.h" #include "chrome/browser/views/sad_tab_view.h" #include "chrome/browser/views/tab_contents/render_view_context_menu_views.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/point.h" #include "gfx/rect.h" #include "gfx/size.h" @@ -388,7 +388,7 @@ gboolean TabContentsViewGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) { gfx::Rect bounds; GetBounds(&bounds, true); sad_tab_->SetBounds(gfx::Rect(0, 0, bounds.width(), bounds.height())); - gfx::CanvasPaint canvas(event); + gfx::CanvasSkiaPaint canvas(event); sad_tab_->ProcessPaint(&canvas); } return false; // False indicates other widgets should get the event as well. diff --git a/chrome/browser/views/tab_contents/tab_contents_view_win.cc b/chrome/browser/views/tab_contents/tab_contents_view_win.cc index 39190f0..0774fea 100644 --- a/chrome/browser/views/tab_contents/tab_contents_view_win.cc +++ b/chrome/browser/views/tab_contents/tab_contents_view_win.cc @@ -25,7 +25,7 @@ #include "chrome/browser/views/sad_tab_view.h" #include "chrome/browser/views/tab_contents/render_view_context_menu_views.h" #include "chrome/browser/views/tab_contents/tab_contents_drag_win.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "views/focus/view_storage.h" #include "views/screen.h" #include "views/widget/root_view.h" @@ -392,7 +392,7 @@ void TabContentsViewWin::OnPaint(HDC junk_dc) { CRect cr; GetClientRect(&cr); sad_tab_->SetBounds(gfx::Rect(cr)); - gfx::CanvasPaint canvas(GetNativeView(), true); + gfx::CanvasSkiaPaint canvas(GetNativeView(), true); sad_tab_->ProcessPaint(&canvas); return; } diff --git a/chrome/browser/views/tabs/dragged_tab_view.cc b/chrome/browser/views/tabs/dragged_tab_view.cc index f3148c6..e5c55a4 100644 --- a/chrome/browser/views/tabs/dragged_tab_view.cc +++ b/chrome/browser/views/tabs/dragged_tab_view.cc @@ -6,6 +6,7 @@ #include "chrome/browser/views/tabs/native_view_photobooth.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "third_party/skia/include/core/SkShader.h" #include "views/widget/widget.h" @@ -185,6 +186,7 @@ void DraggedTabView::PaintAttachedTab(gfx::Canvas* canvas) { void DraggedTabView::PaintDetachedView(gfx::Canvas* canvas) { gfx::Size ps = GetPreferredSize(); + // TODO(beng): Convert to CanvasSkia gfx::Canvas scale_canvas(ps.width(), ps.height(), false); SkBitmap& bitmap_device = const_cast( scale_canvas.getTopPlatformDevice().accessBitmap(true)); diff --git a/chrome/browser/views/tabs/tab.cc b/chrome/browser/views/tabs/tab.cc index e4785be..afb7f6a 100644 --- a/chrome/browser/views/tabs/tab.cc +++ b/chrome/browser/views/tabs/tab.cc @@ -14,6 +14,7 @@ #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/defaults.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/favicon_size.h" #include "gfx/font.h" #include "gfx/path.h" @@ -398,7 +399,7 @@ void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { SkBitmap background_image = background_canvas.ExtractBitmap(); // Draw a radial gradient to hover_canvas. - gfx::Canvas hover_canvas(width(), height(), false); + gfx::CanvasSkia hover_canvas(width(), height(), false); int radius = kMiniTitleChangeGradientRadius; int x0 = width() + radius - kMiniTitleChangeInitialXOffset; int x1 = radius; diff --git a/chrome/browser/views/theme_helpers.cc b/chrome/browser/views/theme_helpers.cc index 82de958..41f6db5 100644 --- a/chrome/browser/views/theme_helpers.cc +++ b/chrome/browser/views/theme_helpers.cc @@ -9,7 +9,7 @@ #include #include "base/logging.h" -#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "skia/ext/bitmap_platform_device_win.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -23,7 +23,7 @@ void GetRebarGradientColors(int width, int x1, int x2, // those so calling code can use them to create gradient brushes for use in // rendering in other directions. - gfx::Canvas canvas(width, 1, true); + gfx::CanvasSkia canvas(width, 1, true); // Render the Rebar gradient into the DIB CTheme theme; diff --git a/chrome/browser/views/toolbar_view.cc b/chrome/browser/views/toolbar_view.cc index 3175922..c16908c 100644 --- a/chrome/browser/views/toolbar_view.cc +++ b/chrome/browser/views/toolbar_view.cc @@ -25,6 +25,7 @@ #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "gfx/skbitmap_operations.h" @@ -682,8 +683,8 @@ SkBitmap ToolbarView::GetAppMenuIcon() { return icon; // Draw the chrome app menu icon onto the canvas. - scoped_ptr canvas( - new gfx::Canvas(icon.width(), icon.height(), false)); + scoped_ptr canvas( + new gfx::CanvasSkia(icon.width(), icon.height(), false)); canvas->DrawBitmapInt(icon, 0, 0); SkBitmap badge; diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 8b4068c..9fa30d1 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -30,7 +30,7 @@ #include "chrome/renderer/render_thread.h" #include "chrome/renderer/render_view.h" #include "gfx/blit.h" -#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/native_widget_types.h" #include "gfx/size.h" #include "grit/generated_resources.h" @@ -1282,7 +1282,7 @@ void WebPluginDelegateProxy::PaintSadPlugin(WebKit::WebCanvas* native_context, // Make a temporary canvas for the background image. const int width = plugin_rect_.width(); const int height = plugin_rect_.height(); - gfx::Canvas canvas(width, height, false); + gfx::CanvasSkia canvas(width, height, false); #if defined(OS_MACOSX) // Flip the canvas, since the context expects flipped data. canvas.translate(0, height); diff --git a/gfx/canvas.cc b/gfx/canvas.cc deleted file mode 100644 index 28bc231..0000000 --- a/gfx/canvas.cc +++ /dev/null @@ -1,325 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gfx/canvas.h" - -#include - -#include "base/i18n/rtl.h" -#include "base/logging.h" -#include "gfx/font.h" -#include "gfx/rect.h" -#include "third_party/skia/include/core/SkShader.h" - -#if defined(OS_WIN) -#include "gfx/canvas_paint.h" -#endif - -namespace gfx { - -bool Canvas::GetClipRect(gfx::Rect* r) { - SkRect clip; - if (!getClipBounds(&clip)) { - if (r) - r->SetRect(0, 0, 0, 0); - return false; - } - r->SetRect(SkScalarRound(clip.fLeft), SkScalarRound(clip.fTop), - SkScalarRound(clip.fRight - clip.fLeft), - SkScalarRound(clip.fBottom - clip.fTop)); - return true; -} - -bool Canvas::ClipRectInt(int x, int y, int w, int h) { - SkRect new_clip; - new_clip.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + w), SkIntToScalar(y + h)); - return clipRect(new_clip); -} - -bool Canvas::IntersectsClipRectInt(int x, int y, int w, int h) { - SkRect clip; - return getClipBounds(&clip) && - clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), - SkIntToScalar(y + h)); -} - -void Canvas::TranslateInt(int x, int y) { - translate(SkIntToScalar(x), SkIntToScalar(y)); -} - -void Canvas::ScaleInt(int x, int y) { - scale(SkIntToScalar(x), SkIntToScalar(y)); -} - -void Canvas::FillRectInt(const SkColor& color, int x, int y, int w, int h) { - SkPaint paint; - paint.setColor(color); - paint.setStyle(SkPaint::kFill_Style); - paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); - FillRectInt(x, y, w, h, paint); -} - -void Canvas::FillRectInt(int x, int y, int w, int h, const SkPaint& paint) { - SkIRect rc = {x, y, x + w, y + h}; - drawIRect(rc, paint); -} - -void Canvas::DrawRectInt(const SkColor& color, int x, int y, int w, int h) { - DrawRectInt(color, x, y, w, h, SkXfermode::kSrcOver_Mode); -} - -void Canvas::DrawRectInt(const SkColor& color, int x, int y, int w, int h, - SkXfermode::Mode mode) { - SkPaint paint; - paint.setColor(color); - paint.setStyle(SkPaint::kStroke_Style); - // Set a stroke width of 0, which will put us down the stroke rect path. If - // we set a stroke width of 1, for example, this will internally create a - // path and fill it, which causes problems near the edge of the canvas. - paint.setStrokeWidth(SkIntToScalar(0)); - paint.setXfermodeMode(mode); - - SkIRect rc = {x, y, x + w, y + h}; - drawIRect(rc, paint); -} - -void Canvas::DrawLineInt(const SkColor& color, int x1, int y1, int x2, int y2) { - SkPaint paint; - paint.setColor(color); - paint.setStrokeWidth(SkIntToScalar(1)); - drawLine(SkIntToScalar(x1), SkIntToScalar(y1), SkIntToScalar(x2), - SkIntToScalar(y2), paint); -} - -void Canvas::DrawFocusRect(int x, int y, int width, int height) { - // Create a 2D bitmap containing alternating on/off pixels - we do this - // so that you never get two pixels of the same color around the edges - // of the focus rect (this may mean that opposing edges of the rect may - // have a dot pattern out of phase to each other). - static SkBitmap* dots = NULL; - if (!dots) { - int col_pixels = 32; - int row_pixels = 32; - - dots = new SkBitmap; - dots->setConfig(SkBitmap::kARGB_8888_Config, col_pixels, row_pixels); - dots->allocPixels(); - dots->eraseARGB(0, 0, 0, 0); - - uint32_t* dot = dots->getAddr32(0, 0); - for (int i = 0; i < row_pixels; i++) { - for (int u = 0; u < col_pixels; u++) { - if ((u % 2 + i % 2) % 2 != 0) { - dot[i * row_pixels + u] = SK_ColorGRAY; - } - } - } - } - - // First the horizontal lines. - - // Make a shader for the bitmap with an origin of the box we'll draw. This - // shader is refcounted and will have an initial refcount of 1. - SkShader* shader = SkShader::CreateBitmapShader( - *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); - // Assign the shader to the paint & release our reference. The paint will - // now own the shader and the shader will be destroyed when the paint goes - // out of scope. - SkPaint paint; - paint.setShader(shader); - shader->unref(); - - SkRect rect; - rect.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + width), SkIntToScalar(y + 1)); - drawRect(rect, paint); - rect.set(SkIntToScalar(x), SkIntToScalar(y + height - 1), - SkIntToScalar(x + width), SkIntToScalar(y + height)); - drawRect(rect, paint); - - rect.set(SkIntToScalar(x), SkIntToScalar(y), - SkIntToScalar(x + 1), SkIntToScalar(y + height)); - drawRect(rect, paint); - rect.set(SkIntToScalar(x + width - 1), SkIntToScalar(y), - SkIntToScalar(x + width), SkIntToScalar(y + height)); - drawRect(rect, paint); -} - -void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { - drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y)); -} - -void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint) { - drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint); -} - -void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, - int src_w, int src_h, int dest_x, int dest_y, - int dest_w, int dest_h, - bool filter) { - SkPaint p; - DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y, - dest_w, dest_h, filter, p); -} - -void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, - int src_w, int src_h, int dest_x, int dest_y, - int dest_w, int dest_h, - bool filter, const SkPaint& paint) { - DLOG_ASSERT(src_x + src_w < std::numeric_limits::max() && - src_y + src_h < std::numeric_limits::max()); - if (src_w <= 0 || src_h <= 0 || dest_w <= 0 || dest_h <= 0) { - NOTREACHED() << "Attempting to draw bitmap to/from an empty rect!"; - return; - } - - if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) - return; - - SkRect dest_rect = { SkIntToScalar(dest_x), - SkIntToScalar(dest_y), - SkIntToScalar(dest_x + dest_w), - SkIntToScalar(dest_y + dest_h) }; - - if (src_w == dest_w && src_h == dest_h) { - // Workaround for apparent bug in Skia that causes image to occasionally - // shift. - SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; - drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); - return; - } - - // Make a bitmap shader that contains the bitmap we want to draw. This is - // basically what SkCanvas.drawBitmap does internally, but it gives us - // more control over quality and will use the mipmap in the source image if - // it has one, whereas drawBitmap won't. - SkShader* shader = SkShader::CreateBitmapShader(bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode); - SkMatrix shader_scale; - shader_scale.setScale(SkFloatToScalar(static_cast(dest_w) / src_w), - SkFloatToScalar(static_cast(dest_h) / src_h)); - shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); - shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); - shader->setLocalMatrix(shader_scale); - - // Set up our paint to use the shader & release our reference (now just owned - // by the paint). - SkPaint p(paint); - p.setFilterBitmap(filter); - p.setShader(shader); - shader->unref(); - - // The rect will be filled by the bitmap. - drawRect(dest_rect, p); -} - -void Canvas::DrawStringInt(const std::wstring& text, - const gfx::Font& font, - const SkColor& color, - int x, int y, int w, int h) { - DrawStringInt(text, font, color, x, y, w, h, - gfx::Canvas::DefaultCanvasTextAlignment()); -} - -void Canvas::DrawStringInt(const std::wstring& text, - const gfx::Font& font, - const SkColor& color, - const gfx::Rect& display_rect) { - DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), - display_rect.width(), display_rect.height()); -} - -void Canvas::TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h) { - TileImageInt(bitmap, 0, 0, x, y, w, h); -} - -void Canvas::TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, - int dest_x, int dest_y, int w, int h) { - if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) - return; - - SkPaint paint; - - SkShader* shader = SkShader::CreateBitmapShader(bitmap, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode); - paint.setShader(shader); - paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); - - // CreateBitmapShader returns a Shader with a reference count of one, we - // need to unref after paint takes ownership of the shader. - shader->unref(); - save(); - translate(SkIntToScalar(dest_x - src_x), SkIntToScalar(dest_y - src_y)); - ClipRectInt(src_x, src_y, w, h); - drawPaint(paint); - restore(); -} - -SkBitmap Canvas::ExtractBitmap() const { - const SkBitmap& device_bitmap = getDevice()->accessBitmap(false); - - // Make a bitmap to return, and a canvas to draw into it. We don't just want - // to call extractSubset or the copy constuctor, since we want an actual copy - // of the bitmap. - SkBitmap result; - device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); - return result; -} - -Canvas* Canvas::AsCanvas() { - return this; -} - -// static -int Canvas::DefaultCanvasTextAlignment() { - if (!base::i18n::IsRTL()) - return gfx::Canvas::TEXT_ALIGN_LEFT; - return gfx::Canvas::TEXT_ALIGN_RIGHT; -} - -//////////////////////////////////////////////////////////////////////////////// -// Canvas2, public: - -Canvas2* Canvas2::CreateCanvas() { - return new Canvas; -} - -Canvas2* Canvas2::CreateCanvas(int width, int height, bool is_opaque) { - return new Canvas(width, height, is_opaque); -} - -#if defined(OS_WIN) -// TODO(beng): move to canvas_win.cc, etc. -class CanvasPaintWin : public CanvasPaint, public CanvasPaint2 { - public: - CanvasPaintWin(gfx::NativeView view) : CanvasPaint(view) {} - - // Overridden from CanvasPaint2: - virtual bool IsValid() const { - return isEmpty(); - } - - virtual gfx::Rect GetInvalidRect() const { - return gfx::Rect(paintStruct().rcPaint); - } - - virtual Canvas2* AsCanvas2() { - return this; - } -}; -#endif - -CanvasPaint2* CanvasPaint2::CreateCanvasPaint(gfx::NativeView view) { -#if defined(OS_WIN) - return new CanvasPaintWin(view); -#else - return NULL; -#endif -} - -} // namespace gfx diff --git a/gfx/canvas.h b/gfx/canvas.h index 53661db..589d77d 100644 --- a/gfx/canvas.h +++ b/gfx/canvas.h @@ -5,129 +5,27 @@ #ifndef GFX_CANVAS_H_ #define GFX_CANVAS_H_ -#include "base/basictypes.h" -#include "gfx/canvas_2.h" -#include "skia/ext/platform_canvas.h" - -#if defined(OS_POSIX) && !defined(OS_MACOSX) -typedef struct _GdkPixbuf GdkPixbuf; -#endif +#include "gfx/canvas_skia.h" namespace gfx { -// Canvas is a SkCanvas subclass that provides a number of methods for common -// operations used throughout an application built using base/gfx and app/gfx. -// -// All methods that take integer arguments (as is used throughout views) -// end with Int. If you need to use methods provided by the superclass -// you'll need to do a conversion. In particular you'll need to use -// macro SkIntToScalar(xxx), or if converting from a scalar to an integer -// SkScalarRound. -// -// A handful of methods in this class are overloaded providing an additional -// argument of type SkXfermode::Mode. SkXfermode::Mode specifies how the -// source and destination colors are combined. Unless otherwise specified, -// the variant that does not take a SkXfermode::Mode uses a transfer mode -// of kSrcOver_Mode. -class Canvas : public skia::PlatformCanvas, - public Canvas2 { +// Temporary compatibility shim, remove once Canvas2->Canvas. +class Canvas : public CanvasSkia { public: - // Creates an empty Canvas. Callers must use initialize before using the - // canvas. - Canvas(); - - Canvas(int width, int height, bool is_opaque); - - virtual ~Canvas(); - - // Compute the size required to draw some text with the provided font. - // Attempts to fit the text with the provided width and height. Increases - // height and then width as needed to make the text fit. This method - // supports multiple lines. - static void SizeStringInt(const std::wstring& text, const gfx::Font& font, - int* width, int* height, int flags); - - // Returns the default text alignment to be used when drawing text on a - // gfx::Canvas based on the directionality of the system locale language. This - // function is used by gfx::Canvas::DrawStringInt when the text alignment is - // not specified. - // - // This function returns either gfx::Canvas::TEXT_ALIGN_LEFT or - // gfx::Canvas::TEXT_ALIGN_RIGHT. - static int DefaultCanvasTextAlignment(); - -#if defined(OS_POSIX) && !defined(OS_MACOSX) - // Draw the pixbuf in its natural size at (x, y). - 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. - void 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); -#endif + Canvas(int width, int height, bool is_opaque) + : CanvasSkia(width, height, is_opaque) { + } + Canvas() : CanvasSkia() {} // Overridden from Canvas2: - virtual bool GetClipRect(gfx::Rect* clip_rect); - virtual bool ClipRectInt(int x, int y, int w, int h); - virtual bool IntersectsClipRectInt(int x, int y, int w, int h); - virtual void TranslateInt(int x, int y); - virtual void ScaleInt(int x, int y); - virtual void FillRectInt(int x, int y, int w, int h, - const SkPaint& paint); - virtual void FillRectInt(const SkColor& color, int x, int y, int w, - int h); - virtual void DrawRectInt(const SkColor& color, int x, int y, int w, - int h); - virtual void DrawRectInt(const SkColor& color, int x, int y, int w, int h, - SkXfermode::Mode mode); - virtual void DrawLineInt(const SkColor& color, int x1, int y1, int x2, - int y2); - virtual void DrawBitmapInt(const SkBitmap& bitmap, int x, int y); - virtual void DrawBitmapInt(const SkBitmap& bitmap, int x, int y, - const SkPaint& paint); - virtual void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, - int src_w, int src_h, int dest_x, int dest_y, - int dest_w, int dest_h, bool filter); - virtual void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, - int src_w, int src_h, int dest_x, int dest_y, - int dest_w, int dest_h, bool filter, - const SkPaint& paint); - virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, - const SkColor& color, int x, int y, int w, - int h); - virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, - const SkColor& color, - const gfx::Rect& display_rect); - virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, - const SkColor& color, int x, int y, int w, int h, - int flags); - virtual void DrawFocusRect(int x, int y, int width, int height); - virtual void TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h); - virtual void TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, - int dest_x, int dest_y, int w, int h); - virtual SkBitmap ExtractBitmap() const; - virtual Canvas* AsCanvas(); + Canvas* AsCanvas() { + return this; + } private: -#if defined(OS_WIN) - // Draws text with the specified color, font and location. The text is - // aligned to the left, vertically centered, clipped to the region. If the - // text is too big, it is truncated and '...' is added to the end. - void DrawStringInt(const std::wstring& text, HFONT font, - const SkColor& color, int x, int y, int w, int h, - int flags); -#endif - DISALLOW_COPY_AND_ASSIGN(Canvas); }; -} // namespace gfx; +} #endif // GFX_CANVAS_H_ diff --git a/gfx/canvas_linux.cc b/gfx/canvas_linux.cc deleted file mode 100644 index 3f658d4..0000000 --- a/gfx/canvas_linux.cc +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gfx/canvas.h" - -#include -#include -#include -#include - -#include "base/logging.h" -#include "base/utf_string_conversions.h" -#include "gfx/font.h" -#include "gfx/gtk_util.h" -#include "gfx/rect.h" - -namespace { - -const gunichar kAcceleratorChar = '&'; - -// Font settings that we initialize once and then use when drawing text in -// DrawStringInt(). -static cairo_font_options_t* cairo_font_options = NULL; - -// Update |cairo_font_options| based on GtkSettings, allocating it if needed. -static void UpdateCairoFontOptions() { - if (!cairo_font_options) - cairo_font_options = cairo_font_options_create(); - - GtkSettings* gtk_settings = gtk_settings_get_default(); - gint antialias = 0; - gint hinting = 0; - gchar* hint_style = NULL; - gchar* rgba_style = NULL; - g_object_get(gtk_settings, - "gtk-xft-antialias", &antialias, - "gtk-xft-hinting", &hinting, - "gtk-xft-hintstyle", &hint_style, - "gtk-xft-rgba", &rgba_style, - NULL); - - // g_object_get() doesn't tell us whether the properties were present or not, - // but if they aren't (because gnome-settings-daemon isn't running), we'll get - // NULL values for the strings. - if (hint_style && rgba_style) { - if (!antialias) { - cairo_font_options_set_antialias(cairo_font_options, - CAIRO_ANTIALIAS_NONE); - } else if (strcmp(rgba_style, "none") == 0) { - cairo_font_options_set_antialias(cairo_font_options, - CAIRO_ANTIALIAS_GRAY); - } else { - cairo_font_options_set_antialias(cairo_font_options, - CAIRO_ANTIALIAS_SUBPIXEL); - cairo_subpixel_order_t cairo_subpixel_order = - CAIRO_SUBPIXEL_ORDER_DEFAULT; - if (strcmp(rgba_style, "rgb") == 0) { - cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; - } else if (strcmp(rgba_style, "bgr") == 0) { - cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; - } else if (strcmp(rgba_style, "vrgb") == 0) { - cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; - } else if (strcmp(rgba_style, "vbgr") == 0) { - cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; - } - cairo_font_options_set_subpixel_order(cairo_font_options, - cairo_subpixel_order); - } - - cairo_hint_style_t cairo_hint_style = CAIRO_HINT_STYLE_DEFAULT; - if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) { - cairo_hint_style = CAIRO_HINT_STYLE_NONE; - } else if (strcmp(hint_style, "hintslight") == 0) { - cairo_hint_style = CAIRO_HINT_STYLE_SLIGHT; - } else if (strcmp(hint_style, "hintmedium") == 0) { - cairo_hint_style = CAIRO_HINT_STYLE_MEDIUM; - } else if (strcmp(hint_style, "hintfull") == 0) { - cairo_hint_style = CAIRO_HINT_STYLE_FULL; - } - cairo_font_options_set_hint_style(cairo_font_options, cairo_hint_style); - } - - if (hint_style) - g_free(hint_style); - if (rgba_style) - g_free(rgba_style); -} - -} // namespace - -namespace gfx { - -Canvas::Canvas(int width, int height, bool is_opaque) - : skia::PlatformCanvas(width, height, is_opaque) { -} - -Canvas::Canvas() : skia::PlatformCanvas() { -} - -Canvas::~Canvas() { -} - -// Pass a width > 0 to force wrapping and elliding. -static void SetupPangoLayout(PangoLayout* layout, - const std::wstring& text, - const gfx::Font& font, - int width, - int flags) { - if (!cairo_font_options) - UpdateCairoFontOptions(); - // This needs to be done early on; it has no effect when called just before - // pango_cairo_show_layout(). - pango_cairo_context_set_font_options( - pango_layout_get_context(layout), cairo_font_options); - - // Callers of DrawStringInt handle RTL layout themselves, so tell pango to not - // scope out RTL characters. - pango_layout_set_auto_dir(layout, FALSE); - - if (width > 0) - pango_layout_set_width(layout, width * PANGO_SCALE); - - if (flags & 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) { - pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); - } else if (flags & Canvas::TEXT_ALIGN_RIGHT) { - pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); - } - - if (flags & Canvas::MULTI_LINE) { - pango_layout_set_wrap(layout, - (flags & Canvas::CHARACTER_BREAK) ? - PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD); - } - - // Set the resolution to match that used by Gtk. If we don't set the - // resolution and the resolution differs from the default, Gtk and Chrome end - // up drawing at different sizes. - double resolution = gfx::GetPangoResolution(); - if (resolution > 0) { - pango_cairo_context_set_resolution(pango_layout_get_context(layout), - resolution); - } - - PangoFontDescription* desc = gfx::Font::PangoFontFromGfxFont(font); - pango_layout_set_font_description(layout, desc); - pango_font_description_free(desc); - - // Set text and accelerator character if needed. - std::string utf8 = WideToUTF8(text); - if (flags & gfx::Canvas::HIDE_PREFIX) { - // Escape the text string to be used as markup. - gchar* escaped_text = g_markup_escape_text(utf8.c_str(), utf8.size()); - pango_layout_set_markup_with_accel(layout, - escaped_text, - strlen(escaped_text), - kAcceleratorChar, NULL); - g_free(escaped_text); - } else { - pango_layout_set_text(layout, utf8.data(), utf8.size()); - } -} - -// static -void Canvas::SizeStringInt(const std::wstring& text, - const gfx::Font& font, - int* width, int* height, int flags) { - int org_width = *width; - cairo_surface_t* surface = - cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); - cairo_t* cr = cairo_create(surface); - PangoLayout* layout = pango_cairo_create_layout(cr); - - SetupPangoLayout(layout, text, font, *width, flags); - - pango_layout_get_pixel_size(layout, width, height); - - 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 - // such that the width returned from pango_layout_get_pixel_size is too - // small. Using the width from pango_layout_get_pixel_size in this case - // results in wrapping across more lines, which requires a bigger height. - // As a workaround we use the original width, which is not necessarily - // exactly correct, but isn't wrong by much. - // - // It looks like Pango uses the size of whitespace in calculating wrapping - // but doesn't include the size of the whitespace when the extents are - // asked for. See the loop in pango-layout.c process_item that determines - // where to wrap. - *width = org_width; - } - - g_object_unref(layout); - cairo_destroy(cr); - cairo_surface_destroy(surface); -} - -void Canvas::DrawStringInt(const std::wstring& text, - const gfx::Font& font, - const SkColor& color, - int x, int y, int w, int h, - int flags) { - 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.style() & gfx::Font::UNDERLINED) { - double underline_y = - static_cast(y) + height + font.underline_position(); - cairo_set_line_width(cr, 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. -} - -void Canvas::DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y) { - if (!pixbuf) { - NOTREACHED(); - return; - } - - cairo_t* cr = beginPlatformPaint(); - gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y); - cairo_paint(cr); -} - -} // namespace gfx diff --git a/gfx/canvas_mac.mm b/gfx/canvas_mac.mm deleted file mode 100644 index 87ff09b..0000000 --- a/gfx/canvas_mac.mm +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import - -#include "gfx/canvas.h" - -#include "base/scoped_cftyperef.h" -#include "base/sys_string_conversions.h" -#include "gfx/font.h" -#include "gfx/rect.h" -#include "third_party/skia/include/core/SkShader.h" - -namespace gfx { - -Canvas::Canvas(int width, int height, bool is_opaque) - : skia::PlatformCanvas(width, height, is_opaque) { -} - -Canvas::Canvas() : skia::PlatformCanvas() { -} - -Canvas::~Canvas() { -} - -// static -void Canvas::SizeStringInt(const std::wstring& text, - const gfx::Font& font, - int *width, int *height, int flags) { - NSFont* native_font = font.nativeFont(); - NSString* ns_string = base::SysWideToNSString(text); - NSDictionary* attributes = - [NSDictionary dictionaryWithObject:native_font - forKey:NSFontAttributeName]; - NSSize string_size = [ns_string sizeWithAttributes:attributes]; - *width = string_size.width; - *height = font.height(); -} - -void Canvas::DrawStringInt(const std::wstring& text, const gfx::Font& font, - const SkColor& color, int x, int y, int w, int h, - int flags) { - if (!IntersectsClipRectInt(x, y, w, h)) - return; - - CGContextRef context = beginPlatformPaint(); - CGContextSaveGState(context); - - NSColor* ns_color = [NSColor colorWithDeviceRed:SkColorGetR(color) / 255.0 - green:SkColorGetG(color) / 255.0 - blue:SkColorGetB(color) / 255.0 - alpha:SkColorGetA(color) / 255.0]; - NSMutableParagraphStyle *ns_style = - [[[NSParagraphStyle alloc] init] autorelease]; - if (flags & TEXT_ALIGN_CENTER) - [ns_style setAlignment:NSCenterTextAlignment]; - // TODO(awalker): Implement the rest of the Canvas text flags - - NSDictionary* attributes = - [NSDictionary dictionaryWithObjectsAndKeys: - font.nativeFont(), NSFontAttributeName, - ns_color, NSForegroundColorAttributeName, - ns_style, NSParagraphStyleAttributeName, - nil]; - - NSAttributedString* ns_string = - [[[NSAttributedString alloc] initWithString:base::SysWideToNSString(text) - attributes:attributes] autorelease]; - scoped_cftyperef framesetter( - CTFramesetterCreateWithAttributedString(reinterpret_cast(ns_string))); - - CGRect text_bounds = CGRectMake(x, y, w, h); - CGMutablePathRef path = CGPathCreateMutable(); - CGPathAddRect(path, NULL, text_bounds); - - scoped_cftyperef frame( - CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL)); - CTFrameDraw(frame, context); - CGContextRestoreGState(context); - endPlatformPaint(); -} - -} // namespace gfx diff --git a/gfx/canvas_paint.h b/gfx/canvas_paint.h deleted file mode 100644 index a11a693..0000000 --- a/gfx/canvas_paint.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GFX_CANVAS_PAINT_H_ -#define GFX_CANVAS_PAINT_H_ - -#include "gfx/canvas.h" -#include "skia/ext/canvas_paint.h" - -// Define a skia::CanvasPaint type that wraps our gfx::Canvas like the -// skia::PlatformCanvasPaint wraps PlatformCanvas. - -namespace gfx { - -typedef skia::CanvasPaintT CanvasPaint; - -} // namespace gfx - -#endif // GFX_CANVAS_PAINT_H_ diff --git a/gfx/canvas_skia.cc b/gfx/canvas_skia.cc new file mode 100644 index 0000000..8fa763a --- /dev/null +++ b/gfx/canvas_skia.cc @@ -0,0 +1,324 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gfx/canvas.h" + +#include + +#include "base/i18n/rtl.h" +#include "base/logging.h" +#include "gfx/canvas.h" +#include "gfx/font.h" +#include "gfx/rect.h" +#include "third_party/skia/include/core/SkShader.h" + +#if defined(OS_WIN) +#include "gfx/canvas_skia_paint.h" +#endif + +namespace gfx { + +bool CanvasSkia::GetClipRect(gfx::Rect* r) { + SkRect clip; + if (!getClipBounds(&clip)) { + if (r) + r->SetRect(0, 0, 0, 0); + return false; + } + r->SetRect(SkScalarRound(clip.fLeft), SkScalarRound(clip.fTop), + SkScalarRound(clip.fRight - clip.fLeft), + SkScalarRound(clip.fBottom - clip.fTop)); + return true; +} + +bool CanvasSkia::ClipRectInt(int x, int y, int w, int h) { + SkRect new_clip; + new_clip.set(SkIntToScalar(x), SkIntToScalar(y), + SkIntToScalar(x + w), SkIntToScalar(y + h)); + return clipRect(new_clip); +} + +bool CanvasSkia::IntersectsClipRectInt(int x, int y, int w, int h) { + SkRect clip; + return getClipBounds(&clip) && + clip.intersect(SkIntToScalar(x), SkIntToScalar(y), SkIntToScalar(x + w), + SkIntToScalar(y + h)); +} + +void CanvasSkia::TranslateInt(int x, int y) { + translate(SkIntToScalar(x), SkIntToScalar(y)); +} + +void CanvasSkia::ScaleInt(int x, int y) { + scale(SkIntToScalar(x), SkIntToScalar(y)); +} + +void CanvasSkia::FillRectInt(const SkColor& color, int x, int y, int w, int h) { + SkPaint paint; + paint.setColor(color); + paint.setStyle(SkPaint::kFill_Style); + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + FillRectInt(x, y, w, h, paint); +} + +void CanvasSkia::FillRectInt(int x, int y, int w, int h, const SkPaint& paint) { + SkIRect rc = {x, y, x + w, y + h}; + drawIRect(rc, paint); +} + +void CanvasSkia::DrawRectInt(const SkColor& color, int x, int y, int w, int h) { + DrawRectInt(color, x, y, w, h, SkXfermode::kSrcOver_Mode); +} + +void CanvasSkia::DrawRectInt(const SkColor& color, int x, int y, int w, int h, + SkXfermode::Mode mode) { + SkPaint paint; + paint.setColor(color); + paint.setStyle(SkPaint::kStroke_Style); + // Set a stroke width of 0, which will put us down the stroke rect path. If + // we set a stroke width of 1, for example, this will internally create a + // path and fill it, which causes problems near the edge of the canvas. + paint.setStrokeWidth(SkIntToScalar(0)); + paint.setXfermodeMode(mode); + + SkIRect rc = {x, y, x + w, y + h}; + drawIRect(rc, paint); +} + +void CanvasSkia::DrawLineInt(const SkColor& color, int x1, int y1, int x2, + int y2) { + SkPaint paint; + paint.setColor(color); + paint.setStrokeWidth(SkIntToScalar(1)); + drawLine(SkIntToScalar(x1), SkIntToScalar(y1), SkIntToScalar(x2), + SkIntToScalar(y2), paint); +} + +void CanvasSkia::DrawFocusRect(int x, int y, int width, int height) { + // Create a 2D bitmap containing alternating on/off pixels - we do this + // so that you never get two pixels of the same color around the edges + // of the focus rect (this may mean that opposing edges of the rect may + // have a dot pattern out of phase to each other). + static SkBitmap* dots = NULL; + if (!dots) { + int col_pixels = 32; + int row_pixels = 32; + + dots = new SkBitmap; + dots->setConfig(SkBitmap::kARGB_8888_Config, col_pixels, row_pixels); + dots->allocPixels(); + dots->eraseARGB(0, 0, 0, 0); + + uint32_t* dot = dots->getAddr32(0, 0); + for (int i = 0; i < row_pixels; i++) { + for (int u = 0; u < col_pixels; u++) { + if ((u % 2 + i % 2) % 2 != 0) { + dot[i * row_pixels + u] = SK_ColorGRAY; + } + } + } + } + + // First the horizontal lines. + + // Make a shader for the bitmap with an origin of the box we'll draw. This + // shader is refcounted and will have an initial refcount of 1. + SkShader* shader = SkShader::CreateBitmapShader( + *dots, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); + // Assign the shader to the paint & release our reference. The paint will + // now own the shader and the shader will be destroyed when the paint goes + // out of scope. + SkPaint paint; + paint.setShader(shader); + shader->unref(); + + SkRect rect; + rect.set(SkIntToScalar(x), SkIntToScalar(y), + SkIntToScalar(x + width), SkIntToScalar(y + 1)); + drawRect(rect, paint); + rect.set(SkIntToScalar(x), SkIntToScalar(y + height - 1), + SkIntToScalar(x + width), SkIntToScalar(y + height)); + drawRect(rect, paint); + + rect.set(SkIntToScalar(x), SkIntToScalar(y), + SkIntToScalar(x + 1), SkIntToScalar(y + height)); + drawRect(rect, paint); + rect.set(SkIntToScalar(x + width - 1), SkIntToScalar(y), + SkIntToScalar(x + width), SkIntToScalar(y + height)); + drawRect(rect, paint); +} + +void CanvasSkia::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) { + drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y)); +} + +void CanvasSkia::DrawBitmapInt(const SkBitmap& bitmap, int x, int y, + const SkPaint& paint) { + drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint); +} + +void CanvasSkia::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, + bool filter) { + SkPaint p; + DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y, + dest_w, dest_h, filter, p); +} + +void CanvasSkia::DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, + bool filter, const SkPaint& paint) { + DLOG_ASSERT(src_x + src_w < std::numeric_limits::max() && + src_y + src_h < std::numeric_limits::max()); + if (src_w <= 0 || src_h <= 0 || dest_w <= 0 || dest_h <= 0) { + NOTREACHED() << "Attempting to draw bitmap to/from an empty rect!"; + return; + } + + if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h)) + return; + + SkRect dest_rect = { SkIntToScalar(dest_x), + SkIntToScalar(dest_y), + SkIntToScalar(dest_x + dest_w), + SkIntToScalar(dest_y + dest_h) }; + + if (src_w == dest_w && src_h == dest_h) { + // Workaround for apparent bug in Skia that causes image to occasionally + // shift. + SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h }; + drawBitmapRect(bitmap, &src_rect, dest_rect, &paint); + return; + } + + // Make a bitmap shader that contains the bitmap we want to draw. This is + // basically what SkCanvas.drawBitmap does internally, but it gives us + // more control over quality and will use the mipmap in the source image if + // it has one, whereas drawBitmap won't. + SkShader* shader = SkShader::CreateBitmapShader(bitmap, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + SkMatrix shader_scale; + shader_scale.setScale(SkFloatToScalar(static_cast(dest_w) / src_w), + SkFloatToScalar(static_cast(dest_h) / src_h)); + shader_scale.preTranslate(SkIntToScalar(-src_x), SkIntToScalar(-src_y)); + shader_scale.postTranslate(SkIntToScalar(dest_x), SkIntToScalar(dest_y)); + shader->setLocalMatrix(shader_scale); + + // Set up our paint to use the shader & release our reference (now just owned + // by the paint). + SkPaint p(paint); + p.setFilterBitmap(filter); + p.setShader(shader); + shader->unref(); + + // The rect will be filled by the bitmap. + drawRect(dest_rect, p); +} + +void CanvasSkia::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + int x, int y, int w, int h) { + DrawStringInt(text, font, color, x, y, w, h, + gfx::CanvasSkia::DefaultCanvasTextAlignment()); +} + +void CanvasSkia::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + const gfx::Rect& display_rect) { + DrawStringInt(text, font, color, display_rect.x(), display_rect.y(), + display_rect.width(), display_rect.height()); +} + +void CanvasSkia::TileImageInt(const SkBitmap& bitmap, int x, int y, int w, + int h) { + TileImageInt(bitmap, 0, 0, x, y, w, h); +} + +void CanvasSkia::TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, + int dest_x, int dest_y, int w, int h) { + if (!IntersectsClipRectInt(dest_x, dest_y, w, h)) + return; + + SkPaint paint; + + SkShader* shader = SkShader::CreateBitmapShader(bitmap, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + paint.setShader(shader); + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); + + // CreateBitmapShader returns a Shader with a reference count of one, we + // need to unref after paint takes ownership of the shader. + shader->unref(); + save(); + translate(SkIntToScalar(dest_x - src_x), SkIntToScalar(dest_y - src_y)); + ClipRectInt(src_x, src_y, w, h); + drawPaint(paint); + restore(); +} + +SkBitmap CanvasSkia::ExtractBitmap() const { + const SkBitmap& device_bitmap = getDevice()->accessBitmap(false); + + // Make a bitmap to return, and a canvas to draw into it. We don't just want + // to call extractSubset or the copy constuctor, since we want an actual copy + // of the bitmap. + SkBitmap result; + device_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config); + return result; +} + +// static +int CanvasSkia::DefaultCanvasTextAlignment() { + if (!base::i18n::IsRTL()) + return gfx::Canvas::TEXT_ALIGN_LEFT; + return gfx::Canvas::TEXT_ALIGN_RIGHT; +} + +//////////////////////////////////////////////////////////////////////////////// +// Canvas2, public: + +Canvas2* Canvas2::CreateCanvas() { + return new Canvas; +} + +Canvas2* Canvas2::CreateCanvas(int width, int height, bool is_opaque) { + return new Canvas(width, height, is_opaque); +} + +#if defined(OS_WIN) +// TODO(beng): move to canvas_win.cc, etc. +class CanvasPaintWin : public CanvasSkiaPaint, public CanvasPaint2 { + public: + CanvasPaintWin(gfx::NativeView view) : CanvasSkiaPaint(view) {} + + // Overridden from CanvasPaint2: + virtual bool IsValid() const { + return isEmpty(); + } + + virtual gfx::Rect GetInvalidRect() const { + return gfx::Rect(paintStruct().rcPaint); + } + + virtual Canvas2* AsCanvas2() { + return this; + } +}; +#endif + +CanvasPaint2* CanvasPaint2::CreateCanvasPaint(gfx::NativeView view) { +#if defined(OS_WIN) + return new CanvasPaintWin(view); +#else + return NULL; +#endif +} + +} // namespace gfx diff --git a/gfx/canvas_skia.h b/gfx/canvas_skia.h new file mode 100644 index 0000000..9a976fd --- /dev/null +++ b/gfx/canvas_skia.h @@ -0,0 +1,135 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GFX_CANVAS_SKIA_H_ +#define GFX_CANVAS_SKIA_H_ + +#include "base/basictypes.h" +#include "gfx/canvas_2.h" +#include "skia/ext/platform_canvas.h" + +#if defined(OS_POSIX) && !defined(OS_MACOSX) +typedef struct _GdkPixbuf GdkPixbuf; +#endif + +namespace gfx { + +class Canvas; + +// CanvasSkia is a SkCanvas subclass that provides a number of methods for +// common operations used throughout an application built using base/gfx and +// app/gfx. +// +// All methods that take integer arguments (as is used throughout views) +// end with Int. If you need to use methods provided by the superclass +// you'll need to do a conversion. In particular you'll need to use +// macro SkIntToScalar(xxx), or if converting from a scalar to an integer +// SkScalarRound. +// +// A handful of methods in this class are overloaded providing an additional +// argument of type SkXfermode::Mode. SkXfermode::Mode specifies how the +// source and destination colors are combined. Unless otherwise specified, +// the variant that does not take a SkXfermode::Mode uses a transfer mode +// of kSrcOver_Mode. +class CanvasSkia : public skia::PlatformCanvas, + public Canvas2 { + public: + // Creates an empty Canvas. Callers must use initialize before using the + // canvas. + CanvasSkia(); + + CanvasSkia(int width, int height, bool is_opaque); + + virtual ~CanvasSkia(); + + // Compute the size required to draw some text with the provided font. + // Attempts to fit the text with the provided width and height. Increases + // height and then width as needed to make the text fit. This method + // supports multiple lines. + static void SizeStringInt(const std::wstring& text, const gfx::Font& font, + int* width, int* height, int flags); + + // Returns the default text alignment to be used when drawing text on a + // gfx::CanvasSkia based on the directionality of the system locale language. + // This function is used by gfx::Canvas::DrawStringInt when the text alignment + // is not specified. + // + // This function returns either gfx::Canvas::TEXT_ALIGN_LEFT or + // gfx::Canvas::TEXT_ALIGN_RIGHT. + static int DefaultCanvasTextAlignment(); + +#if defined(OS_POSIX) && !defined(OS_MACOSX) + // Draw the pixbuf in its natural size at (x, y). + 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. + void 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); +#endif + + // Overridden from Canvas2: + virtual bool GetClipRect(gfx::Rect* clip_rect); + virtual bool ClipRectInt(int x, int y, int w, int h); + virtual bool IntersectsClipRectInt(int x, int y, int w, int h); + virtual void TranslateInt(int x, int y); + virtual void ScaleInt(int x, int y); + virtual void FillRectInt(int x, int y, int w, int h, + const SkPaint& paint); + virtual void FillRectInt(const SkColor& color, int x, int y, int w, + int h); + virtual void DrawRectInt(const SkColor& color, int x, int y, int w, + int h); + virtual void DrawRectInt(const SkColor& color, int x, int y, int w, int h, + SkXfermode::Mode mode); + virtual void DrawLineInt(const SkColor& color, int x1, int y1, int x2, + int y2); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int x, int y); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int x, int y, + const SkPaint& paint); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, bool filter); + virtual void DrawBitmapInt(const SkBitmap& bitmap, int src_x, int src_y, + int src_w, int src_h, int dest_x, int dest_y, + int dest_w, int dest_h, bool filter, + const SkPaint& paint); + virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, + int h); + virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, + const gfx::Rect& display_rect); + virtual void DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, int h, + int flags); + virtual void DrawFocusRect(int x, int y, int width, int height); + virtual void TileImageInt(const SkBitmap& bitmap, int x, int y, int w, int h); + virtual void TileImageInt(const SkBitmap& bitmap, int src_x, int src_y, + int dest_x, int dest_y, int w, int h); + virtual SkBitmap ExtractBitmap() const; + + private: +#if defined(OS_WIN) + // Draws text with the specified color, font and location. The text is + // aligned to the left, vertically centered, clipped to the region. If the + // text is too big, it is truncated and '...' is added to the end. + void DrawStringInt(const std::wstring& text, HFONT font, + const SkColor& color, int x, int y, int w, int h, + int flags); +#endif + + DISALLOW_COPY_AND_ASSIGN(CanvasSkia); +}; + +} // namespace gfx; + +#endif // GFX_CANVAS_SKIA_H_ diff --git a/gfx/canvas_skia_linux.cc b/gfx/canvas_skia_linux.cc new file mode 100644 index 0000000..59e0e29 --- /dev/null +++ b/gfx/canvas_skia_linux.cc @@ -0,0 +1,269 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gfx/canvas.h" + +#include +#include +#include +#include + +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "gfx/font.h" +#include "gfx/gtk_util.h" +#include "gfx/rect.h" + +namespace { + +const gunichar kAcceleratorChar = '&'; + +// Font settings that we initialize once and then use when drawing text in +// DrawStringInt(). +static cairo_font_options_t* cairo_font_options = NULL; + +// Update |cairo_font_options| based on GtkSettings, allocating it if needed. +static void UpdateCairoFontOptions() { + if (!cairo_font_options) + cairo_font_options = cairo_font_options_create(); + + GtkSettings* gtk_settings = gtk_settings_get_default(); + gint antialias = 0; + gint hinting = 0; + gchar* hint_style = NULL; + gchar* rgba_style = NULL; + g_object_get(gtk_settings, + "gtk-xft-antialias", &antialias, + "gtk-xft-hinting", &hinting, + "gtk-xft-hintstyle", &hint_style, + "gtk-xft-rgba", &rgba_style, + NULL); + + // g_object_get() doesn't tell us whether the properties were present or not, + // but if they aren't (because gnome-settings-daemon isn't running), we'll get + // NULL values for the strings. + if (hint_style && rgba_style) { + if (!antialias) { + cairo_font_options_set_antialias(cairo_font_options, + CAIRO_ANTIALIAS_NONE); + } else if (strcmp(rgba_style, "none") == 0) { + cairo_font_options_set_antialias(cairo_font_options, + CAIRO_ANTIALIAS_GRAY); + } else { + cairo_font_options_set_antialias(cairo_font_options, + CAIRO_ANTIALIAS_SUBPIXEL); + cairo_subpixel_order_t cairo_subpixel_order = + CAIRO_SUBPIXEL_ORDER_DEFAULT; + if (strcmp(rgba_style, "rgb") == 0) { + cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB; + } else if (strcmp(rgba_style, "bgr") == 0) { + cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR; + } else if (strcmp(rgba_style, "vrgb") == 0) { + cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB; + } else if (strcmp(rgba_style, "vbgr") == 0) { + cairo_subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR; + } + cairo_font_options_set_subpixel_order(cairo_font_options, + cairo_subpixel_order); + } + + cairo_hint_style_t cairo_hint_style = CAIRO_HINT_STYLE_DEFAULT; + if (hinting == 0 || strcmp(hint_style, "hintnone") == 0) { + cairo_hint_style = CAIRO_HINT_STYLE_NONE; + } else if (strcmp(hint_style, "hintslight") == 0) { + cairo_hint_style = CAIRO_HINT_STYLE_SLIGHT; + } else if (strcmp(hint_style, "hintmedium") == 0) { + cairo_hint_style = CAIRO_HINT_STYLE_MEDIUM; + } else if (strcmp(hint_style, "hintfull") == 0) { + cairo_hint_style = CAIRO_HINT_STYLE_FULL; + } + cairo_font_options_set_hint_style(cairo_font_options, cairo_hint_style); + } + + if (hint_style) + g_free(hint_style); + if (rgba_style) + 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, + const gfx::Font& font, + int width, + int flags) { + if (!cairo_font_options) + UpdateCairoFontOptions(); + // This needs to be done early on; it has no effect when called just before + // pango_cairo_show_layout(). + pango_cairo_context_set_font_options( + pango_layout_get_context(layout), cairo_font_options); + + // Callers of DrawStringInt handle RTL layout themselves, so tell pango to not + // scope out RTL characters. + pango_layout_set_auto_dir(layout, FALSE); + + if (width > 0) + pango_layout_set_width(layout, width * PANGO_SCALE); + + if (flags & 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) { + pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); + } else if (flags & Canvas::TEXT_ALIGN_RIGHT) { + pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT); + } + + if (flags & Canvas::MULTI_LINE) { + pango_layout_set_wrap(layout, + (flags & Canvas::CHARACTER_BREAK) ? + PANGO_WRAP_WORD_CHAR : PANGO_WRAP_WORD); + } + + // Set the resolution to match that used by Gtk. If we don't set the + // resolution and the resolution differs from the default, Gtk and Chrome end + // up drawing at different sizes. + double resolution = gfx::GetPangoResolution(); + if (resolution > 0) { + pango_cairo_context_set_resolution(pango_layout_get_context(layout), + resolution); + } + + PangoFontDescription* desc = gfx::Font::PangoFontFromGfxFont(font); + pango_layout_set_font_description(layout, desc); + pango_font_description_free(desc); + + // Set text and accelerator character if needed. + std::string utf8 = WideToUTF8(text); + if (flags & gfx::Canvas::HIDE_PREFIX) { + // Escape the text string to be used as markup. + gchar* escaped_text = g_markup_escape_text(utf8.c_str(), utf8.size()); + pango_layout_set_markup_with_accel(layout, + escaped_text, + strlen(escaped_text), + kAcceleratorChar, NULL); + g_free(escaped_text); + } else { + pango_layout_set_text(layout, utf8.data(), utf8.size()); + } +} + +// static +void CanvasSkia::SizeStringInt(const std::wstring& text, + const gfx::Font& font, + int* width, int* height, int flags) { + int org_width = *width; + cairo_surface_t* surface = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0); + cairo_t* cr = cairo_create(surface); + PangoLayout* layout = pango_cairo_create_layout(cr); + + SetupPangoLayout(layout, text, font, *width, flags); + + pango_layout_get_pixel_size(layout, width, height); + + 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 + // such that the width returned from pango_layout_get_pixel_size is too + // small. Using the width from pango_layout_get_pixel_size in this case + // results in wrapping across more lines, which requires a bigger height. + // As a workaround we use the original width, which is not necessarily + // exactly correct, but isn't wrong by much. + // + // It looks like Pango uses the size of whitespace in calculating wrapping + // but doesn't include the size of the whitespace when the extents are + // asked for. See the loop in pango-layout.c process_item that determines + // where to wrap. + *width = org_width; + } + + g_object_unref(layout); + cairo_destroy(cr); + cairo_surface_destroy(surface); +} + +void CanvasSkia::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + int x, int y, int w, int h, + int flags) { + 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.style() & gfx::Font::UNDERLINED) { + double underline_y = + static_cast(y) + height + font.underline_position(); + cairo_set_line_width(cr, 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. +} + +void CanvasSkia::DrawGdkPixbuf(GdkPixbuf* pixbuf, int x, int y) { + if (!pixbuf) { + NOTREACHED(); + return; + } + + cairo_t* cr = beginPlatformPaint(); + gdk_cairo_set_source_pixbuf(cr, pixbuf, x, y); + cairo_paint(cr); +} + +} // namespace gfx diff --git a/gfx/canvas_skia_mac.mm b/gfx/canvas_skia_mac.mm new file mode 100644 index 0000000..29102fd --- /dev/null +++ b/gfx/canvas_skia_mac.mm @@ -0,0 +1,84 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +#include "gfx/canvas.h" + +#include "base/scoped_cftyperef.h" +#include "base/sys_string_conversions.h" +#include "gfx/font.h" +#include "gfx/rect.h" +#include "third_party/skia/include/core/SkShader.h" + +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, + int *width, int *height, int flags) { + NSFont* native_font = font.nativeFont(); + NSString* ns_string = base::SysWideToNSString(text); + NSDictionary* attributes = + [NSDictionary dictionaryWithObject:native_font + forKey:NSFontAttributeName]; + NSSize string_size = [ns_string sizeWithAttributes:attributes]; + *width = string_size.width; + *height = font.height(); +} + +void CanvasSkia::DrawStringInt(const std::wstring& text, const gfx::Font& font, + const SkColor& color, int x, int y, int w, int h, + int flags) { + if (!IntersectsClipRectInt(x, y, w, h)) + return; + + CGContextRef context = beginPlatformPaint(); + CGContextSaveGState(context); + + NSColor* ns_color = [NSColor colorWithDeviceRed:SkColorGetR(color) / 255.0 + green:SkColorGetG(color) / 255.0 + blue:SkColorGetB(color) / 255.0 + alpha:SkColorGetA(color) / 255.0]; + NSMutableParagraphStyle *ns_style = + [[[NSParagraphStyle alloc] init] autorelease]; + if (flags & TEXT_ALIGN_CENTER) + [ns_style setAlignment:NSCenterTextAlignment]; + // TODO(awalker): Implement the rest of the Canvas text flags + + NSDictionary* attributes = + [NSDictionary dictionaryWithObjectsAndKeys: + font.nativeFont(), NSFontAttributeName, + ns_color, NSForegroundColorAttributeName, + ns_style, NSParagraphStyleAttributeName, + nil]; + + NSAttributedString* ns_string = + [[[NSAttributedString alloc] initWithString:base::SysWideToNSString(text) + attributes:attributes] autorelease]; + scoped_cftyperef framesetter( + CTFramesetterCreateWithAttributedString(reinterpret_cast(ns_string))); + + CGRect text_bounds = CGRectMake(x, y, w, h); + CGMutablePathRef path = CGPathCreateMutable(); + CGPathAddRect(path, NULL, text_bounds); + + scoped_cftyperef frame( + CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL)); + CTFrameDraw(frame, context); + CGContextRestoreGState(context); + endPlatformPaint(); +} + +} // namespace gfx diff --git a/gfx/canvas_skia_paint.h b/gfx/canvas_skia_paint.h new file mode 100644 index 0000000..4e6f768 --- /dev/null +++ b/gfx/canvas_skia_paint.h @@ -0,0 +1,20 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GFX_CANVAS_SKIA_PAINT_H_ +#define GFX_CANVAS_SKIA_PAINT_H_ + +#include "gfx/canvas.h" +#include "skia/ext/canvas_paint.h" + +// Define a gfx::CanvasSkiaPaint type that wraps our gfx::Canvas like the +// skia::PlatformCanvasPaint wraps PlatformCanvas. + +namespace gfx { + +typedef skia::CanvasPaintT CanvasSkiaPaint; + +} // namespace gfx + +#endif // GFX_CANVAS_SKIA_PAINT_H_ diff --git a/gfx/canvas_skia_win.cc b/gfx/canvas_skia_win.cc new file mode 100644 index 0000000..4177ef5 --- /dev/null +++ b/gfx/canvas_skia_win.cc @@ -0,0 +1,293 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gfx/canvas.h" + +#include + +#include "base/i18n/rtl.h" +#include "gfx/font.h" +#include "gfx/rect.h" +#include "third_party/skia/include/core/SkShader.h" + +namespace { + +// We make sure that LTR text we draw in an RTL context is modified +// appropriately to make sure it maintains it LTR orientation. +void DoDrawText(HDC hdc, const std::wstring& text, + RECT* text_bounds, int flags) { + std::wstring localized_text; + const wchar_t* string_ptr = text.c_str(); + int string_size = static_cast(text.length()); + // Only adjust string directionality if both of the following are true: + // 1. The current locale is RTL. + // 2. The string itself has RTL directionality. + if (flags & DT_RTLREADING) { + if (base::i18n::AdjustStringForLocaleDirection(text, &localized_text)) { + string_ptr = localized_text.c_str(); + string_size = static_cast(localized_text.length()); + } + } + + DrawText(hdc, string_ptr, string_size, text_bounds, flags); +} + +// Compute the windows flags necessary to implement the provided text Canvas +// flags. +int ComputeFormatFlags(int flags, const std::wstring& text) { + // Setting the text alignment explicitly in case it hasn't already been set. + // This will make sure that we don't align text to the left on RTL locales + // just because no alignment flag was passed to DrawStringInt(). + if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | + gfx::Canvas::TEXT_ALIGN_RIGHT | + gfx::Canvas::TEXT_ALIGN_LEFT))) { + flags |= gfx::CanvasSkia::DefaultCanvasTextAlignment(); + } + + // horizontal alignment + int f = 0; + if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) + f |= DT_CENTER; + else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) + f |= DT_RIGHT; + else + f |= DT_LEFT; + + // vertical alignment + if (flags & gfx::Canvas::TEXT_VALIGN_TOP) + f |= DT_TOP; + else if (flags & gfx::Canvas::TEXT_VALIGN_BOTTOM) + f |= DT_BOTTOM; + else + f |= DT_VCENTER; + + if (flags & gfx::Canvas::MULTI_LINE) { + f |= DT_WORDBREAK; + if (flags & gfx::Canvas::CHARACTER_BREAK) + f |= DT_EDITCONTROL; // Turns on character breaking (not documented) + else if (!(flags & gfx::Canvas::NO_ELLIPSIS)) + f |= DT_WORD_ELLIPSIS; + } else { + f |= DT_SINGLELINE; + } + + if (flags & gfx::Canvas::HIDE_PREFIX) + f |= DT_HIDEPREFIX; + else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0) + f |= DT_NOPREFIX; + + if (!(flags & gfx::Canvas::NO_ELLIPSIS)) + f |= DT_END_ELLIPSIS; + + // In order to make sure RTL/BiDi strings are rendered correctly, we must + // pass the flag DT_RTLREADING to DrawText (when the locale's language is + // a right-to-left language) so that Windows does the right thing. + // + // In addition to correctly displaying text containing both RTL and LTR + // elements (for example, a string containing a telephone number within a + // sentence in Hebrew, or a sentence in Hebrew that contains a word in + // English) this flag also makes sure that if there is not enough space to + // display the entire string, the ellipsis is displayed on the left hand side + // of the truncated string and not on the right hand side. + // + // We make a distinction between Chrome UI strings and text coming from a web + // page. + // + // For text coming from a web page we determine the alignment based on the + // first character with strong directionality. If the directionality of the + // first character with strong directionality in the text is LTR, the + // alignment is set to DT_LEFT, and the directionality should not be set as + // DT_RTLREADING. + // + // This heuristic doesn't work for Chrome UI strings since even in RTL + // locales, some of those might start with English text but we know they're + // localized so we always want them to be right aligned, and their + // directionality should be set as DT_RTLREADING. + // + // Caveat: If the string is purely LTR, don't set DTL_RTLREADING since when + // the flag is set, LRE-PDF don't have the desired effect of rendering + // multiline English-only text as LTR. + // + // Note that if the caller is explicitly requesting displaying the text + // using RTL directionality then we respect that and pass DT_RTLREADING to + // ::DrawText even if the locale is LTR. + if ((flags & gfx::Canvas::FORCE_RTL_DIRECTIONALITY) || + (base::i18n::IsRTL() && + (f & DT_RIGHT) && base::i18n::StringContainsStrongRTLChars(text))) { + f |= DT_RTLREADING; + } + + return f; +} + +} // anonymous 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, + int* width, int* height, int flags) { + // Clamp the max amount of text we'll measure to 2K. When the string is + // actually drawn, it will be clipped to whatever size box is provided, and + // the time to do that doesn't depend on the length being clipped off. + const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. + std::wstring clamped_string(text.substr(0, kMaxStringLength)); + + if (*width == 0) { + // If multi-line + character break are on, the computed width will be one + // character wide (useless). Furthermore, if in this case the provided text + // contains very long "words" (substrings without a word-breaking point), + // DrawText() can run extremely slowly (e.g. several seconds). So in this + // case, we turn character breaking off to get a more accurate "desired" + // width and avoid the slowdown. + if (flags & (gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK)) + flags &= ~gfx::Canvas::CHARACTER_BREAK; + + // Weird undocumented behavior: if the width is 0, DoDrawText() won't + // calculate a size at all. So set it to 1, which it will then change. + if (!text.empty()) + *width = 1; + } + RECT r = { 0, 0, *width, *height }; + + HDC dc = GetDC(NULL); + HFONT old_font = static_cast(SelectObject(dc, font.hfont())); + DoDrawText(dc, clamped_string, &r, + ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT); + SelectObject(dc, old_font); + ReleaseDC(NULL, dc); + + *width = r.right; + *height = r.bottom; +} + +void CanvasSkia::DrawStringInt(const std::wstring& text, HFONT font, + const SkColor& color, int x, int y, int w, int h, + int flags) { + if (!IntersectsClipRectInt(x, y, w, h)) + return; + + // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in + // DrawText() if you e.g. ask it to character-break a no-whitespace string of + // length > 43680 (for which it draws nothing), and since we clamped to 2K in + // SizeStringInt() we're unlikely to be able to display this much anyway. + const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. + std::wstring clamped_string(text.substr(0, kMaxStringLength)); + + RECT text_bounds = { x, y, x + w, y + h }; + HDC dc = beginPlatformPaint(); + SetBkMode(dc, TRANSPARENT); + HFONT old_font = (HFONT)SelectObject(dc, font); + COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), + SkColorGetB(color)); + SetTextColor(dc, brush_color); + + int f = ComputeFormatFlags(flags, clamped_string); + DoDrawText(dc, clamped_string, &text_bounds, f); + endPlatformPaint(); + + // Restore the old font. This way we don't have to worry if the caller + // deletes the font and the DC lives longer. + SelectObject(dc, old_font); + + // Windows will have cleared the alpha channel of the text we drew. Assume + // we're drawing to an opaque surface, or at least the text rect area is + // opaque. + getTopPlatformDevice().makeOpaque(x, y, w, h); +} + +void CanvasSkia::DrawStringInt(const std::wstring& text, + const gfx::Font& font, + const SkColor& color, + int x, int y, int w, int h, int flags) { + DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); +} + +// Checks each pixel immediately adjacent to the given pixel in the bitmap. If +// any of them are not the halo color, returns true. This defines the halo of +// pixels that will appear around the text. Note that we have to check each +// pixel against both the halo color and transparent since DrawStringWithHalo +// will modify the bitmap as it goes, and clears pixels shouldn't count as +// changed. +static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, + SkColor halo_color) { + if (x > 0 && + *bitmap.getAddr32(x - 1, y) != halo_color && + *bitmap.getAddr32(x - 1, y) != 0) + return true; // Touched pixel to the left. + if (x < bitmap.width() - 1 && + *bitmap.getAddr32(x + 1, y) != halo_color && + *bitmap.getAddr32(x + 1, y) != 0) + return true; // Touched pixel to the right. + if (y > 0 && + *bitmap.getAddr32(x, y - 1) != halo_color && + *bitmap.getAddr32(x, y - 1) != 0) + return true; // Touched pixel above. + if (y < bitmap.height() - 1 && + *bitmap.getAddr32(x, y + 1) != halo_color && + *bitmap.getAddr32(x, y + 1) != 0) + return true; // Touched pixel below. + return false; +} + +void CanvasSkia::DrawStringWithHalo(const std::wstring& text, + const gfx::Font& font, + const SkColor& text_color, + const SkColor& halo_color_in, + int x, int y, int w, int h, + int flags) { + // Some callers will have semitransparent halo colors, which we don't handle + // (since the resulting image can have 1-bit transparency only). + SkColor halo_color = halo_color_in | 0xFF000000; + + // Create a temporary buffer filled with the halo color. It must leave room + // for the 1-pixel border around the text. + CanvasSkia text_canvas(w + 2, h + 2, true); + SkPaint bkgnd_paint; + bkgnd_paint.setColor(halo_color); + text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); + + // Draw the text into the temporary buffer. This will have correct + // ClearType since the background color is the same as the halo color. + text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); + + // Windows will have cleared the alpha channel for the pixels it drew. Make it + // opaque. We have to do this first since pixelShouldGetHalo will check for + // 0 to see if a pixel has been modified to transparent, and black text that + // Windows draw will look transparent to it! + text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); + + uint32_t halo_premul = SkPreMultiplyColor(halo_color); + SkBitmap& text_bitmap = const_cast( + text_canvas.getTopPlatformDevice().accessBitmap(true)); + for (int cur_y = 0; cur_y < h + 2; cur_y++) { + uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); + for (int cur_x = 0; cur_x < w + 2; cur_x++) { + if (text_row[cur_x] == halo_premul) { + // This pixel was not touched by the text routines. See if it borders + // a touched pixel in any of the 4 directions (not diagonally). + if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) + text_row[cur_x] = 0; // Make transparent. + } else { + text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. + } + } + } + + // Draw the halo bitmap with blur. + drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); +} + +} // namespace gfx diff --git a/gfx/canvas_win.cc b/gfx/canvas_win.cc deleted file mode 100644 index 98c5f74..0000000 --- a/gfx/canvas_win.cc +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gfx/canvas.h" - -#include - -#include "base/i18n/rtl.h" -#include "gfx/font.h" -#include "gfx/rect.h" -#include "third_party/skia/include/core/SkShader.h" - -namespace { - -// We make sure that LTR text we draw in an RTL context is modified -// appropriately to make sure it maintains it LTR orientation. -void DoDrawText(HDC hdc, const std::wstring& text, - RECT* text_bounds, int flags) { - std::wstring localized_text; - const wchar_t* string_ptr = text.c_str(); - int string_size = static_cast(text.length()); - // Only adjust string directionality if both of the following are true: - // 1. The current locale is RTL. - // 2. The string itself has RTL directionality. - if (flags & DT_RTLREADING) { - if (base::i18n::AdjustStringForLocaleDirection(text, &localized_text)) { - string_ptr = localized_text.c_str(); - string_size = static_cast(localized_text.length()); - } - } - - DrawText(hdc, string_ptr, string_size, text_bounds, flags); -} - -// Compute the windows flags necessary to implement the provided text Canvas -// flags. -int ComputeFormatFlags(int flags, const std::wstring& text) { - // Setting the text alignment explicitly in case it hasn't already been set. - // This will make sure that we don't align text to the left on RTL locales - // just because no alignment flag was passed to DrawStringInt(). - if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER | - gfx::Canvas::TEXT_ALIGN_RIGHT | - gfx::Canvas::TEXT_ALIGN_LEFT))) { - flags |= gfx::Canvas::DefaultCanvasTextAlignment(); - } - - // horizontal alignment - int f = 0; - if (flags & gfx::Canvas::TEXT_ALIGN_CENTER) - f |= DT_CENTER; - else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT) - f |= DT_RIGHT; - else - f |= DT_LEFT; - - // vertical alignment - if (flags & gfx::Canvas::TEXT_VALIGN_TOP) - f |= DT_TOP; - else if (flags & gfx::Canvas::TEXT_VALIGN_BOTTOM) - f |= DT_BOTTOM; - else - f |= DT_VCENTER; - - if (flags & gfx::Canvas::MULTI_LINE) { - f |= DT_WORDBREAK; - if (flags & gfx::Canvas::CHARACTER_BREAK) - f |= DT_EDITCONTROL; // Turns on character breaking (not documented) - else if (!(flags & gfx::Canvas::NO_ELLIPSIS)) - f |= DT_WORD_ELLIPSIS; - } else { - f |= DT_SINGLELINE; - } - - if (flags & gfx::Canvas::HIDE_PREFIX) - f |= DT_HIDEPREFIX; - else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0) - f |= DT_NOPREFIX; - - if (!(flags & gfx::Canvas::NO_ELLIPSIS)) - f |= DT_END_ELLIPSIS; - - // In order to make sure RTL/BiDi strings are rendered correctly, we must - // pass the flag DT_RTLREADING to DrawText (when the locale's language is - // a right-to-left language) so that Windows does the right thing. - // - // In addition to correctly displaying text containing both RTL and LTR - // elements (for example, a string containing a telephone number within a - // sentence in Hebrew, or a sentence in Hebrew that contains a word in - // English) this flag also makes sure that if there is not enough space to - // display the entire string, the ellipsis is displayed on the left hand side - // of the truncated string and not on the right hand side. - // - // We make a distinction between Chrome UI strings and text coming from a web - // page. - // - // For text coming from a web page we determine the alignment based on the - // first character with strong directionality. If the directionality of the - // first character with strong directionality in the text is LTR, the - // alignment is set to DT_LEFT, and the directionality should not be set as - // DT_RTLREADING. - // - // This heuristic doesn't work for Chrome UI strings since even in RTL - // locales, some of those might start with English text but we know they're - // localized so we always want them to be right aligned, and their - // directionality should be set as DT_RTLREADING. - // - // Caveat: If the string is purely LTR, don't set DTL_RTLREADING since when - // the flag is set, LRE-PDF don't have the desired effect of rendering - // multiline English-only text as LTR. - // - // Note that if the caller is explicitly requesting displaying the text - // using RTL directionality then we respect that and pass DT_RTLREADING to - // ::DrawText even if the locale is LTR. - if ((flags & gfx::Canvas::FORCE_RTL_DIRECTIONALITY) || - (base::i18n::IsRTL() && - (f & DT_RIGHT) && base::i18n::StringContainsStrongRTLChars(text))) { - f |= DT_RTLREADING; - } - - return f; -} - -} // anonymous namespace - -namespace gfx { - -Canvas::Canvas(int width, int height, bool is_opaque) - : skia::PlatformCanvas(width, height, is_opaque) { -} - -Canvas::Canvas() : skia::PlatformCanvas() { -} - -Canvas::~Canvas() { -} - -// static -void Canvas::SizeStringInt(const std::wstring& text, - const gfx::Font& font, - int* width, int* height, int flags) { - // Clamp the max amount of text we'll measure to 2K. When the string is - // actually drawn, it will be clipped to whatever size box is provided, and - // the time to do that doesn't depend on the length being clipped off. - const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K. - std::wstring clamped_string(text.substr(0, kMaxStringLength)); - - if (*width == 0) { - // If multi-line + character break are on, the computed width will be one - // character wide (useless). Furthermore, if in this case the provided text - // contains very long "words" (substrings without a word-breaking point), - // DrawText() can run extremely slowly (e.g. several seconds). So in this - // case, we turn character breaking off to get a more accurate "desired" - // width and avoid the slowdown. - if (flags & (gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK)) - flags &= ~gfx::Canvas::CHARACTER_BREAK; - - // Weird undocumented behavior: if the width is 0, DoDrawText() won't - // calculate a size at all. So set it to 1, which it will then change. - if (!text.empty()) - *width = 1; - } - RECT r = { 0, 0, *width, *height }; - - HDC dc = GetDC(NULL); - HFONT old_font = static_cast(SelectObject(dc, font.hfont())); - DoDrawText(dc, clamped_string, &r, - ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT); - SelectObject(dc, old_font); - ReleaseDC(NULL, dc); - - *width = r.right; - *height = r.bottom; -} - -void Canvas::DrawStringInt(const std::wstring& text, HFONT font, - const SkColor& color, int x, int y, int w, int h, - int flags) { - if (!IntersectsClipRectInt(x, y, w, h)) - return; - - // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in - // DrawText() if you e.g. ask it to character-break a no-whitespace string of - // length > 43680 (for which it draws nothing), and since we clamped to 2K in - // SizeStringInt() we're unlikely to be able to display this much anyway. - const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K. - std::wstring clamped_string(text.substr(0, kMaxStringLength)); - - RECT text_bounds = { x, y, x + w, y + h }; - HDC dc = beginPlatformPaint(); - SetBkMode(dc, TRANSPARENT); - HFONT old_font = (HFONT)SelectObject(dc, font); - COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color), - SkColorGetB(color)); - SetTextColor(dc, brush_color); - - int f = ComputeFormatFlags(flags, clamped_string); - DoDrawText(dc, clamped_string, &text_bounds, f); - endPlatformPaint(); - - // Restore the old font. This way we don't have to worry if the caller - // deletes the font and the DC lives longer. - SelectObject(dc, old_font); - - // Windows will have cleared the alpha channel of the text we drew. Assume - // we're drawing to an opaque surface, or at least the text rect area is - // opaque. - getTopPlatformDevice().makeOpaque(x, y, w, h); -} - -void Canvas::DrawStringInt(const std::wstring& text, - const gfx::Font& font, - const SkColor& color, - int x, int y, int w, int h, int flags) { - DrawStringInt(text, font.hfont(), color, x, y, w, h, flags); -} - -// Checks each pixel immediately adjacent to the given pixel in the bitmap. If -// any of them are not the halo color, returns true. This defines the halo of -// pixels that will appear around the text. Note that we have to check each -// pixel against both the halo color and transparent since DrawStringWithHalo -// will modify the bitmap as it goes, and clears pixels shouldn't count as -// changed. -static bool pixelShouldGetHalo(const SkBitmap& bitmap, int x, int y, - SkColor halo_color) { - if (x > 0 && - *bitmap.getAddr32(x - 1, y) != halo_color && - *bitmap.getAddr32(x - 1, y) != 0) - return true; // Touched pixel to the left. - if (x < bitmap.width() - 1 && - *bitmap.getAddr32(x + 1, y) != halo_color && - *bitmap.getAddr32(x + 1, y) != 0) - return true; // Touched pixel to the right. - if (y > 0 && - *bitmap.getAddr32(x, y - 1) != halo_color && - *bitmap.getAddr32(x, y - 1) != 0) - return true; // Touched pixel above. - if (y < bitmap.height() - 1 && - *bitmap.getAddr32(x, y + 1) != halo_color && - *bitmap.getAddr32(x, y + 1) != 0) - return true; // Touched pixel below. - return false; -} - -void Canvas::DrawStringWithHalo(const std::wstring& text, - const gfx::Font& font, - const SkColor& text_color, - const SkColor& halo_color_in, - int x, int y, int w, int h, - int flags) { - // Some callers will have semitransparent halo colors, which we don't handle - // (since the resulting image can have 1-bit transparency only). - SkColor halo_color = halo_color_in | 0xFF000000; - - // Create a temporary buffer filled with the halo color. It must leave room - // for the 1-pixel border around the text. - Canvas text_canvas(w + 2, h + 2, true); - SkPaint bkgnd_paint; - bkgnd_paint.setColor(halo_color); - text_canvas.FillRectInt(0, 0, w + 2, h + 2, bkgnd_paint); - - // Draw the text into the temporary buffer. This will have correct - // ClearType since the background color is the same as the halo color. - text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags); - - // Windows will have cleared the alpha channel for the pixels it drew. Make it - // opaque. We have to do this first since pixelShouldGetHalo will check for - // 0 to see if a pixel has been modified to transparent, and black text that - // Windows draw will look transparent to it! - text_canvas.getTopPlatformDevice().makeOpaque(0, 0, w + 2, h + 2); - - uint32_t halo_premul = SkPreMultiplyColor(halo_color); - SkBitmap& text_bitmap = const_cast( - text_canvas.getTopPlatformDevice().accessBitmap(true)); - for (int cur_y = 0; cur_y < h + 2; cur_y++) { - uint32_t* text_row = text_bitmap.getAddr32(0, cur_y); - for (int cur_x = 0; cur_x < w + 2; cur_x++) { - if (text_row[cur_x] == halo_premul) { - // This pixel was not touched by the text routines. See if it borders - // a touched pixel in any of the 4 directions (not diagonally). - if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul)) - text_row[cur_x] = 0; // Make transparent. - } else { - text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque. - } - } - } - - // Draw the halo bitmap with blur. - drawBitmap(text_bitmap, SkIntToScalar(x - 1), SkIntToScalar(y - 1)); -} - -} // namespace gfx diff --git a/gfx/gfx.gyp b/gfx/gfx.gyp index 54d6833..c0d4000 100644 --- a/gfx/gfx.gyp +++ b/gfx/gfx.gyp @@ -62,13 +62,14 @@ 'sources': [ 'blit.cc', 'blit.h', - 'canvas.cc', 'canvas.h', 'canvas_2.h', - 'canvas_linux.cc', - 'canvas_mac.mm', - 'canvas_paint.h', - 'canvas_win.cc', + 'canvas_skia.h', + 'canvas_skia.cc', + 'canvas_skia_linux.cc', + 'canvas_skia_mac.mm', + 'canvas_skia_paint.h', + 'canvas_skia_win.cc', 'codec/jpeg_codec.cc', 'codec/jpeg_codec.h', 'codec/png_codec.cc', @@ -79,7 +80,6 @@ 'font.h', 'font_gtk.cc', 'font_mac.mm', - 'font_skia.cc', 'font_win.cc', 'gfx_paths.cc', 'gfx_paths.h', @@ -123,6 +123,7 @@ '../build/linux/system.gyp:fontconfig', ], 'sources': [ + 'font_skia.cc', 'gtk_native_view_id_manager.cc', 'gtk_native_view_id_manager.h', 'gtk_util.cc', diff --git a/views/controls/menu/menu_controller.cc b/views/controls/menu/menu_controller.cc index d0adb838..de31f02 100644 --- a/views/controls/menu/menu_controller.cc +++ b/views/controls/menu/menu_controller.cc @@ -469,6 +469,7 @@ void MenuController::OnMouseDragged(SubmenuView* source, gfx::Point press_loc(press_pt_); View::ConvertPointToScreen(source->GetScrollViewContainer(), &press_loc); View::ConvertPointToView(NULL, item, &press_loc); + // TODO(beng): Convert to CanvasSkia gfx::Canvas canvas(item->width(), item->height(), false); item->Paint(&canvas, true); diff --git a/views/controls/menu/menu_win.cc b/views/controls/menu/menu_win.cc index b941788..5c976d5 100644 --- a/views/controls/menu/menu_win.cc +++ b/views/controls/menu/menu_win.cc @@ -13,7 +13,7 @@ #include "base/logging.h" #include "base/stl_util-inl.h" #include "base/string_util.h" -#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/font.h" #include "gfx/rect.h" #include "views/accelerator.h" @@ -184,7 +184,7 @@ class MenuHostWindow : public app::WindowImpl { // Draw the icon after the label, otherwise it would be covered // by the label. if (data->icon.width() != 0 && data->icon.height() != 0) { - gfx::Canvas canvas(data->icon.width(), data->icon.height(), false); + gfx::CanvasSkia canvas(data->icon.width(), data->icon.height(), false); canvas.drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); canvas.DrawBitmapInt(data->icon, 0, 0); canvas.getTopPlatformDevice().drawToHDC(hDC, lpdis->rcItem.left + diff --git a/views/controls/menu/native_menu_win.cc b/views/controls/menu/native_menu_win.cc index 0881ab5..cc528e3 100644 --- a/views/controls/menu/native_menu_win.cc +++ b/views/controls/menu/native_menu_win.cc @@ -9,7 +9,7 @@ #include "base/keyboard_codes.h" #include "base/logging.h" #include "base/stl_util-inl.h" -#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/font.h" #include "third_party/skia/include/core/SkBitmap.h" #include "views/accelerator.h" @@ -223,7 +223,7 @@ class NativeMenuWin::MenuHostWindow { // by the label. SkBitmap icon; if (data->native_menu_win->model_->GetIconAt(data->model_index, &icon)) { - gfx::Canvas canvas(icon.width(), icon.height(), false); + gfx::CanvasSkia canvas(icon.width(), icon.height(), false); canvas.drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); canvas.DrawBitmapInt(icon, 0, 0); canvas.getTopPlatformDevice().drawToHDC(dc, diff --git a/views/controls/table/native_table_win.cc b/views/controls/table/native_table_win.cc index d34856f..f0b0659 100644 --- a/views/controls/table/native_table_win.cc +++ b/views/controls/table/native_table_win.cc @@ -12,7 +12,7 @@ #include "app/table_model.h" #include "base/logging.h" #include "base/win_util.h" -#include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/favicon_size.h" #include "gfx/icon_util.h" #include "skia/ext/skia_utils_win.h" @@ -389,7 +389,7 @@ void NativeTableWin::CreateNativeControl() { // We create 2 phony images because we are going to switch images at every // refresh in order to force a refresh of the icon area (somehow the clip // rect does not include the icon). - gfx::Canvas canvas(kImageSize, kImageSize, false); + gfx::CanvasSkia canvas(kImageSize, kImageSize, false); // Make the background completely transparent. canvas.drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); HICON empty_icon = @@ -508,8 +508,8 @@ LRESULT NativeTableWin::OnCustomDraw(NMLVCUSTOMDRAW* draw_info) { client_rect.top += content_offset_; // Make sure the region need to paint is visible. if (IntersectRect(&intersection, &icon_rect, &client_rect)) { - gfx::Canvas canvas(icon_rect.right - icon_rect.left, - icon_rect.bottom - icon_rect.top, false); + gfx::CanvasSkia canvas(icon_rect.right - icon_rect.left, + icon_rect.bottom - icon_rect.top, false); // It seems the state in nmcd.uItemState is not correct. // We'll retrieve it explicitly. diff --git a/views/controls/table/table_view.cc b/views/controls/table/table_view.cc index 2363985..75425c2 100644 --- a/views/controls/table/table_view.cc +++ b/views/controls/table/table_view.cc @@ -834,7 +834,7 @@ HWND TableView::CreateNativeControl(HWND parent_container) { // We create 2 phony images because we are going to switch images at every // refresh in order to force a refresh of the icon area (somehow the clip // rect does not include the icon). - gfx::Canvas canvas(kImageSize, kImageSize, false); + gfx::CanvasSkia canvas(kImageSize, kImageSize, false); // Make the background completely transparent. canvas.drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); HICON empty_icon = @@ -1153,7 +1153,7 @@ void TableView::PaintAltText() { HDC dc = GetDC(GetNativeControlHWND()); gfx::Font font = GetAltTextFont(); gfx::Rect bounds = GetAltTextBounds(); - gfx::Canvas canvas(bounds.width(), bounds.height(), false); + gfx::CanvasSkia canvas(bounds.width(), bounds.height(), false); // Pad by 1 for halo. canvas.DrawStringWithHalo(alt_text_, font, SK_ColorDKGRAY, SK_ColorWHITE, 1, 1, bounds.width() - 2, bounds.height() - 2, @@ -1236,8 +1236,8 @@ LRESULT TableView::OnCustomDraw(NMLVCUSTOMDRAW* draw_info) { client_rect.top += content_offset_; // Make sure the region need to paint is visible. if (IntersectRect(&intersection, &icon_rect, &client_rect)) { - gfx::Canvas canvas(icon_rect.right - icon_rect.left, - icon_rect.bottom - icon_rect.top, false); + gfx::CanvasSkia canvas(icon_rect.right - icon_rect.left, + icon_rect.bottom - icon_rect.top, false); // It seems the state in nmcd.uItemState is not correct. // We'll retrieve it explicitly. diff --git a/views/controls/textfield/gtk_views_entry.cc b/views/controls/textfield/gtk_views_entry.cc index 037e902d..a068009 100644 --- a/views/controls/textfield/gtk_views_entry.cc +++ b/views/controls/textfield/gtk_views_entry.cc @@ -5,7 +5,7 @@ #include "views/controls/textfield/gtk_views_entry.h" #include "base/utf_string_conversions.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/insets.h" #include "gfx/skia_utils_gtk.h" #include "views/controls/textfield/native_textfield_gtk.h" @@ -28,7 +28,7 @@ static gint gtk_views_entry_expose_event(GtkWidget *widget, if (host && event->window == entry->text_area && !host->textfield()->text_to_display_when_empty().empty() && g_utf8_strlen(gtk_entry_get_text(entry), -1) == 0) { - gfx::CanvasPaint canvas(event); + gfx::CanvasSkiaPaint canvas(event); if (!canvas.is_empty()) { gfx::Insets insets = views::NativeTextfieldGtk::GetEntryInnerBorder(entry); diff --git a/views/controls/textfield/gtk_views_textview.cc b/views/controls/textfield/gtk_views_textview.cc index e285ad9..da43d93 100644 --- a/views/controls/textfield/gtk_views_textview.cc +++ b/views/controls/textfield/gtk_views_textview.cc @@ -5,7 +5,7 @@ #include "views/controls/textfield/gtk_views_textview.h" #include "base/utf_string_conversions.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/insets.h" #include "gfx/skia_utils_gtk.h" #include "views/controls/textfield/native_textfield_gtk.h" @@ -43,7 +43,7 @@ static gint gtk_views_textview_expose_event(GtkWidget *widget, if (host && event->window == text_window && !host->textfield()->text_to_display_when_empty().empty() && gtk_text_iter_equal(&start, &end)) { - gfx::CanvasPaint canvas(event); + gfx::CanvasSkiaPaint canvas(event); if (!canvas.is_empty()) { gfx::Insets insets = views::NativeTextfieldGtk::GetTextViewInnerBorder(text_view); diff --git a/views/controls/tree/tree_view.cc b/views/controls/tree/tree_view.cc index b544abc..799d89a 100644 --- a/views/controls/tree/tree_view.cc +++ b/views/controls/tree/tree_view.cc @@ -13,8 +13,8 @@ #include "base/keyboard_codes.h" #include "base/stl_util-inl.h" #include "base/win_util.h" -#include "gfx/canvas.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/favicon_size.h" #include "gfx/icon_util.h" #include "gfx/point.h" @@ -688,7 +688,7 @@ HIMAGELIST TreeView::CreateImageList() { // IDR_FOLDER_CLOSED if they aren't already. if (model_images[i].width() != width || model_images[i].height() != height) { - gfx::Canvas canvas(width, height, false); + gfx::CanvasSkia canvas(width, height, false); // Make the background completely transparent. canvas.drawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); @@ -739,16 +739,16 @@ LRESULT CALLBACK TreeView::TreeWndProc(HWND window, return 1; case WM_PAINT: { - gfx::CanvasPaint canvas(window); + gfx::CanvasSkiaPaint canvas(window); if (canvas.isEmpty()) return 0; HDC dc = canvas.beginPlatformPaint(); if (base::i18n::IsRTL()) { - // gfx::Canvas ends up configuring the DC with a mode of GM_ADVANCED. - // For some reason a graphics mode of ADVANCED triggers all the text - // to be mirrored when RTL. Set the mode back to COMPATIBLE and - // explicitly set the layout. Additionally SetWorldTransform and + // gfx::CanvasSkia ends up configuring the DC with a mode of + // GM_ADVANCED. For some reason a graphics mode of ADVANCED triggers + // all the text to be mirrored when RTL. Set the mode back to COMPATIBLE + // and explicitly set the layout. Additionally SetWorldTransform and // COMPATIBLE don't play nicely together. We need to use // SetViewportOrgEx when using a mode of COMPATIBLE. // diff --git a/views/drag_utils.cc b/views/drag_utils.cc index 73ecedb..8fbd79a 100644 --- a/views/drag_utils.cc +++ b/views/drag_utils.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/utf_string_conversions.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/font.h" #include "googleurl/src/gurl.h" #include "grit/app_resources.h" @@ -48,6 +49,7 @@ void SetURLAndDragImage(const GURL& url, button.SetBounds(0, 0, prefsize.width(), prefsize.height()); // Render the image. + // TODO(beng): Convert to CanvasSkia gfx::Canvas canvas(prefsize.width(), prefsize.height(), false); button.Paint(&canvas, true); SetDragImageOnDataObject(canvas, prefsize, @@ -68,6 +70,7 @@ void CreateDragImageForFile(const FilePath::StringType& file_name, // Add +2 here to allow room for the halo. const int height = font.height() + icon->height() + kLinkDragImageVPadding + 2; + // TODO(beng): Convert to CanvasSkia gfx::Canvas canvas(width, height, false /* translucent */); // Paint the icon. diff --git a/views/widget/root_view_gtk.cc b/views/widget/root_view_gtk.cc index 75438fb..b2103e1 100644 --- a/views/widget/root_view_gtk.cc +++ b/views/widget/root_view_gtk.cc @@ -7,7 +7,7 @@ #include #include "base/logging.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "views/widget/widget_gtk.h" namespace views { @@ -20,7 +20,7 @@ void RootView::OnPaint(GdkEventExpose* event) { } gfx::Rect scheduled_dirty_rect = GetScheduledPaintRectConstrainedToSize(); gfx::Rect expose_rect = gfx::Rect(event->area); - gfx::CanvasPaint canvas(event); + gfx::CanvasSkiaPaint canvas(event); bool invoked_process_paint = false; if (!canvas.is_empty()) { canvas.set_composite_alpha(widget->is_transparent()); diff --git a/views/widget/root_view_win.cc b/views/widget/root_view_win.cc index 49717e1..3c9706d 100644 --- a/views/widget/root_view_win.cc +++ b/views/widget/root_view_win.cc @@ -9,7 +9,8 @@ #include "app/os_exchange_data_provider_win.h" #include "base/base_drag_source.h" #include "base/logging.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_2.h" +#include "gfx/canvas_skia.h" namespace views { diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc index 332365a..7705784 100644 --- a/views/widget/widget_win.cc +++ b/views/widget/widget_win.cc @@ -10,6 +10,7 @@ #include "base/string_util.h" #include "base/win_util.h" #include "gfx/canvas.h" +#include "gfx/canvas_skia.h" #include "gfx/native_theme_win.h" #include "gfx/path.h" #include "views/accessibility/view_accessibility.h" diff --git a/views/window/window_win.cc b/views/window/window_win.cc index c9efbff..4381e74 100644 --- a/views/window/window_win.cc +++ b/views/window/window_win.cc @@ -13,7 +13,7 @@ #include "app/win_util.h" #include "base/i18n/rtl.h" #include "base/win_util.h" -#include "gfx/canvas_paint.h" +#include "gfx/canvas_skia_paint.h" #include "gfx/font.h" #include "gfx/icon_util.h" #include "gfx/path.h" @@ -938,12 +938,13 @@ void WindowWin::OnNCPaint(HRGN rgn) { root_view->SchedulePaint(gfx::Rect(dirty_region), false); - // gfx::CanvasPaints destructor does the actual painting. As such, wrap the - // following in a block to force paint to occur so that we can release the dc. + // gfx::CanvasSkiaPaint's destructor does the actual painting. As such, wrap + // the following in a block to force paint to occur so that we can release + // the dc. { - gfx::CanvasPaint canvas(dc, opaque(), dirty_region.left, dirty_region.top, - dirty_region.Width(), dirty_region.Height()); - + gfx::CanvasSkiaPaint canvas(dc, opaque(), dirty_region.left, + dirty_region.top, dirty_region.Width(), + dirty_region.Height()); root_view->ProcessPaint(&canvas); } -- cgit v1.1