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