nux-1.16.0
|
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 t_u8* 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& gfxContext, 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 gfxContext.PushClippingRectangle (geom); 00170 00171 GetGraphicsEngine().GetRenderStates().SetBlend (false); 00172 00173 TexCoordXForm texxform; 00174 texxform.SetWrap (TEXWRAP_CLAMP, TEXWRAP_CLAMP); 00175 texxform.SetTexCoordType (TexCoordXForm::OFFSET_COORD); 00176 00177 gfxContext.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 gfxContext.PopClippingRectangle (); 00186 } 00187 00188 void Canvas::DrawContent (GraphicsEngine& gfxContext, bool forceDraw) 00189 { 00190 } 00191 00192 long Canvas::ProcessEvent (IEvent& event, 00193 long traverseInfo, 00194 long processEventInfo) 00195 { 00196 long ret = traverseInfo; 00197 00198 return ret; 00199 } 00200 00201 void Canvas::Invalidate () 00202 { 00203 _invalid = true; 00204 } 00205 00206 void Canvas::PreLayoutManagement () 00207 { 00208 View::PreLayoutManagement (); 00209 } 00210 00211 long Canvas::PostLayoutManagement (long layoutResult) 00212 { 00213 long result = View::PostLayoutManagement (layoutResult); 00214 00215 return result; 00216 } 00217 }