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