1 /* === S Y N F I G ========================================================= */
2 /*! \file synfig/render.cpp
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
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.
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.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
25 #define SYNFIG_NO_ANGLE
36 #include <sys/types.h>
51 using namespace synfig;
54 /* === M A C R O S ========================================================= */
56 /* === P R O C E D U R E S ================================================= */
59 synfig::parametric_render(
63 ProgressCallback *callback
67 u,v, // Current location in image
68 su,sv, // Starting locations
69 du, dv, // Distance between pixels
70 dsu,dsv; // Distance between subpixels
73 no_clamp=!desc.get_clamp();
78 a(desc.get_antialias());
85 // gamma(desc.get_gamma());
88 x,y, // Current location on output bitmap
89 x2,y2; // Subpixel counters
92 pool; // Alpha pool (for correct alpha antialiasing)
94 // Calculate the number of channels
95 //chan=channels(desc.get_pixel_format());
97 // Calculate the distance between pixels
98 du=(br[0]-tl[0])/(Point::value_type)w;
99 dv=(br[1]-tl[1])/(Point::value_type)h;
101 // Calculate the distance between sub pixels
102 dsu=du/(Point::value_type)a;
103 dsv=dv/(Point::value_type)a;
105 // Calculate the starting points
106 //su=tl[0]+(du-dsu)/(Point::value_type)2.0;
107 //sv=tl[1]-(dv-dsv)/(Point::value_type)2.0;
111 surface.set_wh(desc.get_w(),desc.get_h());
115 // Loop through all horizontal lines
116 for(y=0,v=sv;y<h;y++,v+=dv)
118 // Set the current pixel pointer
119 // to the start of the line
120 Color *colordata=surface[y];
124 // If we have a callback that we need
125 // to report to, do so now.
127 if( callback->amount_complete(y,h) == false )
129 // If the callback returns false,
130 // then the render has been aborted.
135 // Loop through every pixel in row
136 for(x=0,u=su;x<w;x++,u+=du)
138 Color &c(*(colordata++));
141 // Loop through all subpixels
142 for(y2=0,pool=0;y2<a;y2++)
145 Color color=context.get_color(
147 u+(Point::value_type)(x2)*dsu,
148 v+(Point::value_type)(y2)*dsv
153 color=color.clamped();
154 c+=color*color.get_a();
159 c+=color*color.get_a();
168 // Give the callback one more last call,
169 // this time with the full height as the
172 callback->amount_complete(h,h);
174 // Report our success
181 Target_Scanline::Handle target,
182 const RendDesc &desc,
183 ProgressCallback *callback)
186 u,v, // Current location in image
187 su,sv, // Starting locations
188 du, dv, // Distance between pixels
189 dsu,dsv; // Distance between subpixels
192 no_clamp=!desc.get_clamp();
197 a(desc.get_antialias());
204 // gamma(desc.get_gamma());
207 x,y, // Current location on output bitmap
208 x2,y2; // Subpixel counters
211 pool; // Alpha pool (for correct alpha antialiasing)
215 // If we do not have a target then bail
219 // Calculate the number of channels
220 //chan=channels(desc.get_pixel_format());
222 // Calculate the distance between pixels
223 du=(br[0]-tl[0])/(Point::value_type)w;
224 dv=(br[1]-tl[1])/(Point::value_type)h;
226 // Calculate the distance between sub pixels
227 dsu=du/(Point::value_type)a;
228 dsv=dv/(Point::value_type)a;
230 // Calculate the starting points
231 su=tl[0]+(du-dsu)/(Point::value_type)2.0;
232 sv=tl[1]-(dv-dsv)/(Point::value_type)2.0;
234 // Mark the start of a new frame.
235 if(!target->start_frame(callback))
238 // Loop through all horizontal lines
239 for(y=0,v=sv;y<h;y++,v+=dv)
241 // Set the current pixel pointer
242 // to the start of the line
243 Color *colordata=target->start_scanline(y);
247 if(callback)callback->error(_("Target panic"));
248 else throw(string(_("Target panic")));
252 // If we have a callback that we need
253 // to report to, do so now.
255 if( callback->amount_complete(y,h) == false )
257 // If the callback returns false,
258 // then the render has been aborted.
261 target->end_scanline();
266 // Loop through every pixel in row
267 for(x=0,u=su;x<w;x++,u+=du)
269 Color &c(*(colordata++));
272 // Loop through all subpixels
273 for(y2=0,pool=0;y2<a;y2++)
276 Color color=context.get_color(
278 u+(Point::value_type)(x2)*dsu,
279 v+(Point::value_type)(y2)*dsv
284 color=color.clamped();
285 c+=color*color.get_a();
290 c+=color*color.get_a();
298 // Send the buffer to the render target.
299 // If anything goes wrong, cleanup and bail.
300 if(!target->end_scanline())
302 if(callback)callback->error(_("Target panic"));
303 else throw(string(_("Target panic")));
308 // Finish up the target's frame
311 // Give the callback one more last call,
312 // this time with the full height as the
315 callback->amount_complete(h,h);
317 // Report our success
322 synfig::render_threaded(
324 Target_Scanline::Handle target,
325 const RendDesc &desc,
326 ProgressCallback *callback,
330 struct _render_thread
355 u,v, // Current location in image
356 su,sv, // Starting locations
357 du, dv, // Distance between pixels
358 dsu,dsv; // Distance between subpixels
361 no_clamp=!desc.get_clamp();
366 a(desc.get_antialias());
373 x,y, // Current location on output bitmap
374 x2,y2; // Subpixel counters
377 pool; // Alpha pool (for correct alpha antialiasing)
381 // If we do not have a target then bail
385 // Calculate the distance between pixels
386 du=(br[0]-tl[0])/(Point::value_type)w;
387 dv=(br[1]-tl[1])/(Point::value_type)h;
389 // Calculate the distance between sub pixels
390 dsu=du/(Point::value_type)a;
391 dsv=dv/(Point::value_type)a;
393 // Calculate the starting points
394 su=tl[0]+(du-dsu)/(Point::value_type)2.0;
395 sv=tl[1]-(dv-dsv)/(Point::value_type)2.0;
397 render_thread=new _render_thread[threads];
400 for(i=0;i<threads;i++)
408 render_thread[i].pid=pid;
411 // Mark the start of a new frame.
412 if(!target->start_frame(callback))
417 // Set the current pixel pointer
418 // to the start of the line
419 Color *colordata(target->start_scanline(y));
423 if(callback)callback->error(_("Target panic"));
424 else throw(string(_("Target panic")));
428 // If we have a callback that we need
429 // to report to, do so now.
431 if( callback->amount_complete(y,h) == false )
433 // If the callback returns false,
434 // then the render has been aborted.
437 target->end_scanline();
439 delete [] render_thread;
443 read(render_thread[y%threads].pipe_read,colordata,w*sizeof(Color));
445 // Send the buffer to the render target.
446 // If anything goes wrong, cleanup and bail.
447 if(!target->end_scanline())
449 delete [] render_thread;
450 if(callback)callback->error(_("Target panic"));
451 else throw(string(_("Target panic")));
456 // Finish up the target's frame
459 // Give the callback one more last call,
460 // this time with the full height as the
463 callback->amount_complete(h,h);
465 delete [] render_thread;
470 // Change the random seed, so that each thread has a different one
471 srand(mythread*20+threads+time(0));
473 Color *buffer(new Color[w]);
475 // Loop through all horizontal lines
476 for(y=mythread,v=sv+dv*(Real)mythread;y<h;y+=threads,v+=dv*(Real)threads)
478 // Set the current pixel pointer
479 // to the start of the line
480 Color* colordata(buffer);
482 // Loop through every pixel in row
483 for(x=0,u=su;x<w;x++,u+=du)
485 Color &c(*(colordata++));
488 // Loop through all subpixels
489 for(y2=0,pool=0;y2<a;y2++)
492 Color color=context.get_color(
494 u+(Point::value_type)(x2)*dsu,
495 v+(Point::value_type)(y2)*dsv
500 color=color.clamped();
501 c+=color*color.get_a();
506 c+=color*color.get_a();
514 // Send the buffer to the primary thread.
515 write(render_thread[mythread].pipe_write,buffer,w*sizeof(Color));
523 return render(context, target, desc, callback);