| // 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 |