Commit 0d9a805b authored by erg@chromium.org's avatar erg@chromium.org

GTK: Port omnibox drawing from GdkGC interface to cairo.

GdkGC is deprecated and will be removed in gtk3 and cairo should be faster anyway. This uses the new CairoCachedSurface in gfx::Image.

BUG=79722
TEST=none


Review URL: http://codereview.chromium.org/8781001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@112839 0039d316-1c4b-4281-b951-d872f2087c98
parent 92fd95bb
...@@ -220,6 +220,20 @@ void ThemeService::Init(Profile* profile) { ...@@ -220,6 +220,20 @@ void ThemeService::Init(Profile* profile) {
LoadThemePrefs(); LoadThemePrefs();
} }
const gfx::Image* ThemeService::GetImageNamed(int id) const {
DCHECK(CalledOnValidThread());
const gfx::Image* image = NULL;
if (theme_pack_.get())
image = theme_pack_->GetImageNamed(id);
if (!image)
image = &rb_.GetNativeImageNamed(id);
return image;
}
SkBitmap* ThemeService::GetBitmapNamed(int id) const { SkBitmap* ThemeService::GetBitmapNamed(int id) const {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
......
...@@ -28,6 +28,10 @@ namespace color_utils { ...@@ -28,6 +28,10 @@ namespace color_utils {
struct HSL; struct HSL;
} }
namespace gfx {
class Image;
}
namespace ui { namespace ui {
class ResourceBundle; class ResourceBundle;
} }
...@@ -140,6 +144,13 @@ class ThemeService : public base::NonThreadSafe, ...@@ -140,6 +144,13 @@ class ThemeService : public base::NonThreadSafe,
REPEAT = 3 REPEAT = 3
} Tiling; } Tiling;
// Returns a cross platform image for an id.
//
// TODO(erg): Make this a virtual, exposed through ui::ThemeProvider and the
// main way to get theme properties out of the theme provider since it's
// cross platform.
const gfx::Image* GetImageNamed(int id) const;
// ui::ThemeProvider implementation. // ui::ThemeProvider implementation.
virtual void Init(Profile* profile) OVERRIDE; virtual void Init(Profile* profile) OVERRIDE;
virtual SkBitmap* GetBitmapNamed(int id) const OVERRIDE; virtual SkBitmap* GetBitmapNamed(int id) const OVERRIDE;
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/gfx/font.h" #include "ui/gfx/font.h"
#include "ui/gfx/gtk_util.h" #include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/cairo_cached_surface.h"
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
#include "ui/gfx/skia_utils_gtk.h" #include "ui/gfx/skia_utils_gtk.h"
...@@ -104,13 +106,13 @@ gfx::Rect GetRectForLine(size_t line, int width) { ...@@ -104,13 +106,13 @@ gfx::Rect GetRectForLine(size_t line, int width) {
} }
// Helper for drawing an entire pixbuf without dithering. // Helper for drawing an entire pixbuf without dithering.
void DrawFullPixbuf(GdkDrawable* drawable, GdkGC* gc, GdkPixbuf* pixbuf, void DrawFullImage(cairo_t* cr, GtkWidget* widget, const gfx::Image* image,
gint dest_x, gint dest_y) { gint dest_x, gint dest_y) {
gdk_draw_pixbuf(drawable, gc, pixbuf, gfx::CairoCachedSurface* surface = image->ToCairo();
0, 0, // Source. surface->SetSource(cr, widget, dest_x, dest_y);
dest_x, dest_y, // Dest. cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
-1, -1, // Width/height (auto). cairo_rectangle(cr, dest_x, dest_y, surface->Width(), surface->Height());
GDK_RGB_DITHER_NONE, 0, 0); // Don't dither. cairo_fill(cr);
} }
// TODO(deanm): Find some better home for this, and make it more efficient. // TODO(deanm): Find some better home for this, and make it more efficient.
...@@ -338,8 +340,8 @@ OmniboxPopupViewGtk::~OmniboxPopupViewGtk() { ...@@ -338,8 +340,8 @@ OmniboxPopupViewGtk::~OmniboxPopupViewGtk() {
g_object_unref(layout_); g_object_unref(layout_);
gtk_widget_destroy(window_); gtk_widget_destroy(window_);
for (PixbufMap::iterator it = pixbufs_.begin(); it != pixbufs_.end(); ++it) for (ImageMap::iterator it = images_.begin(); it != images_.end(); ++it)
g_object_unref(it->second); delete it->second;
} }
bool OmniboxPopupViewGtk::IsOpen() const { bool OmniboxPopupViewGtk::IsOpen() const {
...@@ -483,13 +485,13 @@ void OmniboxPopupViewGtk::AcceptLine(size_t line, ...@@ -483,13 +485,13 @@ void OmniboxPopupViewGtk::AcceptLine(size_t line,
is_keyword_hint ? string16() : keyword); is_keyword_hint ? string16() : keyword);
} }
GdkPixbuf* OmniboxPopupViewGtk::IconForMatch(const AutocompleteMatch& match, const gfx::Image* OmniboxPopupViewGtk::IconForMatch(
bool selected) { const AutocompleteMatch& match, bool selected) {
const SkBitmap* bitmap = model_->GetIconIfExtensionMatch(match); const SkBitmap* bitmap = model_->GetIconIfExtensionMatch(match);
if (bitmap) { if (bitmap) {
if (!ContainsKey(pixbufs_, bitmap)) if (!ContainsKey(images_, bitmap))
pixbufs_[bitmap] = gfx::GdkPixbufFromSkBitmap(bitmap); images_[bitmap] = new gfx::Image(bitmap);
return pixbufs_[bitmap]; return images_[bitmap];
} }
int icon = match.starred ? int icon = match.starred ?
...@@ -517,8 +519,7 @@ GdkPixbuf* OmniboxPopupViewGtk::IconForMatch(const AutocompleteMatch& match, ...@@ -517,8 +519,7 @@ GdkPixbuf* OmniboxPopupViewGtk::IconForMatch(const AutocompleteMatch& match,
} }
} }
// TODO(estade): Do we want to flip these for RTL? (Windows doesn't). return theme_service_->GetImageNamed(icon);
return theme_service_->GetPixbufNamed(icon);
} }
gboolean OmniboxPopupViewGtk::HandleMotion(GtkWidget* widget, gboolean OmniboxPopupViewGtk::HandleMotion(GtkWidget* widget,
...@@ -583,20 +584,18 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget, ...@@ -583,20 +584,18 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget,
if (window_rect.width() < (kIconAreaWidth * 3)) if (window_rect.width() < (kIconAreaWidth * 3))
return TRUE; return TRUE;
GdkDrawable* drawable = GDK_DRAWABLE(event->window); cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window));
GdkGC* gc = gdk_gc_new(drawable); gdk_cairo_rectangle(cr, &event->area);
cairo_clip(cr);
// kBorderColor is unallocated, so use the GdkRGB routine.
gdk_gc_set_rgb_fg_color(gc, &border_color_);
// This assert is kinda ugly, but it would be more currently unneeded work // This assert is kinda ugly, but it would be more currently unneeded work
// to support painting a border that isn't 1 pixel thick. There is no point // to support painting a border that isn't 1 pixel thick. There is no point
// in writing that code now, and explode if that day ever comes. // in writing that code now, and explode if that day ever comes.
COMPILE_ASSERT(kBorderThickness == 1, border_1px_implied); COMPILE_ASSERT(kBorderThickness == 1, border_1px_implied);
// Draw the 1px border around the entire window. // Draw the 1px border around the entire window.
gdk_draw_rectangle(drawable, gc, FALSE, gdk_cairo_set_source_color(cr, &border_color_);
0, 0, cairo_rectangle(cr, 0, 0, window_rect.width(), window_rect.height());
window_rect.width() - 1, window_rect.height() - 1); cairo_stroke(cr);
pango_layout_set_height(layout_, kHeightPerResult * PANGO_SCALE); pango_layout_set_height(layout_, kHeightPerResult * PANGO_SCALE);
...@@ -610,20 +609,20 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget, ...@@ -610,20 +609,20 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget,
bool is_selected = (model_->selected_line() == i); bool is_selected = (model_->selected_line() == i);
bool is_hovered = (model_->hovered_line() == i); bool is_hovered = (model_->hovered_line() == i);
if (is_selected || is_hovered) { if (is_selected || is_hovered) {
gdk_gc_set_rgb_fg_color(gc, is_selected ? &selected_background_color_ : gdk_cairo_set_source_color(cr, is_selected ? &selected_background_color_ :
&hovered_background_color_); &hovered_background_color_);
// This entry is selected or hovered, fill a rect with the color. // This entry is selected or hovered, fill a rect with the color.
gdk_draw_rectangle(drawable, gc, TRUE, cairo_rectangle(cr, line_rect.x(), line_rect.y(),
line_rect.x(), line_rect.y(), line_rect.width(), line_rect.height());
line_rect.width(), line_rect.height()); cairo_fill(cr);
} }
int icon_start_x = ltr ? kIconLeftPadding : int icon_start_x = ltr ? kIconLeftPadding :
(line_rect.width() - kIconLeftPadding - kIconWidth); (line_rect.width() - kIconLeftPadding - kIconWidth);
// Draw the icon for this result. // Draw the icon for this result.
DrawFullPixbuf(drawable, gc, DrawFullImage(cr, widget,
IconForMatch(match, is_selected), IconForMatch(match, is_selected),
icon_start_x, line_rect.y() + kIconTopPadding); icon_start_x, line_rect.y() + kIconTopPadding);
// Draw the results text vertically centered in the results space. // Draw the results text vertically centered in the results space.
// First draw the contents / url, but don't let it take up the whole width // First draw the contents / url, but don't let it take up the whole width
...@@ -655,10 +654,13 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget, ...@@ -655,10 +654,13 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget,
int content_y = std::max(line_rect.y(), int content_y = std::max(line_rect.y(),
line_rect.y() + ((kHeightPerResult - actual_content_height) / 2)); line_rect.y() + ((kHeightPerResult - actual_content_height) / 2));
gdk_draw_layout(drawable, gc, cairo_save(cr);
ltr ? kIconAreaWidth : cairo_move_to(cr,
ltr ? kIconAreaWidth :
(text_width - actual_content_width), (text_width - actual_content_width),
content_y, layout_); content_y);
pango_cairo_show_layout(cr, layout_);
cairo_restore(cr);
if (has_description) { if (has_description) {
pango_layout_set_width(layout_, pango_layout_set_width(layout_,
...@@ -677,15 +679,18 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget, ...@@ -677,15 +679,18 @@ gboolean OmniboxPopupViewGtk::HandleExpose(GtkWidget* widget,
std::string(" - ")); std::string(" - "));
gint actual_description_width; gint actual_description_width;
pango_layout_get_size(layout_, &actual_description_width, NULL); pango_layout_get_size(layout_, &actual_description_width, NULL);
gdk_draw_layout(drawable, gc, ltr ?
(kIconAreaWidth + actual_content_width) : cairo_save(cr);
(text_width - actual_content_width - cairo_move_to(cr, ltr ?
(actual_description_width / PANGO_SCALE)), (kIconAreaWidth + actual_content_width) :
content_y, layout_); (text_width - actual_content_width -
(actual_description_width / PANGO_SCALE)),
content_y);
pango_cairo_show_layout(cr, layout_);
cairo_restore(cr);
} }
} }
g_object_unref(gc); cairo_destroy(cr);
return TRUE; return TRUE;
} }
...@@ -28,6 +28,10 @@ class GtkThemeService; ...@@ -28,6 +28,10 @@ class GtkThemeService;
class OmniboxView; class OmniboxView;
class SkBitmap; class SkBitmap;
namespace gfx {
class Image;
}
class OmniboxPopupViewGtk : public AutocompletePopupView, class OmniboxPopupViewGtk : public AutocompletePopupView,
public content::NotificationObserver { public content::NotificationObserver {
public: public:
...@@ -75,7 +79,7 @@ class OmniboxPopupViewGtk : public AutocompletePopupView, ...@@ -75,7 +79,7 @@ class OmniboxPopupViewGtk : public AutocompletePopupView,
// Accept a line of the results, for example, when the user clicks a line. // Accept a line of the results, for example, when the user clicks a line.
void AcceptLine(size_t line, WindowOpenDisposition disposition); void AcceptLine(size_t line, WindowOpenDisposition disposition);
GdkPixbuf* IconForMatch(const AutocompleteMatch& match, bool selected); const gfx::Image* IconForMatch(const AutocompleteMatch& match, bool selected);
CHROMEGTK_CALLBACK_1(OmniboxPopupViewGtk, gboolean, HandleMotion, CHROMEGTK_CALLBACK_1(OmniboxPopupViewGtk, gboolean, HandleMotion,
GdkEventMotion*); GdkEventMotion*);
...@@ -108,8 +112,8 @@ class OmniboxPopupViewGtk : public AutocompletePopupView, ...@@ -108,8 +112,8 @@ class OmniboxPopupViewGtk : public AutocompletePopupView,
// Used to cache GdkPixbufs and map them from the SkBitmaps they were created // Used to cache GdkPixbufs and map them from the SkBitmaps they were created
// from. // from.
typedef std::map<const SkBitmap*, GdkPixbuf*> PixbufMap; typedef std::map<const SkBitmap*, gfx::Image*> ImageMap;
PixbufMap pixbufs_; ImageMap images_;
// A list of colors which we should use for drawing the popup. These change // A list of colors which we should use for drawing the popup. These change
// between gtk and normal mode. // between gtk and normal mode.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment