Back to index

nux  3.0.0
Canvas.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 "Canvas.h"
00021 
00022 namespace nux
00023 {
00024   Canvas::Canvas (NUX_FILE_LINE_DECL) : View (NUX_FILE_LINE_PARAM)
00025   {
00026     _surface     = NULL;
00027     _cr          = NULL;
00028     _last_width  = 0;
00029     _last_height = 0;
00030     _invalid     = true;
00031     _texture     = NULL;
00032   }
00033 
00034   Canvas::~Canvas ()
00035   {
00036     cairo_surface_destroy (_surface);
00037     cairo_destroy (_cr);
00038     _texture->UnReference ();
00039   }
00040 
00041   void Canvas::Recreate ()
00042   {
00043     if (_surface)
00044       cairo_surface_destroy (_surface);
00045 
00046     if (_cr)
00047       cairo_destroy (_cr);
00048 
00049     if (_last_width < 1 || _last_height < 1) {
00050       g_debug ("Width or height of view invalid!");
00051       return;
00052     }
00053 
00054     _surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
00055                                            _last_width,
00056                                            _last_height);
00057 
00058     if (cairo_surface_status (_surface) != CAIRO_STATUS_SUCCESS) {
00059       g_debug ("Could not create image-surface!");
00060       return;
00061     }
00062 
00063     _cr = cairo_create (_surface);
00064     if (cairo_status (_cr) != CAIRO_STATUS_SUCCESS) {
00065       cairo_surface_destroy (_surface);
00066       g_debug ("Could not create cairo-context!");
00067       return;
00068     }
00069 
00070     cairo_set_operator (_cr, CAIRO_OPERATOR_CLEAR);
00071     cairo_paint (_cr);
00072     _invalid = false;
00073   }
00074 
00075   NBitmapData* Canvas::GetBitmap ()
00076   {
00077     if (_last_width < 1 || _last_height < 1) {
00078       g_debug ("Width or height invalid!");
00079       return NULL;
00080     }
00081 
00082     BitmapFormat  bitmap_format = BITFMT_B8G8R8A8;
00083     NTextureData* bitmap_data   = new NTextureData (bitmap_format,
00084                                                     _last_width,
00085                                                     _last_height,
00086                                                     1);
00087     unsigned char*  ptr           = cairo_image_surface_get_data (_surface);
00088     int             stride        = cairo_image_surface_get_stride (_surface);
00089 
00090     if (ptr == NULL || stride == 0) {
00091       g_debug ("Invalid surface!");
00092 
00093       delete bitmap_data;
00094       return NULL;
00095     }
00096 
00097     for (int j = 0; j < _last_height; j++) {
00098       Memcpy (bitmap_data->GetSurface (0).GetPtrRawData() + j * bitmap_data->GetSurface (0).GetPitch(),
00099                 (const void *) (&ptr[j * stride]),
00100                 _last_width * GPixelFormats[bitmap_format].NumComponents);
00101     }
00102 
00103     return bitmap_data;
00104   }
00105 
00106   cairo_surface_t* Canvas::GetCairoSurface ()
00107   {
00108     return _surface;
00109   }
00110 
00111   cairo_t* Canvas::GetCairoContext ()
00112   {
00113     return _cr;
00114   }
00115 
00116   int Canvas::GetLastWidth ()
00117   {
00118     return _last_width;
00119   }
00120 
00121   int Canvas::GetLastHeight ()
00122   {
00123     return _last_height;
00124   }
00125 
00126   // this is really just a stub... Canvas::Paint() being declared as virtual is
00127   // meant to be overwritten by a derived class anyway in real-world scenario
00128   // whatever needs to be drawn (and adapt to size) happens here in Paint()
00129   void Canvas::Paint ()
00130   {
00131     cairo_t* cr = GetCairoContext ();
00132 
00133     if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
00134       return;
00135 
00136     cairo_scale (cr, 1.0, 1.0);
00137     cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
00138     cairo_rectangle (cr,
00139                      0.0f,
00140                      0.0f,
00141                      (double) GetLastWidth (),
00142                      (double) GetLastHeight ());
00143     cairo_set_source_rgba (cr, 1.0f, 0.0f, 0.0f, 1.0f);
00144     cairo_fill_preserve (cr);
00145     cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 1.0f);
00146     cairo_stroke (cr);
00147     //cairo_surface_write_to_png (GetCairoSurface (), "/tmp/surf-debug.png");      
00148   }
00149 
00150   void Canvas::Draw (GraphicsEngine& graphics_engine, bool forceDraw)
00151   {
00152     Geometry geom = GetGeometry ();
00153 
00154     // see if the (cairo-drawn) texture needs to be updated
00155     if (_invalid || _last_width != geom.width || _last_height != geom.height) {
00156       _last_width = geom.width;
00157       _last_height = geom.height;
00158       Recreate ();
00159       Paint ();
00160       NBitmapData* bitmap = GetBitmap ();
00161       if (_texture)
00162         _texture->UnReference ();
00163       _texture = GetGraphicsDisplay()->GetGpuDevice()->CreateSystemCapableTexture ();
00164       _texture->Update (bitmap);
00165       delete bitmap;
00166     }
00167 
00168     // draw the texture on screen
00169     graphics_engine.PushClippingRectangle (geom);
00170 
00171     GetWindowThread()->GetGraphicsEngine().GetRenderStates().SetBlend (false);
00172 
00173     TexCoordXForm texxform;
00174     texxform.SetWrap(TEXWRAP_CLAMP, TEXWRAP_CLAMP);
00175     texxform.SetTexCoordType(TexCoordXForm::OFFSET_COORD);
00176 
00177     graphics_engine.QRP_1Tex(geom.x,
00178                          geom.y,
00179                          geom.width,
00180                          geom.height,
00181                          _texture->GetDeviceTexture (),
00182                          texxform,
00183                          Color (1.0f, 1.0f, 1.0f, 1.0f));
00184 
00185     graphics_engine.PopClippingRectangle();
00186   }
00187 
00188   void Canvas::DrawContent(GraphicsEngine& graphics_engine, bool forceDraw)
00189   {
00190   }
00191 
00192   void Canvas::Invalidate()
00193   {
00194     _invalid = true;
00195   }
00196 
00197   void Canvas::PreLayoutManagement()
00198   {
00199     View::PreLayoutManagement();
00200   }
00201 
00202   long Canvas::PostLayoutManagement(long layoutResult)
00203   {
00204     long result = View::PostLayoutManagement(layoutResult);
00205 
00206     return result;
00207   }
00208 }