Index: ui/gfx/image/cairo_cached_surface.cc |
diff --git a/ui/gfx/image/cairo_cached_surface.cc b/ui/gfx/image/cairo_cached_surface.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2de4a3210b3d4c38cf08e3fe4a07cac1d509064b |
--- /dev/null |
+++ b/ui/gfx/image/cairo_cached_surface.cc |
@@ -0,0 +1,109 @@ |
+// Copyright (c) 2011 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 "ui/gfx/image/cairo_cached_surface.h" |
+ |
+#include <gtk/gtk.h> |
+ |
+#include "base/basictypes.h" |
+#include "base/logging.h" |
+ |
+namespace gfx { |
+ |
+CairoCachedSurface::CairoCachedSurface() : pixbuf_(NULL) { |
+} |
+ |
+CairoCachedSurface::~CairoCachedSurface() { |
+ Reset(); |
+} |
+ |
+void CairoCachedSurface::Reset() { |
+ for (SurfaceVector::iterator it = surface_map_.begin(); |
+ it != surface_map_.end(); ++it) { |
+ cairo_surface_destroy(it->second); |
+ } |
+ surface_map_.clear(); |
+ |
+ if (pixbuf_) { |
+ g_object_unref(pixbuf_); |
+ pixbuf_ = NULL; |
+ } |
+} |
+ |
+int CairoCachedSurface::Width() const { |
+ return pixbuf_ ? gdk_pixbuf_get_width(pixbuf_) : -1; |
+} |
+ |
+int CairoCachedSurface::Height() const { |
+ return pixbuf_ ? gdk_pixbuf_get_height(pixbuf_) : -1; |
+} |
+ |
+void CairoCachedSurface::UsePixbuf(GdkPixbuf* pixbuf) { |
+ if (pixbuf) |
+ g_object_ref(pixbuf); |
+ |
+ Reset(); |
+ |
+ pixbuf_ = pixbuf; |
+} |
+ |
+void CairoCachedSurface::SetSource(cairo_t* cr, GtkWidget* widget, |
+ int x, int y) const { |
+ SetSource(cr, gtk_widget_get_display(widget), x, y); |
+} |
+ |
+void CairoCachedSurface::SetSource(cairo_t* cr, GdkDisplay* display, |
+ int x, int y) const { |
+ DCHECK(pixbuf_); |
+ DCHECK(cr); |
+ DCHECK(display); |
+ |
+ cairo_surface_t* surface = GetSurfaceFor(cr, display); |
+ cairo_set_source_surface(cr, surface, x, y); |
+} |
+ |
+void CairoCachedSurface::MaskSource(cairo_t* cr, GtkWidget* widget, |
+ int x, int y) const { |
+ MaskSource(cr, gtk_widget_get_display(widget), x, y); |
+} |
+ |
+void CairoCachedSurface::MaskSource(cairo_t* cr, GdkDisplay* display, |
+ int x, int y) const { |
+ DCHECK(pixbuf_); |
+ DCHECK(cr); |
+ DCHECK(display); |
+ |
+ cairo_surface_t* surface = GetSurfaceFor(cr, display); |
+ cairo_mask_surface(cr, surface, x, y); |
+} |
+ |
+cairo_surface_t* CairoCachedSurface::GetSurfaceFor(cairo_t* cr, |
+ GdkDisplay* display) const { |
+ for (SurfaceVector::const_iterator it = surface_map_.begin(); |
+ it != surface_map_.end(); ++it) { |
+ if (display == it->first) { |
+ return it->second; |
+ } |
+ } |
+ |
+ // First time here since last UsePixbuf call. Generate the surface. |
+ cairo_surface_t* target = cairo_get_target(cr); |
+ cairo_surface_t* out = cairo_surface_create_similar( |
+ target, |
+ CAIRO_CONTENT_COLOR_ALPHA, |
+ gdk_pixbuf_get_width(pixbuf_), |
+ gdk_pixbuf_get_height(pixbuf_)); |
+ |
+ DCHECK(out); |
+ |
+ cairo_t* copy_cr = cairo_create(out); |
+ gdk_cairo_set_source_pixbuf(copy_cr, pixbuf_, 0, 0); |
+ cairo_paint(copy_cr); |
+ cairo_destroy(copy_cr); |
+ |
+ surface_map_.push_back(std::make_pair(display, out)); |
+ return out; |
+} |
+ |
+} // namespace gfx |