Fixed the name of the last parameter in the set_time() prototype to match that of...
[synfig.git] / synfig-core / trunk / src / synfig / surface.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file surface.cpp
3 **      \brief Template File
4 **
5 **      \legal
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 **      \endlegal
18 **
19 ** === N O T E S ===========================================================
20 **
21 ** ========================================================================= */
22
23 /* === H E A D E R S ======================================================= */
24
25 #define SYNFIG_NO_ANGLE
26
27 #ifdef USING_PCH
28 #       include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 #       include <config.h>
32 #endif
33
34 #include "canvas.h"
35 #include "surface.h"
36 #include "target_scanline.h"
37 #include "general.h"
38
39 #ifdef HAS_VIMAGE
40 #include <Accelerate/Accelerate.h>
41 #endif
42
43 #endif
44
45 using namespace synfig;
46 using namespace std;
47 using namespace etl;
48
49 /* === M A C R O S ========================================================= */
50
51 /* === G L O B A L S ======================================================= */
52
53 class target2surface : public synfig::Target_Scanline
54 {
55 public:
56         Surface *surface;
57         bool     sized;
58 public:
59         target2surface(Surface *surface);
60         virtual ~target2surface();
61
62         virtual bool set_rend_desc(synfig::RendDesc *newdesc);
63
64         virtual bool start_frame(synfig::ProgressCallback *cb);
65
66         virtual void end_frame();
67
68         virtual Color * start_scanline(int scanline);
69
70         virtual bool end_scanline();
71 };
72
73 target2surface::target2surface(Surface *surface):surface(surface)
74 {
75 }
76
77 target2surface::~target2surface()
78 {
79 }
80
81 bool
82 target2surface::set_rend_desc(synfig::RendDesc *newdesc)
83 {
84         assert(newdesc);
85         assert(surface);
86         desc=*newdesc;
87         return synfig::Target_Scanline::set_rend_desc(newdesc);
88 }
89
90 bool
91 target2surface::start_frame(synfig::ProgressCallback *cb)
92 {
93         if(surface->get_w() != desc.get_w() || surface->get_h() != desc.get_h())
94         {
95                 surface->set_wh(desc.get_w(),desc.get_h());
96         }
97         return true;
98 }
99
100 void
101 target2surface::end_frame()
102 {
103         return;
104 }
105
106 Color *
107 target2surface::start_scanline(int scanline)
108 {
109         return (*surface)[scanline];
110 }
111
112 bool
113 target2surface::end_scanline()
114 {
115         return true;
116 }
117
118 /* === P R O C E D U R E S ================================================= */
119
120 /* === M E T H O D S ======================================================= */
121
122 Target_Scanline::Handle
123 synfig::surface_target(Surface *surface)
124 {
125         return Target_Scanline::Handle(new target2surface(surface));
126 }
127
128 void
129 synfig::Surface::clear()
130 {
131 #ifdef HAS_VIMAGE
132         fill(Color(0.5,0.5,0.5,0.0000001));
133 #else
134         etl::surface<Color, ColorAccumulator, ColorPrep>::clear();
135 #endif
136 }
137
138 void
139 synfig::Surface::blit_to(alpha_pen& pen, int x, int y, int w, int h)
140 {
141         static const float epsilon(0.00001);
142         const float alpha(pen.get_alpha());
143         if(     pen.get_blend_method()==Color::BLEND_STRAIGHT && fabs(alpha-1.0f)<epsilon )
144         {
145                 if(x>=get_w() || y>=get_w())
146                         return;
147
148                 //clip source origin
149                 if(x<0)
150                 {
151                         w+=x;   //decrease
152                         x=0;
153                 }
154
155                 if(y<0)
156                 {
157                         h+=y;   //decrease
158                         y=0;
159                 }
160
161                 //clip width against dest width
162                 w = min((long)w,(long)(pen.end_x()-pen.x()));
163                 h = min((long)h,(long)(pen.end_y()-pen.y()));
164
165                 //clip width against src width
166                 w = min(w,get_w()-x);
167                 h = min(h,get_h()-y);
168
169                 if(w<=0 || h<=0)
170                         return;
171
172                 for(int i=0;i<h;i++)
173                 {
174                         char* src(static_cast<char*>(static_cast<void*>(operator[](y)+x))+i*get_w()*sizeof(Color));
175                         char* dest(static_cast<char*>(static_cast<void*>(pen.x()))+i*pen.get_width()*sizeof(Color));
176                         memcpy(dest,src,w*sizeof(Color));
177                 }
178                 return;
179         }
180
181 #ifdef HAS_VIMAGE
182         if(     pen.get_blend_method()==Color::BLEND_COMPOSITE && fabs(alpha-1.0f)<epsilon )
183         {
184                 if(x>=get_w() || y>=get_w())
185                         return;
186
187                 //clip source origin
188                 if(x<0)
189                 {
190                         //u-=x; //increase
191                         w+=x;   //decrease
192                         x=0;
193                 }
194
195                 if(y<0)
196                 {
197                         //v-=y; //increase
198                         h+=y;   //decrease
199                         y=0;
200                 }
201
202                 //clip width against dest width
203                 w = min(w,pen.end_x()-pen.x());
204                 h = min(h,pen.end_y()-pen.y());
205
206                 //clip width against src width
207                 w = min(w,get_w()-x);
208                 h = min(h,get_h()-y);
209
210                 if(w<=0 || h<=0)
211                         return;
212
213
214
215                 vImage_Buffer top,bottom;
216                 vImage_Buffer& dest(bottom);
217
218                 top.data=static_cast<void*>(operator[](y)+x);
219                 top.height=h;
220                 top.width=w;
221                 //top.rowBytes=get_w()*sizeof(Color); //! \fixme this should get the pitch!!
222                 top.rowBytes=get_pitch();
223
224                 bottom.data=static_cast<void*>(pen.x());
225                 bottom.height=h;
226                 bottom.width=w;
227                 //bottom.rowBytes=pen.get_width()*sizeof(Color); //! \fixme this should get the pitch!!
228                 bottom.rowBytes=pen.get_pitch(); //! \fixme this should get the pitch!!
229
230                 vImage_Error ret;
231                 ret=vImageAlphaBlend_ARGBFFFF(&top,&bottom,&dest,kvImageNoFlags);
232
233                 assert(ret!=kvImageNoError);
234
235                 return;
236         }
237 #endif
238         etl::surface<Color, ColorAccumulator, ColorPrep>::blit_to(pen,x,y,w,h);
239 }
240