Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_05 / synfig-core / src / synfig / surface.cpp
1 /* ========================================================================
2 ** Synfig
3 ** Template File
4 ** $Id: surface.cpp,v 1.1.1.1 2005/01/04 01:23:14 darco Exp $
5 **
6 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
7 **
8 **      This package is free software; you can redistribute it and/or
9 **      modify it under the terms of the GNU General Public License as
10 **      published by the Free Software Foundation; either version 2 of
11 **      the License, or (at your option) any later version.
12 **
13 **      This package is distributed in the hope that it will be useful,
14 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
15 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 **      General Public License for more details.
17 **
18 ** === N O T E S ===========================================================
19 **
20 ** ========================================================================= */
21
22 /* === H E A D E R S ======================================================= */
23
24 #define SYNFIG_NO_ANGLE
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "canvas.h"
34 #include "surface.h"
35 #include "target_scanline.h"
36 #include "general.h"
37
38 #ifdef HAS_VIMAGE
39 #include <Accelerate/Accelerate.h>
40 #endif
41
42 #endif
43
44 using namespace synfig;
45 using namespace std;
46 using namespace etl;
47
48 /* === M A C R O S ========================================================= */
49
50 /* === G L O B A L S ======================================================= */
51
52 class target2surface : public synfig::Target_Scanline
53 {
54 public:
55         Surface *surface;
56         bool     sized;
57 public:
58         target2surface(Surface *surface);
59         virtual ~target2surface();
60
61         virtual bool set_rend_desc(synfig::RendDesc *newdesc);
62         
63         virtual bool start_frame(synfig::ProgressCallback *cb);
64         
65         virtual void end_frame();
66
67         virtual Color * start_scanline(int scanline);
68
69         virtual bool end_scanline();
70 };
71
72 target2surface::target2surface(Surface *surface):surface(surface)
73 {
74 }
75
76 target2surface::~target2surface()
77 {
78 }
79
80 bool
81 target2surface::set_rend_desc(synfig::RendDesc *newdesc)
82 {
83         assert(newdesc);
84         assert(surface);
85         desc=*newdesc;
86         return synfig::Target_Scanline::set_rend_desc(newdesc);
87 }
88         
89 bool
90 target2surface::start_frame(synfig::ProgressCallback *cb) 
91
92         if(surface->get_w() != desc.get_w() || surface->get_h() != desc.get_h())
93         {
94                 surface->set_wh(desc.get_w(),desc.get_h());
95         }
96         return true; 
97 }
98         
99 void
100 target2surface::end_frame()
101 {
102         return;
103 }
104         
105 Color *
106 target2surface::start_scanline(int scanline)
107 {
108         return (*surface)[scanline];
109 }
110
111 bool
112 target2surface::end_scanline()
113 {
114         return true;
115 }
116
117 /* === P R O C E D U R E S ================================================= */
118
119 /* === M E T H O D S ======================================================= */
120
121 Target_Scanline::Handle
122 synfig::surface_target(Surface *surface)
123 {
124         return Target_Scanline::Handle(new target2surface(surface));
125 }
126
127 void
128 synfig::Surface::clear()
129 {
130 #ifdef HAS_VIMAGE
131         fill(Color(0.5,0.5,0.5,0.0000001));
132 #else
133         etl::surface<Color, ColorAccumulator, ColorPrep>::clear();
134 #endif
135 }
136
137 void
138 synfig::Surface::blit_to(alpha_pen& pen, int x, int y, int w, int h)
139 {
140         static const float epsilon(0.00001);
141         const float alpha(pen.get_alpha());
142         if(     pen.get_blend_method()==Color::BLEND_STRAIGHT && fabs(alpha-1.0f)<epsilon )
143         {
144                 if(x>=get_w() || y>=get_w())
145                         return;
146
147                 //clip source origin
148                 if(x<0)
149                 {
150                         w+=x;   //decrease
151                         x=0;            
152                 }
153                 
154                 if(y<0)
155                 {
156                         h+=y;   //decrease
157                         y=0;            
158                 }
159                                 
160                 //clip width against dest width
161                 w = min(w,pen.end_x()-pen.x());
162                 h = min(h,pen.end_y()-pen.y());
163                 
164                 //clip width against src width
165                 w = min(w,get_w()-x);           
166                 h = min(h,get_h()-y);   
167
168                 if(w<=0 || h<=0)
169                         return;
170                                 
171                 for(int i=0;i<h;i++)
172                 {
173                         char* src(static_cast<char*>(static_cast<void*>(operator[](y)+x))+i*get_w()*sizeof(Color));
174                         char* dest(static_cast<char*>(static_cast<void*>(pen.x()))+i*pen.get_width()*sizeof(Color));
175                         memcpy(dest,src,w*sizeof(Color));
176                 }
177                 return;
178         }
179         
180 #ifdef HAS_VIMAGE       
181         if(     pen.get_blend_method()==Color::BLEND_COMPOSITE && fabs(alpha-1.0f)<epsilon )
182         {
183                 if(x>=get_w() || y>=get_w())
184                         return;
185
186                 //clip source origin
187                 if(x<0)
188                 {
189                         //u-=x; //increase
190                         w+=x;   //decrease
191                         x=0;            
192                 }
193                 
194                 if(y<0)
195                 {
196                         //v-=y; //increase
197                         h+=y;   //decrease
198                         y=0;            
199                 }
200                                 
201                 //clip width against dest width
202                 w = min(w,pen.end_x()-pen.x());
203                 h = min(h,pen.end_y()-pen.y());
204                 
205                 //clip width against src width
206                 w = min(w,get_w()-x);           
207                 h = min(h,get_h()-y);   
208
209                 if(w<=0 || h<=0)
210                         return;
211
212
213
214                 vImage_Buffer top,bottom;
215                 vImage_Buffer& dest(bottom);
216                 
217                 top.data=static_cast<void*>(operator[](y)+x);
218                 top.height=h;
219                 top.width=w;
220                 //top.rowBytes=get_w()*sizeof(Color); //! \fixme this should get the pitch!!
221                 top.rowBytes=get_pitch();
222
223                 bottom.data=static_cast<void*>(pen.x());
224                 bottom.height=h;
225                 bottom.width=w;
226                 //bottom.rowBytes=pen.get_width()*sizeof(Color); //! \fixme this should get the pitch!!
227                 bottom.rowBytes=pen.get_pitch(); //! \fixme this should get the pitch!!
228                                 
229                 vImage_Error ret;
230                 ret=vImageAlphaBlend_ARGBFFFF(&top,&bottom,&dest,kvImageNoFlags);
231                 
232                 assert(ret!=kvImageNoError);
233                 
234                 return;
235         }
236 #endif
237         etl::surface<Color, ColorAccumulator, ColorPrep>::blit_to(pen,x,y,w,h);
238 }
239