Home | History | Annotate | Download | only in image
      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