Initial Stable Commit
[synfig.git] / synfig-core / trunk / src / modules / lyr_std / supersample.cpp
1 /*! ========================================================================
2 ** Sinfg
3 ** Template File
4 ** $Id: supersample.cpp,v 1.1.1.1 2005/01/04 01:23:10 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 #ifdef USING_PCH
24 #       include "pch.h"
25 #else
26 #ifdef HAVE_CONFIG_H
27 #       include <config.h>
28 #endif
29
30 #include "supersample.h"
31 #include <sinfg/string.h>
32 #include <sinfg/time.h>
33 #include <sinfg/context.h>
34 #include <sinfg/paramdesc.h>
35 #include <sinfg/renddesc.h>
36 #include <sinfg/surface.h>
37 #include <sinfg/value.h>
38 #include <sinfg/valuenode.h>
39
40 #include <sinfg/target.h>
41 #include <sinfg/render.h>
42
43 #endif
44
45 /* === M A C R O S ========================================================= */
46
47 /* === G L O B A L S ======================================================= */
48
49 SINFG_LAYER_INIT(SuperSample);
50 SINFG_LAYER_SET_NAME(SuperSample,"super_sample");
51 SINFG_LAYER_SET_LOCAL_NAME(SuperSample,_("Super Sample"));
52 SINFG_LAYER_SET_CATEGORY(SuperSample,_("Other"));
53 SINFG_LAYER_SET_VERSION(SuperSample,"0.1");
54 SINFG_LAYER_SET_CVS_ID(SuperSample,"$Id: supersample.cpp,v 1.1.1.1 2005/01/04 01:23:10 darco Exp $");
55
56 /* === P R O C E D U R E S ================================================= */
57
58 /* === M E T H O D S ======================================================= */
59
60 SuperSample::SuperSample():width(2),height(2)
61 {
62         scanline=false;
63         alpha_aware=true;
64 }
65
66 bool
67 SuperSample::set_param(const String & param, const ValueBase &value)
68 {
69
70         IMPORT(width);
71         IMPORT(height);
72         IMPORT(scanline);
73         IMPORT(alpha_aware);
74         
75         return false;
76 }
77
78 ValueBase
79 SuperSample::get_param(const String& param)const
80 {
81         EXPORT(width);
82         EXPORT(height);
83     EXPORT(scanline);
84     EXPORT(alpha_aware);
85         
86         EXPORT_NAME();
87         EXPORT_VERSION();
88
89         return ValueBase();
90 }
91
92 bool
93 SuperSample::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
94 {
95         // don't bother supersampling if our quality is too low.
96         if(quality>=10)
97                 return context.accelerated_render(surface,quality,renddesc,cb);
98         
99         RendDesc desc(renddesc);
100
101         SuperCallback subcb(cb,1,9000,10000);
102         SuperCallback stagetwo(cb,9000,10000,10000);
103
104         desc.clear_flags();
105         desc.set_wh(desc.get_w()*width,desc.get_h()*height);
106
107         Surface tempsurface;
108
109         // Render the scene
110         if(scanline)
111         {
112                 handle<Target> target=surface_target(&tempsurface);
113                 if(!target)
114                 {
115                         if(cb)cb->error(_("Unable to create SurfaceTarget"));
116                         return false;
117                 }
118                 target->set_rend_desc(&desc);
119
120                 if(!render(context-1,target,desc,&subcb))
121                 {
122                         if(cb)cb->error(strprintf(__FILE__"%d: Scanline Renderer Failure",__LINE__));
123                         return false;
124                 }
125         }
126         else
127                 if(!context.accelerated_render(&tempsurface,quality,desc,cb))
128                 {
129                         //if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__));
130                         return false;
131                 }
132
133         surface->set_wh(renddesc.get_w(),renddesc.get_h());
134
135         Surface::pen pen(surface->begin());
136         Surface::pen temp_pen(tempsurface.begin());
137
138         if(cb && !cb->amount_complete(9001,10000)) return false;
139
140         if(alpha_aware)
141         {
142                 int x,y,u,v;
143                 float sum;
144                 Color pool;
145                 for(y=0;y<surface->get_h();y++,pen.inc_y(),pen.dec_x(x),temp_pen.inc_y(height),temp_pen.dec_x(x*width))
146                 {
147                         for(x=0;x<surface->get_w();x++,pen.inc_x(),temp_pen.inc_x(width))
148                         {
149                                 pool=Color(0,0,0,0);
150                                 sum=0;
151
152                                 for(v=0;v<height;v++,temp_pen.inc_y(),temp_pen.dec_x(u))
153                                         for(u=0;u<width;u++,temp_pen.inc_x())
154                                         {
155                                                 pool+=temp_pen.get_value()*temp_pen.get_value().get_a();
156                                                 sum+=temp_pen.get_value().get_a();
157                                         }
158                                 temp_pen.dec_y(v);
159
160                                 if(sum)
161                                 {
162                                         pool/=sum;
163                                         pool.set_a(sum/float(width*height));
164                                         pen.put_value(pool);
165                                 }
166                                 else
167                                         pen.put_value(Color::alpha());
168                         }
169                         if(y&31==0 && cb)
170                         {
171                                 if(!stagetwo.amount_complete(y,surface->get_h()))
172                                         return false;
173                         }
174                 }
175         }
176         else
177         {
178                 int x,y,u,v;
179                 Color pool;
180                 float multiplier=1.0f/float(width*height);
181                 for(y=0;y<surface->get_h();y++,pen.inc_y(),pen.dec_x(x),temp_pen.inc_y(height),temp_pen.dec_x(x*width))
182                 {
183                         for(x=0;x<surface->get_w();x++,pen.inc_x(),temp_pen.inc_x(width))
184                         {
185                                 pool=Color(0,0,0,0);
186                                 for(v=0;v<height;v++,temp_pen.inc_y(),temp_pen.dec_x(u))
187                                         for(u=0;u<width;u++,temp_pen.inc_x())
188                                                 pool+=temp_pen.get_value();
189                                 temp_pen.dec_y(v);
190                                 pen.put_value(pool*multiplier);
191                         }
192                         if(y&31==0 && cb)
193                         {
194                                 if(!stagetwo.amount_complete(y,surface->get_h()))
195                                         return false;
196                         }
197                 }
198         }
199         
200         if(cb && !cb->amount_complete(10000,10000)) return false;
201         
202         return true;
203 }
204
205 Layer::Vocab
206 SuperSample::get_param_vocab(void)const
207 {
208         Layer::Vocab ret;
209
210         ret.push_back(ParamDesc("width")
211                 .set_local_name(_("Width"))
212                 .set_description(_("Width of sample area (In pixels)"))
213         );
214         ret.push_back(ParamDesc("height")
215                 .set_local_name(_("Height"))
216                 .set_description(_("Height of sample area (In pixels)"))
217         );
218         ret.push_back(ParamDesc("scanline")
219                 .set_local_name(_("Use Parametric"))
220                 .set_description(_("Use the Parametric Renderer"))
221         );
222         ret.push_back(ParamDesc("alpha_aware")
223                 .set_local_name(_("Be Alpha Safe"))
224         );
225         
226         return ret;
227 }
228
229 Rect
230 SuperSample::get_bounding_rect(Context context)const
231 {
232         return context.get_full_bounding_rect();
233 }