Back to index

nux  3.0.0
CairoWrapper.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 Canonical Ltd
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License version 3 as
00006  * published by the Free Software Foundation.
00007  *
00008  * This program is distributed in the hope that it will be useful,
00009  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  * GNU General Public License for more details.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  * Authored by: Mirco Müller <mirco.mueller@canonical.com
00017  */
00018 
00019 
00020 #include "CairoWrapper.h"
00021 
00022 #include <iostream>
00023 
00024 namespace nux
00025 {
00026   struct CairoWrapper::Impl
00027   {
00028     Impl(CairoWrapper* parent, Geometry const& geo, DrawCanvasCallback callback);
00029     ~Impl();
00030 
00031     bool CreateBitmap ();
00032     bool Invalidate (Geometry const& geom);
00033     void SetDrawCanvasCallback (DrawCanvasCallback callback);
00034     bool DumpToFile (std::string const& filename);
00035     bool Recreate ();
00036     void DeleteResources();
00037 
00038     CairoWrapper*      parent_;
00039     Geometry           geometry_;
00040     DrawCanvasCallback draw_canvas_callback_;
00041     cairo_t*           cr_;
00042     cairo_surface_t*   surface_;
00043     NBitmapData*       bitmap_;
00044     BaseTexture*       texture_;
00045   };
00046 
00047   CairoWrapper::Impl::Impl(CairoWrapper* parent, Geometry const& geo, DrawCanvasCallback callback)
00048     : parent_(parent)
00049     , geometry_(geo)
00050     , draw_canvas_callback_(callback)
00051     , cr_(0)
00052     , surface_(0)
00053     , bitmap_(0)
00054     , texture_(0)
00055   {
00056   }
00057 
00058   CairoWrapper::Impl::~Impl()
00059   {
00060     DeleteResources();
00061   }
00062 
00063   void CairoWrapper::Impl::DeleteResources()
00064   {
00065     if (surface_)
00066     {
00067       cairo_surface_destroy (surface_);
00068       surface_ = 0;
00069     }
00070 
00071     if (cr_)
00072     {
00073       cairo_destroy (cr_);
00074       cr_ = 0;
00075     }
00076 
00077     if (bitmap_)
00078     {
00079       delete bitmap_;
00080       bitmap_ = 0;
00081     }
00082 
00083     if (texture_)
00084     {
00085       texture_->UnReference ();
00086       texture_ = 0;
00087     }
00088   }
00089 
00090   bool CairoWrapper::Impl::Recreate ()
00091   {
00092     DeleteResources();
00093 
00094     surface_ = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
00095                                            geometry_.width,
00096                                            geometry_.height);
00097 
00098     if (cairo_surface_status (surface_) != CAIRO_STATUS_SUCCESS)
00099     {
00100       g_debug ("Could not create image-surface!");
00101       return false;
00102     }
00103 
00104     cr_ = cairo_create (surface_);
00105     if (cairo_status (cr_) != CAIRO_STATUS_SUCCESS)
00106     {
00107       cairo_surface_destroy (surface_);
00108       g_debug ("Could not create cairo-context!");
00109       return false;
00110     }
00111 
00112     if (!draw_canvas_callback_)
00113       return false;
00114 
00115     draw_canvas_callback_ (geometry_, cr_);
00116 
00117     CreateBitmap ();
00118     NBitmapData* bitmap = parent_->GetBitmap ();
00119     if (texture_)
00120         texture_->UnReference ();
00121 
00122     if (GetGraphicsDisplay()->GetGraphicsEngine() == 0)
00123       return false;
00124 
00125     texture_ = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture();
00126     texture_->Update (bitmap);
00127 
00128     return true;
00129   }
00130 
00131   bool CairoWrapper::Impl::CreateBitmap ()
00132   {
00133     if (geometry_.width < 1 || geometry_.height < 1)
00134     {
00135       g_debug ("Width or height invalid!");
00136       return false;
00137     }
00138 
00139     if (bitmap_)
00140     {
00141       delete bitmap_;
00142       bitmap_ = 0;
00143     }
00144 
00145     BitmapFormat bitmap_format = BITFMT_B8G8R8A8;
00146     bitmap_ = new NTextureData (bitmap_format,
00147                                 geometry_.width,
00148                                 geometry_.height,
00149                                 1);
00150     unsigned char* ptr = cairo_image_surface_get_data (surface_);
00151     int stride = cairo_image_surface_get_stride (surface_);
00152 
00153     if (ptr == 0 || stride == 0)
00154     {
00155       g_debug ("Invalid surface!");
00156       return false;
00157     }
00158 
00159     for (int j = 0; j < geometry_.height; j++)
00160     {
00161       Memcpy (bitmap_->GetSurface (0).GetPtrRawData() + j * bitmap_->GetSurface (0).GetPitch(),
00162                 (const void *) (&ptr[j * stride]),
00163                 geometry_.width * GPixelFormats[bitmap_format].NumComponents);
00164     }
00165 
00166     return true;
00167   }
00168 
00169   void CairoWrapper::Impl::SetDrawCanvasCallback (DrawCanvasCallback callback)
00170   {
00171     if (!callback)
00172       return;
00173 
00174     draw_canvas_callback_ = callback;
00175     Recreate (); 
00176   }
00177 
00178   bool CairoWrapper::Impl::DumpToFile (std::string const& filename)
00179   {
00180     if (!surface_)
00181       Recreate();
00182 
00183     cairo_surface_write_to_png (surface_, filename.c_str ());
00184 
00185     return true;
00186   }
00187 
00188   bool CairoWrapper::Impl::Invalidate (Geometry const& geom)
00189   {
00190     if (geometry_.width  == geom.width && geometry_.height == geom.height)
00191       return false;
00192 
00193     geometry_.x      = geom.x;
00194     geometry_.y      = geom.y;
00195     geometry_.width  = geom.width;
00196     geometry_.height = geom.height;
00197 
00198     DeleteResources(); 
00199 
00200     return true;
00201   }
00202 
00203   CairoWrapper::CairoWrapper (Geometry const& geom, DrawCanvasCallback callback)
00204     : pimpl(new Impl(this, geom, callback))
00205   {
00206     Recreate ();
00207   }
00208 
00209   CairoWrapper::~CairoWrapper ()
00210   {
00211     delete pimpl;
00212   }
00213 
00214   bool CairoWrapper::Invalidate (Geometry const& geom)
00215   {
00216     return pimpl->Invalidate(geom);
00217   }
00218 
00219   void CairoWrapper::SetDrawCanvasCallback (DrawCanvasCallback callback)
00220   {
00221     pimpl->SetDrawCanvasCallback(callback);
00222   }
00223 
00224   bool CairoWrapper::DumpToFile (std::string const& filename)
00225   {
00226     return pimpl->DumpToFile(filename);
00227   }
00228 
00229   bool CairoWrapper::Recreate ()
00230   {
00231     return pimpl->Recreate();
00232   }
00233 
00234   NBitmapData* CairoWrapper::GetBitmap () const
00235   {
00236     if (!pimpl->bitmap_)
00237       pimpl->Recreate();
00238 
00239     return pimpl->bitmap_;
00240   }
00241 
00242   BaseTexture* CairoWrapper::GetTexture () const
00243   {
00244     if (!pimpl->texture_)
00245       pimpl->Recreate();
00246 
00247     return pimpl->texture_;
00248   }
00249 
00250   cairo_surface_t* CairoWrapper::GetCairoSurface () const
00251   {
00252     if (!pimpl->surface_)
00253       pimpl->Recreate();
00254 
00255     return pimpl->surface_;
00256   }
00257 
00258   cairo_t* CairoWrapper::GetCairoContext () const
00259   {
00260     if (!pimpl->cr_)
00261       pimpl->Recreate();
00262 
00263     return pimpl->cr_;
00264   }
00265 }