515087e818f5a19aa2b11e23856efd69ab2c9079
[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$
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 "value.h"
33 #include "general.h"
34 #include <ETL/stringf>
35 #include "canvas.h"
36 #include "gradient.h"
37
38
39
40 #include "vector.h"
41 #include "time.h"
42 #include "segment.h"
43 #include "color.h"
44
45 #endif
46
47 using namespace synfig;
48 using namespace std;
49 using namespace etl;
50
51 /* === M A C R O S ========================================================= */
52
53 /* === G L O B A L S ======================================================= */
54
55 /* === P R O C E D U R E S ================================================= */
56
57 /* === M E T H O D S ======================================================= */
58
59 ValueBase::ValueBase():type(TYPE_NIL),data(0),ref_count(0),loop_(0)
60 {
61 }
62
63 ValueBase::ValueBase(Type x):
64         type(x),
65         data(0),
66         loop_(0)
67 {
68         switch(type)
69         {
70         case TYPE_BOOL:                 data=static_cast<void*>(new bool());                            break;
71         case TYPE_INTEGER:              data=static_cast<void*>(new int());                                     break;
72         case TYPE_ANGLE:                data=static_cast<void*>(new Angle());                           break;
73         case TYPE_VECTOR:               data=static_cast<void*>(new Vector());                          break;
74         case TYPE_TIME:                 data=static_cast<void*>(new Time());                            break;
75         case TYPE_REAL:                 data=static_cast<void*>(new Real());                            break;
76         case TYPE_COLOR:                data=static_cast<void*>(new Color());                           break;
77         case TYPE_SEGMENT:              data=static_cast<void*>(new Segment());                         break;
78         case TYPE_BLINEPOINT:   data=static_cast<void*>(new BLinePoint());                      break;
79         case TYPE_LIST:                 data=static_cast<void*>(new list_type());                       break;
80         case TYPE_STRING:               data=static_cast<void*>(new String());                          break;
81         case TYPE_GRADIENT:             data=static_cast<void*>(new Gradient());                        break;
82         case TYPE_CANVAS:               data=static_cast<void*>(new etl::handle<Canvas>());     break;
83         default:                                                                                                                                        break;
84         }
85 }
86
87 ValueBase::~ValueBase()
88 {
89         clear();
90 }
91
92 const char*
93 ValueBase::get(const char*)const
94 {
95         return get(String()).c_str();
96 }
97
98 void
99 ValueBase::set(Canvas* x)
100 {
101         clear();
102         if(x && x->is_inline())
103         {
104                 _set(etl::handle<Canvas>(x));
105         }
106         else
107         {
108                 _set(etl::loose_handle<Canvas>(x));
109         }
110         assert(get(x)==x);
111 }
112
113 void
114 ValueBase::set(etl::loose_handle<Canvas> x)
115 {
116         clear();
117         if(x && x->is_inline())
118                 _set(etl::handle<Canvas>(x));
119         else
120                 _set(etl::loose_handle<Canvas>(x));
121         assert(get(x)==x);
122 }
123
124 void
125 ValueBase::set(etl::handle<Canvas> x)
126 {
127         clear();
128         if(x && x->is_inline())
129                 _set(etl::handle<Canvas>(x));
130         else
131                 _set(etl::loose_handle<Canvas>(x));
132         assert(get(x)==x);
133 }
134
135 void
136 ValueBase::set(const list_type &x)
137 {
138         _set(x);
139 }
140
141 void
142 ValueBase::set(const char* x)
143 {
144         _set(String(x));
145 }
146
147 bool
148 ValueBase::is_valid()const
149 {
150         return type>TYPE_NIL && type<TYPE_END && ref_count;
151 }
152
153 bool
154 ValueBase::empty()const
155 {
156         return !is_valid() || ((type==TYPE_LIST)?get_list().empty():false);
157 }
158
159 ValueBase::Type
160 ValueBase::get_contained_type()const
161 {
162         if(type!=TYPE_LIST || empty())
163                 return TYPE_NIL;
164         return get_list().front().get_type();
165 }
166
167 ValueBase&
168 ValueBase::operator=(const ValueBase& x)
169 {
170         if(data!=x.data)
171         {
172                 clear();
173                 type=x.type;
174                 data=x.data;
175                 ref_count=x.ref_count;
176         }
177         loop_=x.loop_;
178         return *this;
179 }
180
181 void
182 ValueBase::clear()
183 {
184         if(ref_count.unique() && data)
185         {
186                 switch(type)
187                 {
188                 case TYPE_BOOL:                 delete static_cast<bool*>(data);                break;
189                 case TYPE_INTEGER:              delete static_cast<int*>(data);                 break;
190                 case TYPE_ANGLE:                delete static_cast<Angle*>(data);               break;
191                 case TYPE_VECTOR:               delete static_cast<Vector*>(data);              break;
192                 case TYPE_TIME:                 delete static_cast<Time*>(data);                break;
193                 case TYPE_REAL:                 delete static_cast<Real*>(data);                break;
194                 case TYPE_COLOR:                delete static_cast<Color*>(data);               break;
195                 case TYPE_SEGMENT:              delete static_cast<Segment*>(data);             break;
196                 case TYPE_BLINEPOINT:   delete static_cast<BLinePoint*>(data);  break;
197                 case TYPE_LIST:                 delete static_cast<list_type*>(data);   break;
198                 case TYPE_STRING:               delete static_cast<String*>(data);              break;
199                 case TYPE_GRADIENT:             delete static_cast<Gradient*>(data);    break;
200                 case TYPE_CANVAS:
201                 {
202                         etl::handle<Canvas> canvas(get(etl::loose_handle<Canvas>()));
203                         if(canvas && canvas->is_inline())
204                                 delete static_cast<etl::handle<Canvas>*>(data);
205                         else
206                                 delete static_cast<etl::loose_handle<Canvas>*>(data);
207                         break;
208                 }
209                 default:
210                         break;
211                 }
212         }
213
214         ref_count.detach();
215         data=0;
216         type=TYPE_NIL;
217 }
218
219
220 String
221 ValueBase::type_name(Type id)
222 {
223         // don't internationalize these type names - they're using in .sif files
224         switch(id)
225         {
226         case TYPE_REAL:                 return "real";
227         case TYPE_TIME:                 return "time";
228         case TYPE_INTEGER:              return "integer";
229         case TYPE_BOOL:                 return "bool";
230         case TYPE_ANGLE:                return "angle";
231         case TYPE_VECTOR:               return "vector";
232         case TYPE_COLOR:                return "color";
233         case TYPE_STRING:               return "string";
234         case TYPE_CANVAS:               return "canvas";
235         case TYPE_LIST:                 return "list";
236         case TYPE_SEGMENT:              return "segment";
237         case TYPE_GRADIENT:             return "gradient";
238         case TYPE_BLINEPOINT:   return "bline_point";
239         case TYPE_NIL:                  return "nil";
240         default:
241                 break;
242         }
243         synfig::warning("Encountered unknown ValueBase with an Type of %d",id);
244 //      assert(0);
245         return "UNKNOWN";
246 }
247
248 ValueBase::Type
249 ValueBase::ident_type(const String &str)
250 {
251         if(str=="nil" ||
252            str=="null")                         return TYPE_NIL;
253         else if(str=="time" ||
254                         str==_("time"))         return TYPE_TIME;
255         else if(str=="real" ||
256                         str=="float" ||
257                         str==_("real"))         return TYPE_REAL;
258         else if(str=="integer" ||
259                         str=="int" ||
260                         str==_("integer"))      return TYPE_INTEGER;
261         else if(str=="bool" ||
262                         str==_("bool"))         return TYPE_BOOL;
263         else if(str=="angle" ||
264                         str=="degrees" ||
265                         str=="radians" ||
266                         str=="rotations")       return TYPE_ANGLE;
267         else if(str=="vector" ||
268                         str=="point")           return TYPE_VECTOR;
269         else if(str=="color")           return TYPE_COLOR;
270         else if(str=="string")          return TYPE_STRING;
271         else if(str=="canvas")          return TYPE_CANVAS;
272         else if(str=="list")            return TYPE_LIST;
273         else if(str=="segment")         return TYPE_SEGMENT;
274         else if(str=="gradient")        return TYPE_GRADIENT;
275         else if(str=="bline_point" ||
276                         str=="blinepoint")      return TYPE_BLINEPOINT;
277
278         return TYPE_NIL;
279 }
280
281 bool
282 ValueBase::operator==(const ValueBase& rhs)const
283 {
284         if(get_type()!=rhs.get_type())
285                 return false;
286         if(data==rhs.data)
287                 return true;
288
289         switch(get_type())
290         {
291         case TYPE_TIME:                    return get(Time()).is_equal(rhs.get(Time()));
292         case TYPE_REAL:                    return abs(get(Real())-rhs.get(Real()))<=0.00000000000001;
293         case TYPE_INTEGER:                 return get(int())==rhs.get(int());
294         case TYPE_BOOL:                    return get(bool())==rhs.get(bool());
295         case TYPE_ANGLE:                   return get(Angle())==rhs.get(Angle());
296         case TYPE_VECTOR:                  return get(Vector()).is_equal_to(rhs.get(Vector()));
297         case TYPE_COLOR:                   return get(Color())==rhs.get(Color());
298         case TYPE_STRING:                  return get(String())==rhs.get(String());
299         case TYPE_CANVAS:                  return get(Canvas::LooseHandle())==rhs.get(Canvas::LooseHandle());
300         case TYPE_LIST:                    return get_list()==rhs.get_list();
301         case TYPE_SEGMENT:              // return get(Segment())==rhs.get(Segment());
302         case TYPE_GRADIENT:             // return get(Gradient())==rhs.get(Gradient());
303         case TYPE_BLINEPOINT:   // return get(BLinePoint())==rhs.get(BLinePoint());
304         case TYPE_NIL:
305         default:                                   return false;
306         }
307         return false;
308 }