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