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 ======================================================= */
34 #include <sys/types.h>
49 using namespace synfig;
52 /* === M A C R O S ========================================================= */
54 /* === P R O C E D U R E S ================================================= */
57 synfig::parametric_render(
61 ProgressCallback *callback
65 u,v, // Current location in image
66 su,sv, // Starting locations
67 du, dv, // Distance between pixels
68 dsu,dsv; // Distance between subpixels
71 no_clamp=!desc.get_clamp();
76 a(desc.get_antialias());
83 // gamma(desc.get_gamma());
86 x,y, // Current location on output bitmap
87 x2,y2; // Subpixel counters
90 pool; // Alpha pool (for correct alpha antialiasing)
92 // Calculate the number of channels
93 //chan=channels(desc.get_pixel_format());
95 // Calculate the distance between pixels
96 du=(br[0]-tl[0])/(Point::value_type)w;
97 dv=(br[1]-tl[1])/(Point::value_type)h;
99 // Calculate the distance between sub pixels
100 dsu=du/(Point::value_type)a;
101 dsv=dv/(Point::value_type)a;
103 // Calculate the starting points
104 //su=tl[0]+(du-dsu)/(Point::value_type)2.0;
105 //sv=tl[1]-(dv-dsv)/(Point::value_type)2.0;
109 surface.set_wh(desc.get_w(),desc.get_h());
113 // Loop through all horizontal lines
114 for(y=0,v=sv;y<h;y++,v+=dv)
116 // Set the current pixel pointer
117 // to the start of the line
118 Color *colordata=surface[y];
122 // If we have a callback that we need
123 // to report to, do so now.
125 if( callback->amount_complete(y,h) == false )
127 // If the callback returns false,
128 // then the render has been aborted.
133 // Loop through every pixel in row
134 for(x=0,u=su;x<w;x++,u+=du)
136 Color &c(*(colordata++));
139 // Loop through all subpixels
140 for(y2=0,pool=0;y2<a;y2++)
143 Color color=context.get_color(
145 u+(Point::value_type)(x2)*dsu,
146 v+(Point::value_type)(y2)*dsv
151 color=color.clamped();
152 c+=color*color.get_a();
157 c+=color*color.get_a();
166 // Give the callback one more last call,
167 // this time with the full height as the
170 callback->amount_complete(h,h);
172 // Report our success
179 Target_Scanline::Handle target,
180 const RendDesc &desc,
181 ProgressCallback *callback)
184 u,v, // Current location in image
185 su,sv, // Starting locations
186 du, dv, // Distance between pixels
187 dsu,dsv; // Distance between subpixels
190 no_clamp=!desc.get_clamp();
195 a(desc.get_antialias());
202 // gamma(desc.get_gamma());
205 x,y, // Current location on output bitmap
206 x2,y2; // Subpixel counters
209 pool; // Alpha pool (for correct alpha antialiasing)
213 // If we do not have a target then bail
217 // Calculate the number of channels
218 //chan=channels(desc.get_pixel_format());
220 // Calculate the distance between pixels
221 du=(br[0]-tl[0])/(Point::value_type)w;
222 dv=(br[1]-tl[1])/(Point::value_type)h;
224 // Calculate the distance between sub pixels
225 dsu=du/(Point::value_type)a;
226 dsv=dv/(Point::value_type)a;
228 // Calculate the starting points
229 su=tl[0]+(du-dsu)/(Point::value_type)2.0;
230 sv=tl[1]-(dv-dsv)/(Point::value_type)2.0;
232 // Mark the start of a new frame.
233 if(!target->start_frame(callback))
236 // Loop through all horizontal lines
237 for(y=0,v=sv;y<h;y++,v+=dv)
239 // Set the current pixel pointer
240 // to the start of the line
241 Color *colordata=target->start_scanline(y);
245 if(callback)callback->error(_("Target panic"));
246 else throw(string(_("Target panic")));
250 // If we have a callback that we need
251 // to report to, do so now.
253 if( callback->amount_complete(y,h) == false )
255 // If the callback returns false,
256 // then the render has been aborted.
259 target->end_scanline();
264 // Loop through every pixel in row
265 for(x=0,u=su;x<w;x++,u+=du)
267 Color &c(*(colordata++));
270 // Loop through all subpixels
271 for(y2=0,pool=0;y2<a;y2++)
274 Color color=context.get_color(
276 u+(Point::value_type)(x2)*dsu,
277 v+(Point::value_type)(y2)*dsv
282 color=color.clamped();
283 c+=color*color.get_a();
288 c+=color*color.get_a();
296 // Send the buffer to the render target.
297 // If anything goes wrong, cleanup and bail.
298 if(!target->end_scanline())
300 if(callback)callback->error(_("Target panic"));
301 else throw(string(_("Target panic")));
306 // Finish up the target's frame
309 // Give the callback one more last call,
310 // this time with the full height as the
313 callback->amount_complete(h,h);
315 // Report our success
320 synfig::render_threaded(
322 Target_Scanline::Handle target,
323 const RendDesc &desc,
324 ProgressCallback *callback,
328 struct _render_thread
353 u,v, // Current location in image
354 su,sv, // Starting locations
355 du, dv, // Distance between pixels
356 dsu,dsv; // Distance between subpixels
359 no_clamp=!desc.get_clamp();
364 a(desc.get_antialias());
371 x,y, // Current location on output bitmap
372 x2,y2; // Subpixel counters
375 pool; // Alpha pool (for correct alpha antialiasing)
379 // If we do not have a target then bail
383 // Calculate the distance between pixels
384 du=(br[0]-tl[0])/(Point::value_type)w;
385 dv=(br[1]-tl[1])/(Point::value_type)h;
387 // Calculate the distance between sub pixels
388 dsu=du/(Point::value_type)a;
389 dsv=dv/(Point::value_type)a;
391 // Calculate the starting points
392 su=tl[0]+(du-dsu)/(Point::value_type)2.0;
393 sv=tl[1]-(dv-dsv)/(Point::value_type)2.0;
395 render_thread=new _render_thread[threads];
398 for(i=0;i<threads;i++)
406 render_thread[i].pid=pid;
409 // Mark the start of a new frame.
410 if(!target->start_frame(callback))
415 // Set the current pixel pointer
416 // to the start of the line
417 Color *colordata(target->start_scanline(y));
421 if(callback)callback->error(_("Target panic"));
422 else throw(string(_("Target panic")));
426 // If we have a callback that we need
427 // to report to, do so now.
429 if( callback->amount_complete(y,h) == false )
431 // If the callback returns false,
432 // then the render has been aborted.
435 target->end_scanline();
437 delete [] render_thread;
441 read(render_thread[y%threads].pipe_read,colordata,w*sizeof(Color));
443 // Send the buffer to the render target.
444 // If anything goes wrong, cleanup and bail.
445 if(!target->end_scanline())
447 delete [] render_thread;
448 if(callback)callback->error(_("Target panic"));
449 else throw(string(_("Target panic")));
454 // Finish up the target's frame
457 // Give the callback one more last call,
458 // this time with the full height as the
461 callback->amount_complete(h,h);
463 delete [] render_thread;
468 // Change the random seed, so that each thread has a different one
469 srand(mythread*20+threads+time(0));
471 Color *buffer(new Color[w]);
473 // Loop through all horizontal lines
474 for(y=mythread,v=sv+dv*(Real)mythread;y<h;y+=threads,v+=dv*(Real)threads)
476 // Set the current pixel pointer
477 // to the start of the line
478 Color* colordata(buffer);
480 // Loop through every pixel in row
481 for(x=0,u=su;x<w;x++,u+=du)
483 Color &c(*(colordata++));
486 // Loop through all subpixels
487 for(y2=0,pool=0;y2<a;y2++)
490 Color color=context.get_color(
492 u+(Point::value_type)(x2)*dsu,
493 v+(Point::value_type)(y2)*dsv
498 color=color.clamped();
499 c+=color*color.get_a();
504 c+=color*color.get_a();
512 // Send the buffer to the primary thread.
513 write(render_thread[mythread].pipe_write,buffer,w*sizeof(Color));
521 return render(context, target, desc, callback);