1 /* === S Y N F I G ========================================================= */ 2 /*! \file surface.h 3 ** \brief Surface and Pen Definitions 4 ** 5 ** $Id$ 6 ** 7 ** \legal 8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley 9 ** Copyright (c) 2012-2013 Carlos López 10 ** 11 ** This package is free software; you can redistribute it and/or 12 ** modify it under the terms of the GNU General Public License as 13 ** published by the Free Software Foundation; either version 2 of 14 ** the License, or (at your option) any later version. 15 ** 16 ** This package is distributed in the hope that it will be useful, 17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 ** General Public License for more details. 20 ** \endlegal 21 */ 22 /* ========================================================================= */ 23 24 /* === S T A R T =========================================================== */ 25 26 #ifndef __SYNFIG_SURFACE_H 27 #define __SYNFIG_SURFACE_H 28 29 /* === H E A D E R S ======================================================= */ 30 31 #include "color.h" 32 #include "renddesc.h" 33 #include <ETL/pen> 34 #include <ETL/surface> 35 #include <ETL/handle> 36 37 #include "cairo.h" 38 39 /* === M A C R O S ========================================================= */ 40 41 /* === T Y P E D E F S ===================================================== */ 42 43 /* === C L A S S E S & S T R U C T S ======================================= */ 44 45 namespace synfig { 46 47 class Target; 48 class Target_Scanline; 49 class Target_Cairo; 50 class Target_Tile; 51 52 class ColorPrep 53 { 54 public: cook_static(Color x)55 static ColorAccumulator cook_static(Color x) 56 { 57 x.set_r(x.get_r()*x.get_a()); 58 x.set_g(x.get_g()*x.get_a()); 59 x.set_b(x.get_b()*x.get_a()); 60 return x; 61 } uncook_static(ColorAccumulator x)62 static Color uncook_static(ColorAccumulator x) 63 { 64 if(!x.get_a()) 65 return Color::alpha(); 66 67 const float a(1.0f/x.get_a()); 68 69 x.set_r(x.get_r()*a); 70 x.set_g(x.get_g()*a); 71 x.set_b(x.get_b()*a); 72 return x; 73 } 74 cook(Color x)75 ColorAccumulator cook(Color x)const 76 { return cook_static(x); } uncook(ColorAccumulator x)77 Color uncook(ColorAccumulator x)const 78 { return uncook_static(x); } 79 }; 80 81 class CairoColorPrep 82 { 83 public: cook(CairoColor x)84 CairoColor cook(CairoColor x)const 85 { 86 return x.premult_alpha(); 87 } uncook(CairoColor x)88 CairoColor uncook(CairoColor x)const 89 { 90 return x.demult_alpha(); 91 } 92 }; 93 94 /*! \class Surface 95 ** \brief Bitmap Surface 96 ** \todo writeme 97 */ 98 class Surface : public etl::surface<Color, ColorAccumulator, ColorPrep> 99 { 100 public: 101 typedef Color value_type; 102 class alpha_pen; 103 Surface()104 Surface() { } 105 Surface(const size_type::value_type & w,const size_type::value_type & h)106 Surface(const size_type::value_type &w, const size_type::value_type &h): 107 etl::surface<Color, ColorAccumulator,ColorPrep>(w,h) { } 108 Surface(const size_type & s)109 Surface(const size_type &s): 110 etl::surface<Color, ColorAccumulator,ColorPrep>(s) { } 111 112 template <typename _pen> Surface(const _pen & _begin,const _pen & _end)113 Surface(const _pen &_begin, const _pen &_end): 114 etl::surface<Color, ColorAccumulator,ColorPrep>(_begin,_end) { } 115 blit_to(_pen & pen)116 template <class _pen> void blit_to(_pen &pen) 117 { return blit_to(pen,0,0, get_w(),get_h()); } 118 119 template <class _pen> void blit_to(_pen & DEST_PEN,int x,int y,int w,int h)120 blit_to(_pen& DEST_PEN, int x, int y, int w, int h) 121 { 122 etl::surface<Color, ColorAccumulator, ColorPrep>::blit_to(DEST_PEN,x,y,w,h); 123 } 124 125 void clear(); 126 127 void blit_to(alpha_pen& DEST_PEN, int x, int y, int w, int h); 128 }; // END of class Surface 129 130 131 /*! \class CairoSurface 132 ** \brief Generic Cairo backed surface. It allows to create a image surface 133 ** equivalent to the current backend for custom modifications purposes. 134 ** \todo writeme 135 */ 136 class CairoSurface : public etl::surface<CairoColor, CairoColorAccumulator, CairoColorPrep> 137 { 138 // This is the Cairo surface pointer 139 // It is NULL if the not initialized 140 cairo_surface_t *cs_; 141 // This pointer is used when map and unmap the cairo_surface to a cairo_image_surface 142 // see map_cairo_surface() unmap_cairo_surface(); 143 cairo_surface_t *cs_image_; 144 145 public: 146 typedef CairoColor value_type; 147 class alpha_pen; 148 CairoSurface()149 CairoSurface():cs_(NULL), cs_image_(NULL) { } CairoSurface(cairo_surface_t * cs)150 CairoSurface(cairo_surface_t *cs):cs_(NULL), cs_image_(NULL) { set_cairo_surface(cs); } ~CairoSurface()151 ~CairoSurface() { 152 if(cs_!= NULL) cairo_surface_destroy(cs_); 153 if(cs_image_!=NULL) cairo_surface_destroy(cs_image_); } 154 155 156 // If cs_ is set then the set_wh does nothing 157 // If cs_ is not set then set_wh creates a cairo_surface_image on cs_image_ 158 // of size wxh 159 void set_wh(int w, int h, int pitch=0); 160 // Use whits version of set_wh to directly give to the etl::surface the 161 // pointer to data, the width, height and pitch (stride) between rows set_wh(int w,int h,unsigned char * data,int pitch)162 void set_wh(int w, int h, unsigned char* data, int pitch) 163 { etl::surface<CairoColor, CairoColorAccumulator, CairoColorPrep>::set_wh(w, h, data, pitch); } 164 // specialization of etl::surface::blit_to that considers the possibility of 165 // don't blend colors when blend method is straight and alpha is 1.0 166 void blit_to(alpha_pen& DEST_PEN, int x, int y, int w, int h); 167 168 // Use this function to reference one given generic cairo_surface 169 // by this surface class. 170 // When the CairoSurface instance is destructed the reference counter of the 171 // cairo_surface_t shoud be decreased. 172 // It is also possible to detach the cairo surface passing NULL as argument. 173 // If the cairo surface is mapped at the time of call this function, then 174 // it is unmaped first. 175 void set_cairo_surface(cairo_surface_t *cs); 176 // Returns an increased reference pointer of the surface. The receiver is responsible 177 // of destroy the surface once referenced. 178 cairo_surface_t* get_cairo_surface()const; 179 // Returns an increased reference pointer of the image surface. The receiver is responsible 180 // of destroy the surface once referenced. 181 cairo_surface_t* get_cairo_image_surface()const; 182 // Maps cs_ to cs_image_ and extract the *data to etl::surface::data for further modifications 183 // It will flush any remaining painting operation to the cs_ 184 // returns true on success or false if something failed 185 bool map_cairo_image(); 186 // Unmap the cs_image_ to cs_ after external modification has been done via *data 187 // It will mark cs_ as dirty 188 void unmap_cairo_image(); 189 // Returns true if the cairo_surface_t* cs_ is mapped on cs_image_ 190 bool is_mapped()const; 191 192 }; // END of class Surface 193 194 195 #ifndef DOXYGEN_SKIP 196 197 /*! \internal Used by Pen_Alpha */ 198 template <class C, typename A=Color::value_type> 199 struct _BlendFunc 200 { 201 Color::BlendMethod blend_method; 202 blend_method_BlendFunc203 _BlendFunc(typename Color::BlendMethod b= Color::BLEND_COMPOSITE):blend_method(b) { } 204 operator_BlendFunc205 C operator()(const C &a,const C &b,const A &t)const 206 { 207 return C::blend(b,a,t,blend_method); 208 } 209 }; // END of class _BlendFunc 210 211 #endif 212 213 /*! \class Surface::alpha_pen 214 ** \brief Alpha-Blending Pen 215 ** 216 ** This pen works like a normal alpha pen, except that it supports 217 ** a variety of blending methods. Use set_blend_method() to select 218 ** which blending method you want to use. 219 ** The default blending method is Color::BLEND_COMPOSITE. 220 ** \see Color::BlendMethod 221 */ 222 class Surface::alpha_pen : public etl::alpha_pen< etl::generic_pen<Color, ColorAccumulator>, Color::value_type, _BlendFunc<Color> > 223 { 224 public: alpha_pen()225 alpha_pen() { } alpha_pen(const etl::alpha_pen<etl::generic_pen<Color,ColorAccumulator>,Color::value_type,_BlendFunc<Color>> & x)226 alpha_pen(const etl::alpha_pen< etl::generic_pen<Color, ColorAccumulator>, Color::value_type, _BlendFunc<Color> > &x): 227 etl::alpha_pen< etl::generic_pen<Color, ColorAccumulator>, Color::value_type, _BlendFunc<Color> >(x) 228 { } 229 230 alpha_pen(const etl::generic_pen<Color, ColorAccumulator>& pen, const Color::value_type &a = 1, const _BlendFunc<Color> &func = _BlendFunc<Color>()): 231 etl::alpha_pen< etl::generic_pen<Color, ColorAccumulator>, Color::value_type, _BlendFunc<Color> >(pen,a,func) 232 { } 233 234 //! Sets the blend method to that described by \a method set_blend_method(Color::BlendMethod method)235 void set_blend_method(Color::BlendMethod method) { affine_func_.blend_method=method; } 236 237 //! Returns the blend method being used for this pen get_blend_method()238 Color::BlendMethod get_blend_method()const { return affine_func_.blend_method; } 239 }; // END of class Surface::alpha_pen 240 241 242 243 /*! \class CairoSurface::alpha_pen 244 ** \brief Alpha-Blending Pen 245 ** 246 ** This pen works like a normal alpha pen, except that it supports 247 ** a variety of blending methods. Use set_blend_method() to select 248 ** which blending method you want to use. 249 ** The default blending method is Color::BLEND_COMPOSITE. 250 ** \see Color::BlendMethod 251 */ 252 class CairoSurface::alpha_pen : public etl::alpha_pen< etl::generic_pen<CairoColor, CairoColorAccumulator>, float, _BlendFunc<CairoColor> > 253 { 254 public: alpha_pen()255 alpha_pen() { } alpha_pen(const etl::alpha_pen<etl::generic_pen<CairoColor,CairoColorAccumulator>,float,_BlendFunc<CairoColor>> & x)256 alpha_pen(const etl::alpha_pen< etl::generic_pen<CairoColor, CairoColorAccumulator>, float, _BlendFunc<CairoColor> > &x): 257 etl::alpha_pen< etl::generic_pen<CairoColor, CairoColorAccumulator>, float, _BlendFunc<CairoColor> >(x) 258 { } 259 260 alpha_pen(const etl::generic_pen<CairoColor, CairoColorAccumulator>& pen, const float &a = 1, const _BlendFunc<CairoColor> &func = _BlendFunc<CairoColor>()): 261 etl::alpha_pen< etl::generic_pen<CairoColor, CairoColorAccumulator>, float, _BlendFunc<CairoColor> >(pen,a,func) 262 { } 263 264 //! Sets the blend method to that described by \a method set_blend_method(Color::BlendMethod method)265 void set_blend_method(Color::BlendMethod method) { affine_func_.blend_method=method; } 266 267 //! Returns the blend method being used for this pen get_blend_method()268 Color::BlendMethod get_blend_method()const { return affine_func_.blend_method; } 269 }; // END of class CairoSurface::alpha_pen 270 271 272 273 //! Creates a target that will render to \a surface by specified \a renderer 274 etl::handle<Target_Tile> surface_target(Surface *surface, const String &renderer = String()); 275 //! Creates a target that will render to \a surface by specified \a renderer 276 etl::handle<Target_Scanline> surface_target_scanline(Surface *surface); 277 //!Creates a target that will render to a cairo_surface_t image surface 278 etl::handle<Target_Cairo> cairo_image_target(cairo_surface_t** surface); 279 280 }; // END of namespace synfig 281 282 /* === E N D =============================================================== */ 283 284 #endif 285