Add new parameters for motionblur. Enable linear, constant and hyperbolic sub-samples.
[synfig.git] / synfig-core / src / synfig / renddesc.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file synfig/renddesc.cpp
3 **      \brief RendDesc
4 **
5 **      $Id$
6 **
7 **      \legal
8 **      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **      Copyright (c) 2008 Chris Moore
10 **
11 **      This package is free software; you can redistribute it and/or
12 **      modify it under the terms of the GNU General Public License as
13 **      published by the Free Software Foundation; either version 2 of
14 **      the License, or (at your option) any later version.
15 **
16 **      This package is distributed in the hope that it will be useful,
17 **      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 **      General Public License for more details.
20 **      \endlegal
21 */
22 /* ========================================================================= */
23
24 /* === H E A D E R S ======================================================= */
25
26 #ifdef USING_PCH
27 #       include "pch.h"
28 #else
29 #ifdef HAVE_CONFIG_H
30 #       include <config.h>
31 #endif
32
33 #include "renddesc.h"
34 #include <ETL/misc>
35
36 #endif
37
38 /* === U S I N G =========================================================== */
39
40 using namespace std;
41 using namespace etl;
42 using namespace synfig;
43
44 /* === M A C R O S ========================================================= */
45
46 #undef FLAGS
47 #define FLAGS(x,y)              (((x)&(y))==(y))
48
49 /* === G L O B A L S ======================================================= */
50
51 /* === M E T H O D S ======================================================= */
52
53 RendDesc &
54 RendDesc::apply(const RendDesc &x)
55 {
56         operator=(x);
57         return *this;
58 }
59
60 const Color &
61 RendDesc::get_bg_color()const
62 {
63         return background;
64 }
65
66 RendDesc &
67 RendDesc::set_bg_color(const Color &bg)
68 {
69         background=bg; return *this;
70 }
71
72 Real
73 RendDesc::get_physical_w()const
74 {
75         return (Real)get_w()/get_x_res();
76 }
77
78 Real
79 RendDesc::get_physical_h()const
80 {
81         return (Real)get_h()/get_y_res();
82 }
83
84 RendDesc&
85 RendDesc::set_physical_w(Real w)
86 {
87         set_w(round_to_int(w*get_x_res()));
88         return *this;
89 }
90
91 RendDesc&
92 RendDesc::set_physical_h(Real h)
93 {
94         set_h(round_to_int(h*get_y_res()));
95         return *this;
96 }
97
98 int
99 RendDesc::get_w()const
100 {
101         return w_;
102 }
103
104 RendDesc &
105 RendDesc::set_w(int x)
106 {
107         if(FLAGS(flags,LINK_PX_ASPECT)) // never set
108         {
109                 h_=h_*x/w_;
110                 w_=x;
111         }
112         else if(FLAGS(flags,LINK_PX_AREA)) // never set
113         {
114                 //! \writeme
115                 w_=x;
116         }
117         else if(FLAGS(flags,PX_ASPECT)) // "Pixel Aspect"
118         {
119                 Vector d=br_-tl_;
120                 float old_span=get_span();
121
122                 // If we should preserve image width
123                 if(             FLAGS(flags,IM_W)                                                       // "Image Width"
124                         || (FLAGS(flags,IM_ZOOMIN) && d[1]>d[1]/x*w_)   // never set
125                         || (FLAGS(flags,IM_ZOOMOUT) && d[1]<d[1]/x*w_)) // never set
126                 {
127                         br_[1]-=focus[1];
128                         br_[1]=br_[1]/x*w_;
129                         br_[1]+=focus[1];
130                         tl_[1]-=focus[1];
131                         tl_[1]=tl_[1]/x*w_;
132                         tl_[1]+=focus[1];
133                 } else
134                 {
135                         br_[0]-=focus[0];
136                         br_[0]=br_[0]/w_*x;
137                         br_[0]+=focus[0];
138                         tl_[0]-=focus[0];
139                         tl_[0]=tl_[0]/w_*x;
140                         tl_[0]+=focus[0];
141                 }
142
143                 w_=x;
144
145                 if(FLAGS(flags,IM_SPAN)) // "Image Span"
146                         set_span(old_span);
147         }
148         else if(FLAGS(flags,PX_AREA)) // never set
149         {
150                 //! \writeme
151                 w_=x;
152         }
153         else
154                 w_=x;
155
156         return *this;
157 }
158
159 int
160 RendDesc::get_h()const
161 {
162         return h_;
163 }
164
165 RendDesc &
166 RendDesc::set_h(int y)
167 {
168         if(FLAGS(flags,LINK_PX_ASPECT)) // never set
169         {
170                 w_=w_*y/h_;
171                 h_=y;
172         }
173         else if(FLAGS(flags,LINK_PX_AREA)) // never set
174         {
175                 //! \writeme
176                 h_=y;
177         }
178         else if(FLAGS(flags,PX_ASPECT)) // "Pixel Aspect"
179         {
180                 Vector d=br_-tl_;
181                 float old_span=get_span();
182
183                 // If we should preserve image width
184                 if(             FLAGS(flags,IM_W)                                                       // "Image Width"
185                         || (FLAGS(flags,IM_ZOOMIN) && d[0]>d[0]/y*h_)   // never set
186                         || (FLAGS(flags,IM_ZOOMOUT) && d[0]<d[0]/y*h_)) // never set
187                 {
188                         br_[0]-=focus[0];
189                         br_[0]=br_[0]/y*h_;
190                         br_[0]+=focus[0];
191                         tl_[0]-=focus[0];
192                         tl_[0]=tl_[0]/y*h_;
193                         tl_[0]+=focus[0];
194                 } else
195                 {
196                         br_[1]-=focus[1];
197                         br_[1]=br_[1]/h_*y;
198                         br_[1]+=focus[1];
199                         tl_[1]-=focus[1];
200                         tl_[1]=tl_[1]/h_*y;
201                         tl_[1]+=focus[1];
202                 }
203
204                 h_=y;
205
206                 if(FLAGS(flags,IM_SPAN)) // "Image Span"
207                         set_span(old_span);
208         }
209         else if(FLAGS(flags,PX_AREA)) // never set
210         {
211                 //! \writeme
212                 h_=y;
213         }
214         else
215                 h_=y;
216
217         return *this;
218 }
219
220 RendDesc &
221 RendDesc::set_wh(int x, int y)
222 {
223         // FIXME: This is a working hack...
224         set_w(x);
225         set_h(y);
226
227         return *this;
228 }
229
230 Real
231 RendDesc::get_x_res()const
232 {
233         return x_res;
234 }
235
236 RendDesc &
237 RendDesc::set_x_res(Real x)
238 {
239         x_res=x; return *this;
240 }
241
242 Real
243 RendDesc::get_y_res()const
244 {
245         return y_res;
246 }
247
248 RendDesc &
249 RendDesc::set_y_res(Real y)
250 {
251         y_res=y; return *this;
252 }
253
254 int
255 RendDesc::get_frame_start()const
256 {
257         return round_to_int(time_begin*frame_rate);
258 }
259
260 RendDesc &
261 RendDesc::set_frame_start(int x)
262 {
263         return set_time_start(Time(x)/frame_rate);
264 }
265
266 int
267 RendDesc::get_frame_end()const
268 {
269         return round_to_int(time_end*frame_rate);
270 }
271
272 RendDesc &
273 RendDesc::set_frame_end(int x)
274 {
275         return set_time_end(Time(x)/frame_rate);
276 }
277
278
279 const Time
280 RendDesc::get_time_start()const
281 {
282         return time_begin;
283 }
284
285 RendDesc &
286 RendDesc::set_time_start(Time x)
287 {
288         if(x>time_end)
289                 time_begin=time_end=x;
290         else
291                 time_begin=x;
292         return *this;
293 }
294
295
296 const Time
297 RendDesc::get_time_end()const
298 {
299         return time_end;
300 }
301
302 RendDesc &
303 RendDesc::set_time_end(Time x)
304 {
305         if(x<time_begin)
306                 time_end=time_begin=x;
307         else
308                 time_end=x;
309         return *this;
310 }
311
312 RendDesc &
313 RendDesc::set_time(Time x)
314 {
315         time_end=time_begin=x;
316         return *this;
317 }
318
319 RendDesc &
320 RendDesc::set_frame(int x)
321 {
322         return set_time(Time(x)/frame_rate);
323 }
324
325 const float &
326 RendDesc::get_frame_rate()const
327 {
328         return frame_rate;
329 }
330
331 RendDesc &
332 RendDesc::set_frame_rate(float x)
333 {
334         frame_rate=x;
335         return *this;
336 }
337
338 const bool &
339 RendDesc::get_interlaced()const
340 {
341         return interlaced;
342 }
343
344 RendDesc &
345 RendDesc::set_interlaced(bool x)
346 { interlaced=x; return *this; }
347
348 //! Return the status of the clamp flag
349 const bool &
350 RendDesc::get_clamp()const
351 { return clamp; }
352
353 //! Set the clamp flag
354 RendDesc &
355 RendDesc::set_clamp(bool x)
356 { clamp=x; return *this; }
357
358 //! Set constraint flags
359 RendDesc &
360 RendDesc::set_flags(const int &x)
361 { flags=x; return *this; }
362
363 //! Clear constraint flags
364 RendDesc &
365 RendDesc::clear_flags()
366 { flags=0; return *this; }
367
368 int
369 RendDesc::get_flags()const
370 { return flags; }
371
372
373 //!     Return the aspect ratio of a single pixel
374 Real
375 RendDesc::get_pixel_aspect()const
376 {
377         Vector tmp=br_-tl_;
378         tmp[0]/=w_;
379         tmp[1]/=h_;
380         tmp[0]/=tmp[1];
381         if(tmp[0]<0.0)
382                 return -tmp[0];
383         return tmp[0];
384 }
385
386 //!     Return the aspect ratio of the entire image
387 Real
388 RendDesc::get_image_aspect()const
389 {
390         Point tmp=br_-tl_;
391         tmp[0]/=tmp[1];
392         if(tmp[0]<0.0)
393                 return -tmp[0];
394         return tmp[0];
395 }
396
397
398 //! Return the antialias amount
399 const int &
400 RendDesc::get_antialias()const
401 { return a; }
402
403 //! Set the antialias amount
404 RendDesc &
405 RendDesc::set_antialias(const int &x)
406 { a=x; return *this; }
407
408
409 //! Return the distance from the bottom-right to the top-left
410 Real
411 RendDesc::get_span()const
412 {
413         return (br_-tl_).mag();
414 }
415
416 //! Set the span distance
417 RendDesc &
418 RendDesc::set_span(const Real &x)
419 {
420         Vector::value_type ratio=x/get_span();
421
422         //! \todo this looks wrong.  I suspect the intention was to check
423         //                "(not IM_W) AND (not IM_H)", ie "not(IM_W OR IM_H)" but
424         //                this check does "not(IM_W AND IM_H)"
425         if(!FLAGS(flags,IM_W|IM_H) || FLAGS(flags,IM_ASPECT)) // (not "Image Width") or (not "Image Height") or "Image Aspect"
426         {
427                 br_-=focus;
428                 br_=br_*ratio;
429                 br_+=focus;
430                 tl_-=focus;
431                 tl_=tl_*ratio;
432                 tl_+=focus;
433         }
434         else if(FLAGS(flags,IM_W))      // "Image Width"
435         {
436                 //! \writeme or fix me
437                 br_-=focus;
438                 br_=br_*ratio;
439                 br_+=focus;
440                 tl_-=focus;
441                 tl_=tl_*ratio;
442                 tl_+=focus;
443         }else // IM_H                           // "Image Height"
444         {
445                 //! \writeme or fix me
446                 br_-=focus;
447                 br_=br_*ratio;
448                 br_+=focus;
449                 tl_-=focus;
450                 tl_=tl_*ratio;
451                 tl_+=focus;
452         }
453
454         return *this;
455 }
456
457
458 /*
459 const Gamma &
460 RendDesc::get_gamma()const
461 { return gamma; }
462
463 RendDesc &
464 RendDesc::set_gamma(const Gamma &x)
465 { gamma=x; return *this;  }
466 */
467
468 const Point &
469 RendDesc::get_focus()const
470 { return focus; }
471
472 RendDesc &
473 RendDesc::set_focus(const Point &x)
474 { focus=x; return *this; }
475
476
477 const Point &
478 RendDesc::get_tl()const
479 { return tl_; }
480
481 const Point &
482 RendDesc::get_br()const
483 { return br_; }
484
485 RendDesc &
486 RendDesc::set_tl(const Point &x)
487 {
488         if(FLAGS(flags,PX_ASPECT)) // "Pixel Aspect"
489         {
490                 Vector new_size(x-br_);
491                 new_size[0]=abs(new_size[0]);
492                 new_size[1]=abs(new_size[1]);
493
494                 Vector old_size(tl_-br_);
495                 old_size[0]=abs(old_size[0]);
496                 old_size[1]=abs(old_size[1]);
497
498                 if(new_size[0]!=old_size[0])
499                         w_=round_to_int(new_size[0]*w_/old_size[0]);
500
501                 if(new_size[1]!=old_size[1])
502                         h_=round_to_int(new_size[1]*h_/old_size[1]);
503         }
504
505         tl_=x; return *this;
506 }
507
508 RendDesc &
509 RendDesc::set_br(const Point &x)
510 {
511         if(FLAGS(flags,PX_ASPECT)) // "Pixel Aspect"
512         {
513                 Vector new_size(x-tl_);
514                 new_size[0]=abs(new_size[0]);
515                 new_size[1]=abs(new_size[1]);
516
517                 Vector old_size(tl_-br_);
518                 old_size[0]=abs(old_size[0]);
519                 old_size[1]=abs(old_size[1]);
520
521                 if(new_size[0]!=old_size[0])
522                         w_=round_to_int(new_size[0]*w_/old_size[0]);
523
524                 if(new_size[1]!=old_size[1])
525                         h_=round_to_int(new_size[1]*h_/old_size[1]);
526         }
527         br_=x; return *this;
528 }
529
530 RendDesc &
531 RendDesc::set_viewport(const Point &__tl, const Point &__br)
532 { tl_=__tl; br_=__br; return *this; }
533
534 RendDesc &
535 RendDesc::set_viewport(Vector::value_type a, Vector::value_type b, Vector::value_type c, Vector::value_type d)
536 { tl_=Point(a,b); br_=Point(c,d); return *this; }
537
538 Real
539 RendDesc::get_pw()const
540 {
541         return (br_[0] - tl_[0]) / w_;
542 }
543
544 Real
545 RendDesc::get_ph()const
546 {
547         return (br_[1] - tl_[1]) / h_;
548 }
549
550 RendDesc &
551 RendDesc::set_subwindow(int x, int y, int w, int h)
552 {
553         const Real pw(get_pw());
554         const Real ph(get_ph());
555
556         tl_[0]+=pw*x;
557         tl_[1]+=ph*y;
558
559         br_[0]-=pw*(w_-(x+w));
560         br_[1]-=ph*(h_-(y+h));
561
562         w_=w;
563         h_=h;
564
565         return *this;
566 }