Remove spaces and tabs at end of lines.
[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 **      Copyright (c) 2007, 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 "value.h"
34 #include "general.h"
35 #include <ETL/stringf>
36 #include "canvas.h"
37 #include "gradient.h"
38
39
40
41 #include "vector.h"
42 #include "time.h"
43 #include "segment.h"
44 #include "color.h"
45
46 #endif
47
48 using namespace synfig;
49 using namespace std;
50 using namespace etl;
51
52 /* === M A C R O S ========================================================= */
53
54 /* === G L O B A L S ======================================================= */
55
56 /* === P R O C E D U R E S ================================================= */
57
58 /* === M E T H O D S ======================================================= */
59
60 ValueBase::ValueBase():type(TYPE_NIL),data(0),ref_count(0),loop_(0)
61 {
62 }
63
64 ValueBase::ValueBase(Type x):
65         type(x),
66         data(0),
67         loop_(0)
68 {
69         switch(type)
70         {
71         case TYPE_BOOL:                 data=static_cast<void*>(new bool());                            break;
72         case TYPE_INTEGER:              data=static_cast<void*>(new int());                                     break;
73         case TYPE_ANGLE:                data=static_cast<void*>(new Angle());                           break;
74         case TYPE_VECTOR:               data=static_cast<void*>(new Vector());                          break;
75         case TYPE_TIME:                 data=static_cast<void*>(new Time());                            break;
76         case TYPE_REAL:                 data=static_cast<void*>(new Real());                            break;
77         case TYPE_COLOR:                data=static_cast<void*>(new Color());                           break;
78         case TYPE_SEGMENT:              data=static_cast<void*>(new Segment());                         break;
79         case TYPE_BLINEPOINT:   data=static_cast<void*>(new BLinePoint());                      break;
80         case TYPE_LIST:                 data=static_cast<void*>(new list_type());                       break;
81         case TYPE_STRING:               data=static_cast<void*>(new String());                          break;
82         case TYPE_GRADIENT:             data=static_cast<void*>(new Gradient());                        break;
83         case TYPE_CANVAS:               data=static_cast<void*>(new etl::handle<Canvas>());     break;
84         default:                                                                                                                                        break;
85         }
86 }
87
88 ValueBase::~ValueBase()
89 {
90         clear();
91 }
92
93 const char*
94 ValueBase::get(const char*)const
95 {
96         return get(String()).c_str();
97 }
98
99 #ifdef _DEBUG
100 String
101 ValueBase::get_string() const
102 {
103         switch(type)
104         {
105         case TYPE_NIL:                  return "Nil";
106         case TYPE_BOOL:                 return strprintf("Bool (%s)", get(bool()) ? "true" : "false");
107         case TYPE_INTEGER:              return strprintf("Integer (%s)", get(int()));
108         case TYPE_ANGLE:                return strprintf("Angle (%.2f)", Angle::deg(get(Angle())).get());
109
110                 // All types after this point are larger than 32 bits
111
112         case TYPE_TIME:                 return strprintf("Time (%s)", get(Time()).get_string().c_str());
113         case TYPE_REAL:                 return strprintf("Real (%f)", get(Real()));
114
115                 // All types after this point are larger than 64 bits
116
117         case TYPE_VECTOR:               return strprintf("Vector (%f, %f)", get(Vector())[0], get(Vector())[1]);
118         case TYPE_COLOR:                return strprintf("Color (%s)", get(Color()).get_string().c_str());
119         case TYPE_SEGMENT:              return strprintf("Segment ((%f, %f) to (%f, %f))", get(Segment()).p1[0], get(Segment()).p1[1], get(Segment()).p2[0], get(Segment()).p2[1]);
120         case TYPE_BLINEPOINT:   return strprintf("BLinePoint (%s)", get(BLinePoint()).get_vertex()[0], get(BLinePoint()).get_vertex()[1]);
121
122                 // All types after this point require construction/destruction
123
124         case TYPE_LIST:                 return strprintf("List (%d elements)", get(list_type()).size());
125         case TYPE_CANVAS:               return strprintf("Canvas (%s)", get(etl::loose_handle<Canvas>())->get_id().c_str());
126         case TYPE_STRING:               return strprintf("String (%s)", get(String()).c_str());
127         case TYPE_GRADIENT:             return strprintf("Gradient (%d cpoints)", get(Gradient()).size());
128         default:                                return "Invalid type";
129         }
130 }
131 #endif  // _DEBUG
132
133 void
134 ValueBase::set(Canvas* x)
135 {
136         clear();
137         if(x && x->is_inline())
138         {
139                 _set(etl::handle<Canvas>(x));
140         }
141         else
142         {
143                 _set(etl::loose_handle<Canvas>(x));
144         }
145         assert(get(x)==x);
146 }
147
148 void
149 ValueBase::set(etl::loose_handle<Canvas> x)
150 {
151         clear();
152         if(x && x->is_inline())
153                 _set(etl::handle<Canvas>(x));
154         else
155                 _set(etl::loose_handle<Canvas>(x));
156         assert(get(x)==x);
157 }
158
159 void
160 ValueBase::set(etl::handle<Canvas> x)
161 {
162         clear();
163         if(x && x->is_inline())
164                 _set(etl::handle<Canvas>(x));
165         else
166                 _set(etl::loose_handle<Canvas>(x));
167         assert(get(x)==x);
168 }
169
170 void
171 ValueBase::set(const list_type &x)
172 {
173         _set(x);
174 }
175
176 void
177 ValueBase::set(const char* x)
178 {
179         _set(String(x));
180 }
181
182 void
183 ValueBase::set(char* x)
184 {
185         _set(String(x));
186 }
187
188 bool
189 ValueBase::is_valid()const
190 {
191         return type>TYPE_NIL && type<TYPE_END && ref_count;
192 }
193
194 bool
195 ValueBase::empty()const
196 {
197         return !is_valid() || ((type==TYPE_LIST)?get_list().empty():false);
198 }
199
200 ValueBase::Type
201 ValueBase::get_contained_type()const
202 {
203         if(type!=TYPE_LIST || empty())
204                 return TYPE_NIL;
205         return get_list().front().get_type();
206 }
207
208 ValueBase&
209 ValueBase::operator=(const ValueBase& x)
210 {
211         if(data!=x.data)
212         {
213                 clear();
214                 type=x.type;
215                 data=x.data;
216                 ref_count=x.ref_count;
217         }
218         loop_=x.loop_;
219         return *this;
220 }
221
222 void
223 ValueBase::clear()
224 {
225         if(ref_count.unique() && data)
226         {
227                 switch(type)
228                 {
229                 case TYPE_BOOL:                 delete static_cast<bool*>(data);                break;
230                 case TYPE_INTEGER:              delete static_cast<int*>(data);                 break;
231                 case TYPE_ANGLE:                delete static_cast<Angle*>(data);               break;
232                 case TYPE_TIME:                 delete static_cast<Time*>(data);                break;
233                 case TYPE_REAL:                 delete static_cast<Real*>(data);                break;
234                 case TYPE_VECTOR:               delete static_cast<Vector*>(data);              break;
235                 case TYPE_COLOR:                delete static_cast<Color*>(data);               break;
236                 case TYPE_SEGMENT:              delete static_cast<Segment*>(data);             break;
237                 case TYPE_BLINEPOINT:   delete static_cast<BLinePoint*>(data);  break;
238                 case TYPE_LIST:                 delete static_cast<list_type*>(data);   break;
239                 case TYPE_CANVAS:
240                 {
241                         etl::handle<Canvas> canvas(get(etl::loose_handle<Canvas>()));
242                         if(canvas && canvas->is_inline())
243                                 delete static_cast<etl::handle<Canvas>*>(data);
244                         else
245                                 delete static_cast<etl::loose_handle<Canvas>*>(data);
246                         break;
247                 }
248                 case TYPE_STRING:               delete static_cast<String*>(data);              break;
249                 case TYPE_GRADIENT:             delete static_cast<Gradient*>(data);    break;
250                 default:
251                         break;
252                 }
253         }
254
255         ref_count.detach();
256         data=0;
257         type=TYPE_NIL;
258 }
259
260
261 String
262 ValueBase::type_name(Type id)
263 {
264         // don't internationalize these type names - they're using in .sif files
265         switch(id)
266         {
267                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
268         case TYPE_BOOL:                 return N_("bool");
269                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
270         case TYPE_INTEGER:              return N_("integer");
271                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
272         case TYPE_ANGLE:                return N_("angle");
273                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
274         case TYPE_TIME:                 return N_("time");
275                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
276         case TYPE_REAL:                 return N_("real");
277                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
278         case TYPE_VECTOR:               return N_("vector");
279                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
280         case TYPE_COLOR:                return N_("color");
281                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
282         case TYPE_SEGMENT:              return N_("segment");
283                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
284         case TYPE_BLINEPOINT:   return N_("bline_point");
285                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
286         case TYPE_LIST:                 return N_("list");
287                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
288         case TYPE_CANVAS:               return N_("canvas");
289                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
290         case TYPE_STRING:               return N_("string");
291                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
292         case TYPE_GRADIENT:             return N_("gradient");
293                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
294         case TYPE_NIL:                  return N_("nil");
295         default:
296                 break;
297         }
298         synfig::warning("Encountered unknown ValueBase with an Type of %d",id);
299 //      assert(0);
300         return "UNKNOWN";
301 }
302
303 String
304 ValueBase::type_local_name(Type id)
305 {
306         return dgettext("synfig",type_name(id).c_str());
307 }
308
309 ValueBase::Type
310 ValueBase::ident_type(const String &str)
311 {
312         if(str=="nil" ||
313            str=="null")                         return TYPE_NIL;
314         else if(str=="time" ||
315                         str==_("time"))         return TYPE_TIME;
316         else if(str=="real" ||
317                         str=="float" ||
318                         str==_("real"))         return TYPE_REAL;
319         else if(str=="integer" ||
320                         str=="int" ||
321                         str==_("integer"))      return TYPE_INTEGER;
322         else if(str=="bool" ||
323                         str==_("bool"))         return TYPE_BOOL;
324         else if(str=="angle" ||
325                         str=="degrees" ||
326                         str=="radians" ||
327                         str=="rotations")       return TYPE_ANGLE;
328         else if(str=="vector" ||
329                         str=="point")           return TYPE_VECTOR;
330         else if(str=="color")           return TYPE_COLOR;
331         else if(str=="string")          return TYPE_STRING;
332         else if(str=="canvas")          return TYPE_CANVAS;
333         else if(str=="list")            return TYPE_LIST;
334         else if(str=="segment")         return TYPE_SEGMENT;
335         else if(str=="gradient")        return TYPE_GRADIENT;
336         else if(str=="bline_point" ||
337                         str=="blinepoint")      return TYPE_BLINEPOINT;
338
339         return TYPE_NIL;
340 }
341
342 bool
343 ValueBase::operator==(const ValueBase& rhs)const
344 {
345         if(get_type()!=rhs.get_type())
346                 return false;
347         if(data==rhs.data)
348                 return true;
349
350         switch(get_type())
351         {
352         case TYPE_TIME:                    return get(Time()).is_equal(rhs.get(Time()));
353         case TYPE_REAL:                    return abs(get(Real())-rhs.get(Real()))<=0.00000000000001;
354         case TYPE_INTEGER:                 return get(int())==rhs.get(int());
355         case TYPE_BOOL:                    return get(bool())==rhs.get(bool());
356         case TYPE_ANGLE:                   return get(Angle())==rhs.get(Angle());
357         case TYPE_VECTOR:                  return get(Vector()).is_equal_to(rhs.get(Vector()));
358         case TYPE_COLOR:                   return get(Color())==rhs.get(Color());
359         case TYPE_STRING:                  return get(String())==rhs.get(String());
360         case TYPE_CANVAS:                  return get(Canvas::LooseHandle())==rhs.get(Canvas::LooseHandle());
361         case TYPE_LIST:                    return get_list()==rhs.get_list();
362         case TYPE_SEGMENT:              // return get(Segment())==rhs.get(Segment());
363         case TYPE_GRADIENT:             // return get(Gradient())==rhs.get(Gradient());
364         case TYPE_BLINEPOINT:   // return get(BLinePoint())==rhs.get(BLinePoint());
365         case TYPE_NIL:
366         default:                                   return false;
367         }
368         return false;
369 }