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