moreupdates
[synfig.git] / synfig-core / trunk / src / synfig / value.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file value.cpp
3 **      \brief Template Header
4 **
5 **      $Id: value.cpp,v 1.1.1.1 2005/01/04 01:23:15 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 "value.h"
32 #include "general.h"
33 #include <ETL/stringf>
34 #include "canvas.h"
35 #include "gradient.h"
36
37
38
39 #include "vector.h"
40 #include "time.h"
41 #include "segment.h"
42 #include "color.h"
43
44 #endif
45
46 using namespace synfig;
47 using namespace std;
48 using namespace etl;
49
50 /* === M A C R O S ========================================================= */
51
52 /* === G L O B A L S ======================================================= */
53
54 /* === P R O C E D U R E S ================================================= */
55
56 /* === M E T H O D S ======================================================= */
57
58 ValueBase::ValueBase():type(TYPE_NIL),data(0),ref_count(0),loop_(0)
59 {
60 }
61
62 ValueBase::ValueBase(Type x):
63         type(x),
64         data(0),
65         loop_(0)
66 {
67
68         switch(type)
69         {
70         case TYPE_BOOL:
71                 static_cast<bool*>(data)=new bool();
72                 break;
73         case TYPE_INTEGER:
74                 static_cast<int*>(data)=new int();
75                 break;
76         case TYPE_ANGLE:
77                 static_cast<Angle*>(data)=new Angle();
78                 break;
79         case TYPE_VECTOR:
80                 static_cast<Vector*>(data)=new Vector();
81                 break;
82         case TYPE_TIME:
83                 static_cast<Time*>(data)=new Time();
84                 break;
85         case TYPE_REAL:
86                 static_cast<Real*>(data)=new Real();
87                 break;
88         case TYPE_COLOR:
89                 static_cast<Color*>(data)=new Color();
90                 break;
91         case TYPE_SEGMENT:
92                 static_cast<Segment*>(data)=new Segment();
93                 break;
94         case TYPE_BLINEPOINT:
95                 static_cast<BLinePoint*>(data)=new BLinePoint();
96                 break;
97         case TYPE_LIST:
98                 static_cast<list_type*>(data)=new list_type();
99                 break;
100         case TYPE_STRING:
101                 static_cast<String*>(data)=new String();
102                 break;
103         case TYPE_GRADIENT:
104                 static_cast<Gradient*>(data)=new Gradient();
105                 break;
106         case TYPE_CANVAS:
107                 static_cast<etl::handle<Canvas>*>(data)=new etl::handle<Canvas>();
108                 break;
109         default:
110                 break;
111         }
112 }
113
114 ValueBase::~ValueBase()
115 {
116         clear();
117 }
118
119 const char*
120 ValueBase::get(const char*)const
121 {
122         return get(String()).c_str();
123 }
124
125
126
127
128 void
129 ValueBase::set(Canvas* x)
130 {
131         clear();
132         if(x && x->is_inline())
133         {
134                 _set(etl::handle<Canvas>(x));
135         }
136         else
137         {
138                 _set(etl::loose_handle<Canvas>(x));
139         }
140         assert(get(x)==x);
141 }
142
143 void
144 ValueBase::set(etl::loose_handle<Canvas> x)
145 {
146         clear();
147         if(x && x->is_inline())
148         {
149                 _set(etl::handle<Canvas>(x));
150         }
151         else
152         {
153                 _set(etl::loose_handle<Canvas>(x));
154         }
155         assert(get(x)==x);
156 }
157
158 void
159 ValueBase::set(etl::handle<Canvas> x)
160 {
161         clear();
162         if(x && x->is_inline())
163         {
164                 _set(etl::handle<Canvas>(x));
165         }
166         else
167         {
168                 _set(etl::loose_handle<Canvas>(x));
169         }
170         assert(get(x)==x);
171 }
172
173 void
174 ValueBase::set(const list_type &x)
175 {
176         _set(x);
177 }
178
179 void
180 ValueBase::set(const char* x)
181 {
182         _set(String(x));
183 }
184
185 bool
186 ValueBase::is_valid()const
187 {
188         return type>TYPE_NIL && type<TYPE_END && ref_count;
189 }
190
191 bool
192 ValueBase::empty()const
193 {
194         return !is_valid() || ((type==TYPE_LIST)?get_list().empty():false);
195 }
196
197 ValueBase::Type
198 ValueBase::get_contained_type()const
199 {
200         if(type!=TYPE_LIST || empty())
201                 return TYPE_NIL;
202         return get_list().front().get_type();
203 }
204
205 ValueBase&
206 ValueBase::operator=(const ValueBase& x)
207 {
208         if(data!=x.data)
209         {
210                 clear();
211                 type=x.type;
212                 data=x.data;
213                 ref_count=x.ref_count;
214         }
215         loop_=x.loop_;
216         return *this;
217 }
218
219 void
220 ValueBase::clear()
221 {
222         if(ref_count.unique() && data)
223         {
224                 switch(type)
225                 {
226                 case TYPE_BOOL:
227                         delete static_cast<bool*>(data);
228                         break;
229                 case TYPE_INTEGER:
230                         delete static_cast<int*>(data);
231                         break;
232                 case TYPE_ANGLE:
233                         delete static_cast<Angle*>(data);
234                         break;
235                 case TYPE_VECTOR:
236                         delete static_cast<Vector*>(data);
237                         break;
238                 case TYPE_TIME:
239                         delete static_cast<Time*>(data);
240                         break;
241                 case TYPE_REAL:
242                         delete static_cast<Real*>(data);
243                         break;
244                 case TYPE_COLOR:
245                         delete static_cast<Color*>(data);
246                         break;
247                 case TYPE_SEGMENT:
248                         delete static_cast<Segment*>(data);
249                         break;
250                 case TYPE_BLINEPOINT:
251                         delete static_cast<BLinePoint*>(data);
252                         break;
253                 case TYPE_LIST:
254                         delete static_cast<list_type*>(data);
255                         break;
256                 case TYPE_STRING:
257                         delete static_cast<String*>(data);
258                         break;
259                 case TYPE_GRADIENT:
260                         delete static_cast<Gradient*>(data);
261                         break;
262
263
264                 case TYPE_CANVAS:
265                 {
266                         etl::handle<Canvas> canvas(get(etl::loose_handle<Canvas>()));
267                         if(canvas && canvas->is_inline())
268                         {
269                                 delete static_cast<etl::handle<Canvas>*>(data);
270                         }
271                         else
272                         {
273                                 delete static_cast<etl::loose_handle<Canvas>*>(data);
274                         }
275                         break;
276                 }
277                 default:
278                         break;
279                 }
280         }
281         
282         ref_count.detach();
283         data=0;
284         type=TYPE_NIL;
285 }
286
287
288 String
289 ValueBase::type_name(Type id)
290 {
291         switch(id)
292         {
293         case TYPE_REAL:
294                 return "real";
295         case TYPE_TIME:
296                 return "time";
297         case TYPE_INTEGER:
298                 return "integer";
299         case TYPE_BOOL:
300                 return "bool";
301         case TYPE_ANGLE:
302                 return "angle";
303         case TYPE_VECTOR:
304                 return "vector";
305         case TYPE_COLOR:
306                 return "color";
307         case TYPE_STRING:
308                 return "string";
309         case TYPE_CANVAS:
310                 return "canvas";
311         case TYPE_LIST:
312                 return "list";
313         case TYPE_SEGMENT:
314                 return "segment";
315         case TYPE_GRADIENT:
316                 return "gradient";
317         case TYPE_BLINEPOINT:
318                 return "bline_point";
319         case TYPE_NIL:
320                 return "nil";
321         default:
322                 break;
323         }
324         synfig::warning("Encountered unknown ValueBase with an Type of %d",id);
325 //      assert(0);
326         return "UNKNOWN";
327 }
328
329 ValueBase::Type
330 ValueBase::ident_type(const String &str)
331 {
332         if(str=="nil" || str=="null")
333                 return TYPE_NIL;
334         else if(str=="time" || str==_("time"))
335                 return TYPE_TIME;
336         else if(str=="real" || str=="float" || str==_("real"))
337                 return TYPE_REAL;
338         else if(str=="integer" || str=="int" || str==_("integer"))
339                 return TYPE_INTEGER;
340         else if(str=="bool" || str==_("bool"))
341                 return TYPE_BOOL;
342         else if(str=="angle" || str=="degrees" || str=="radians" || str=="rotations")
343                 return TYPE_ANGLE;
344         else if(str=="vector" || str=="point")
345                 return TYPE_VECTOR;
346         else if(str=="color")
347                 return TYPE_COLOR;
348         else if(str=="string")
349                 return TYPE_STRING;
350         else if(str=="canvas")
351                 return TYPE_CANVAS;
352         else if(str=="list")
353                 return TYPE_LIST;
354         else if(str=="segment")
355                 return TYPE_SEGMENT;
356         else if(str=="gradient")
357                 return TYPE_GRADIENT;
358         else if(str=="bline_point" || str=="blinepoint")
359                 return TYPE_BLINEPOINT;
360
361         return TYPE_NIL;
362 }
363
364 bool
365 ValueBase::operator==(const ValueBase& rhs)const
366 {
367         if(get_type()!=rhs.get_type())
368                 return false;
369         if(data==rhs.data)
370                 return true;
371         
372         switch(get_type())
373         {
374         case TYPE_TIME:
375                 return get(Time()).is_equal(rhs.get(Time()));
376         case TYPE_REAL:
377                 return abs(get(Real())-rhs.get(Real()))<=0.00000000000001;
378         case TYPE_INTEGER:
379                 return get(int())==rhs.get(int());
380         case TYPE_BOOL:
381                 return get(bool())==rhs.get(bool());
382         case TYPE_ANGLE:
383                 return get(Angle())==rhs.get(Angle());
384         case TYPE_VECTOR:
385                 return get(Vector()).is_equal_to(rhs.get(Vector()));
386         case TYPE_COLOR:
387                 return get(Color())==rhs.get(Color());
388         case TYPE_STRING:
389                 return get(String())==rhs.get(String());
390         case TYPE_CANVAS:
391                 return get(Canvas::LooseHandle())==rhs.get(Canvas::LooseHandle());
392         case TYPE_LIST:
393                 return get_list()==rhs.get_list();
394         case TYPE_SEGMENT:
395 //              return get(Segment())==rhs.get(Segment());
396         case TYPE_GRADIENT:
397 //              return get(Gradient())==rhs.get(Gradient());
398         case TYPE_BLINEPOINT:
399 //              return get(BLinePoint())==rhs.get(BLinePoint());
400         case TYPE_NIL:
401         default:
402                 return false;
403                 break;
404         }
405         return false;
406 }