608a242162e1aa3021585561a11e150173c80188
[synfig.git] /
1 /* === S Y N F I G ========================================================= */
2 /*!     \file supersample.cpp
3 **      \brief Implementation of the "Super Sample" layer
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **
10 **      This package is free software; you can redistribute it and/or
11 **      modify it under the terms of the GNU General Public License as
12 **      published by the Free Software Foundation; either version 2 of
13 **      the License, or (at your option) any later version.
14 **
15 **      This package is distributed in the hope that it will be useful,
16 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
17 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 **      General Public License for more details.
19 **      \endlegal
20 **
21 ** === N O T E S ===========================================================
22 **
23 ** ========================================================================= */
24
25 /* === H E A D E R S ======================================================= */
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 "supersample.h"
35 #include <synfig/string.h>
36 #include <synfig/time.h>
37 #include <synfig/context.h>
38 #include <synfig/paramdesc.h>
39 #include <synfig/renddesc.h>
40 #include <synfig/surface.h>
41 #include <synfig/value.h>
42 #include <synfig/valuenode.h>
43
44 #include <synfig/target.h>
45 #include <synfig/render.h>
46
47 #endif
48
49 /* === M A C R O S ========================================================= */
50
51 /* === G L O B A L S ======================================================= */
52
53 SYNFIG_LAYER_INIT(SuperSample);
54 SYNFIG_LAYER_SET_NAME(SuperSample,"super_sample");
55 SYNFIG_LAYER_SET_LOCAL_NAME(SuperSample,N_("Super Sample"));
56 SYNFIG_LAYER_SET_CATEGORY(SuperSample,N_("Other"));
57 SYNFIG_LAYER_SET_VERSION(SuperSample,"0.1");
58 SYNFIG_LAYER_SET_CVS_ID(SuperSample,"$Id$");
59
60 /* === P R O C E D U R E S ================================================= */
61
62 /* === M E T H O D S ======================================================= */
63
64 SuperSample::SuperSample():width(2),height(2)
65 {
66         scanline=false;
67         alpha_aware=true;
68 }
69
70 bool
71 SuperSample::set_param(const String & param, const ValueBase &value)
72 {
73
74         IMPORT(width);
75         IMPORT(height);
76         IMPORT(scanline);
77         IMPORT(alpha_aware);
78
79         return false;
80 }
81
82 ValueBase
83 SuperSample::get_param(const String& param)const
84 {
85         EXPORT(width);
86         EXPORT(height);
87     EXPORT(scanline);
88     EXPORT(alpha_aware);
89
90         EXPORT_NAME();
91         EXPORT_VERSION();
92
93         return ValueBase();
94 }
95
96 bool
97 SuperSample::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
98 {
99         // don't bother supersampling if our quality is too low.
100         if(quality>=10)
101                 return context.accelerated_render(surface,quality,renddesc,cb);
102
103         RendDesc desc(renddesc);
104
105         SuperCallback subcb(cb,1,9000,10000);
106         SuperCallback stagetwo(cb,9000,10000,10000);
107
108         desc.clear_flags();
109         desc.set_wh(desc.get_w()*width,desc.get_h()*height);
110
111         Surface tempsurface;
112
113         // Render the scene
114         if(scanline)
115         {
116                 handle<Target> target=surface_target(&tempsurface);
117                 if(!target)
118                 {
119                         if(cb)cb->error(_("Unable to create SurfaceTarget"));
120                         return false;
121                 }
122                 target->set_rend_desc(&desc);
123
124                 if(!render(context-1,target,desc,&subcb))
125                 {
126                         if(cb)cb->error(strprintf(__FILE__"%d: Scanline Renderer Failure",__LINE__));
127                         return false;
128                 }
129         }
130         else
131                 if(!context.accelerated_render(&tempsurface,quality,desc,cb))
132                 {
133                         //if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Renderer Failure",__LINE__));
134                         return false;
135                 }
136
137         surface->set_wh(renddesc.get_w(),renddesc.get_h());
138
139         Surface::pen pen(surface->begin());
140         Surface::pen temp_pen(tempsurface.begin());
141
142         if(cb && !cb->amount_complete(9001,10000)) return false;
143
144         if(alpha_aware)
145         {
146                 int x,y,u,v;
147                 float sum;
148                 Color pool;
149                 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))
150                 {
151                         for(x=0;x<surface->get_w();x++,pen.inc_x(),temp_pen.inc_x(width))
152                         {
153                                 pool=Color(0,0,0,0);
154                                 sum=0;
155
156                                 for(v=0;v<height;v++,temp_pen.inc_y(),temp_pen.dec_x(u))
157                                         for(u=0;u<width;u++,temp_pen.inc_x())
158                                         {
159                                                 pool+=temp_pen.get_value()*temp_pen.get_value().get_a();
160                                                 sum+=temp_pen.get_value().get_a();
161                                         }
162                                 temp_pen.dec_y(v);
163
164                                 if(sum)
165                                 {
166                                         pool/=sum;
167                                         pool.set_a(sum/float(width*height));
168                                         pen.put_value(pool);
169                                 }
170                                 else
171                                         pen.put_value(Color::alpha());
172                         }
173                         if((y&31)==0 && cb)
174                         {
175                                 if(!stagetwo.amount_complete(y,surface->get_h()))
176                                         return false;
177                         }
178                 }
179         }
180         else
181         {
182                 int x,y,u,v;
183                 Color pool;
184                 float multiplier=1.0f/float(width*height);
185                 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))
186                 {
187                         for(x=0;x<surface->get_w();x++,pen.inc_x(),temp_pen.inc_x(width))
188                         {
189                                 pool=Color(0,0,0,0);
190                                 for(v=0;v<height;v++,temp_pen.inc_y(),temp_pen.dec_x(u))
191                                         for(u=0;u<width;u++,temp_pen.inc_x())
192                                                 pool+=temp_pen.get_value();
193                                 temp_pen.dec_y(v);
194                                 pen.put_value(pool*multiplier);
195                         }
196                         if((y&31)==0 && cb)
197                         {
198                                 if(!stagetwo.amount_complete(y,surface->get_h()))
199                                         return false;
200                         }
201                 }
202         }
203
204         if(cb && !cb->amount_complete(10000,10000)) return false;
205
206         return true;
207 }
208
209 Layer::Vocab
210 SuperSample::get_param_vocab(void)const
211 {
212         Layer::Vocab ret;
213
214         ret.push_back(ParamDesc("width")
215                 .set_local_name(_("Width"))
216                 .set_description(_("Width of sample area (In pixels)"))
217         );
218         ret.push_back(ParamDesc("height")
219                 .set_local_name(_("Height"))
220                 .set_description(_("Height of sample area (In pixels)"))
221         );
222         ret.push_back(ParamDesc("scanline")
223                 .set_local_name(_("Use Parametric"))
224                 .set_description(_("Use the Parametric Renderer"))
225         );
226         ret.push_back(ParamDesc("alpha_aware")
227                 .set_local_name(_("Be Alpha Safe"))
228         );
229
230         return ret;
231 }
232
233 Rect
234 SuperSample::get_bounding_rect(Context context)const
235 {
236         return context.get_full_bounding_rect();
237 }