1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/gfx/image/cairo_cached_surface.h" 6 7 #include <gtk/gtk.h> 8 9 #include "base/basictypes.h" 10 #include "base/logging.h" 11 12 namespace gfx { 13 14 CairoCachedSurface::CairoCachedSurface() : pixbuf_(NULL) { 15 } 16 17 CairoCachedSurface::~CairoCachedSurface() { 18 Reset(); 19 } 20 21 void CairoCachedSurface::Reset() { 22 for (SurfaceVector::iterator it = surface_map_.begin(); 23 it != surface_map_.end(); ++it) { 24 cairo_surface_destroy(it->second); 25 } 26 surface_map_.clear(); 27 28 if (pixbuf_) { 29 g_object_unref(pixbuf_); 30 pixbuf_ = NULL; 31 } 32 } 33 34 int CairoCachedSurface::Width() const { 35 return pixbuf_ ? gdk_pixbuf_get_width(pixbuf_) : -1; 36 } 37 38 int CairoCachedSurface::Height() const { 39 return pixbuf_ ? gdk_pixbuf_get_height(pixbuf_) : -1; 40 } 41 42 void CairoCachedSurface::UsePixbuf(GdkPixbuf* pixbuf) { 43 if (pixbuf) 44 g_object_ref(pixbuf); 45 46 Reset(); 47 48 pixbuf_ = pixbuf; 49 } 50 51 void CairoCachedSurface::SetSource(cairo_t* cr, GtkWidget* widget, 52 int x, int y) const { 53 SetSource(cr, gtk_widget_get_display(widget), x, y); 54 } 55 56 void CairoCachedSurface::SetSource(cairo_t* cr, GdkDisplay* display, 57 int x, int y) const { 58 DCHECK(pixbuf_); 59 DCHECK(cr); 60 DCHECK(display); 61 62 cairo_surface_t* surface = GetSurfaceFor(cr, display); 63 cairo_set_source_surface(cr, surface, x, y); 64 } 65 66 void CairoCachedSurface::MaskSource(cairo_t* cr, GtkWidget* widget, 67 int x, int y) const { 68 MaskSource(cr, gtk_widget_get_display(widget), x, y); 69 } 70 71 void CairoCachedSurface::MaskSource(cairo_t* cr, GdkDisplay* display, 72 int x, int y) const { 73 DCHECK(pixbuf_); 74 DCHECK(cr); 75 DCHECK(display); 76 77 cairo_surface_t* surface = GetSurfaceFor(cr, display); 78 cairo_mask_surface(cr, surface, x, y); 79 } 80 81 cairo_surface_t* CairoCachedSurface::GetSurfaceFor(cairo_t* cr, 82 GdkDisplay* display) const { 83 for (SurfaceVector::const_iterator it = surface_map_.begin(); 84 it != surface_map_.end(); ++it) { 85 if (display == it->first) { 86 return it->second; 87 } 88 } 89 90 // First time here since last UsePixbuf call. Generate the surface. 91 cairo_surface_t* target = cairo_get_target(cr); 92 cairo_surface_t* out = cairo_surface_create_similar( 93 target, 94 CAIRO_CONTENT_COLOR_ALPHA, 95 gdk_pixbuf_get_width(pixbuf_), 96 gdk_pixbuf_get_height(pixbuf_)); 97 98 DCHECK(out); 99 100 cairo_t* copy_cr = cairo_create(out); 101 gdk_cairo_set_source_pixbuf(copy_cr, pixbuf_, 0, 0); 102 cairo_paint(copy_cr); 103 cairo_destroy(copy_cr); 104 105 surface_map_.push_back(std::make_pair(display, out)); 106 return out; 107 } 108 109 } // namespace gfx 110