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