Using mutexes around accesses to refcounts seems to make the Windows build much less...
[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 void
100 ValueBase::set(Canvas* x)
101 {
102         clear();
103         if(x && x->is_inline())
104         {
105                 _set(etl::handle<Canvas>(x));
106         }
107         else
108         {
109                 _set(etl::loose_handle<Canvas>(x));
110         }
111         assert(get(x)==x);
112 }
113
114 void
115 ValueBase::set(etl::loose_handle<Canvas> x)
116 {
117         clear();
118         if(x && x->is_inline())
119                 _set(etl::handle<Canvas>(x));
120         else
121                 _set(etl::loose_handle<Canvas>(x));
122         assert(get(x)==x);
123 }
124
125 void
126 ValueBase::set(etl::handle<Canvas> x)
127 {
128         clear();
129         if(x && x->is_inline())
130                 _set(etl::handle<Canvas>(x));
131         else
132                 _set(etl::loose_handle<Canvas>(x));
133         assert(get(x)==x);
134 }
135
136 void
137 ValueBase::set(const list_type &x)
138 {
139         _set(x);
140 }
141
142 void
143 ValueBase::set(const char* x)
144 {
145         _set(String(x));
146 }
147
148 void
149 ValueBase::set(char* x)
150 {
151         _set(String(x));
152 }
153
154 bool
155 ValueBase::is_valid()const
156 {
157         return type>TYPE_NIL && type<TYPE_END && ref_count;
158 }
159
160 bool
161 ValueBase::empty()const
162 {
163         return !is_valid() || ((type==TYPE_LIST)?get_list().empty():false);
164 }
165
166 ValueBase::Type
167 ValueBase::get_contained_type()const
168 {
169         if(type!=TYPE_LIST || empty())
170                 return TYPE_NIL;
171         return get_list().front().get_type();
172 }
173
174 ValueBase&
175 ValueBase::operator=(const ValueBase& x)
176 {
177         if(data!=x.data)
178         {
179                 clear();
180                 type=x.type;
181                 data=x.data;
182                 ref_count=x.ref_count;
183         }
184         loop_=x.loop_;
185         return *this;
186 }
187
188 void
189 ValueBase::clear()
190 {
191         if(ref_count.unique() && data)
192         {
193                 switch(type)
194                 {
195                 case TYPE_BOOL:                 delete static_cast<bool*>(data);                break;
196                 case TYPE_INTEGER:              delete static_cast<int*>(data);                 break;
197                 case TYPE_ANGLE:                delete static_cast<Angle*>(data);               break;
198                 case TYPE_TIME:                 delete static_cast<Time*>(data);                break;
199                 case TYPE_REAL:                 delete static_cast<Real*>(data);                break;
200                 case TYPE_VECTOR:               delete static_cast<Vector*>(data);              break;
201                 case TYPE_COLOR:                delete static_cast<Color*>(data);               break;
202                 case TYPE_SEGMENT:              delete static_cast<Segment*>(data);             break;
203                 case TYPE_BLINEPOINT:   delete static_cast<BLinePoint*>(data);  break;
204                 case TYPE_LIST:                 delete static_cast<list_type*>(data);   break;
205                 case TYPE_CANVAS:
206                 {
207                         etl::handle<Canvas> canvas(get(etl::loose_handle<Canvas>()));
208                         if(canvas && canvas->is_inline())
209                                 delete static_cast<etl::handle<Canvas>*>(data);
210                         else
211                                 delete static_cast<etl::loose_handle<Canvas>*>(data);
212                         break;
213                 }
214                 case TYPE_STRING:               delete static_cast<String*>(data);              break;
215                 case TYPE_GRADIENT:             delete static_cast<Gradient*>(data);    break;
216                 default:
217                         break;
218                 }
219         }
220
221         ref_count.detach();
222         data=0;
223         type=TYPE_NIL;
224 }
225
226
227 String
228 ValueBase::type_name(Type id)
229 {
230         // don't internationalize these type names - they're using in .sif files
231         switch(id)
232         {
233                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
234         case TYPE_BOOL:                 return N_("bool");
235                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
236         case TYPE_INTEGER:              return N_("integer");
237                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
238         case TYPE_ANGLE:                return N_("angle");
239                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
240         case TYPE_TIME:                 return N_("time");
241                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
242         case TYPE_REAL:                 return N_("real");
243                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
244         case TYPE_VECTOR:               return N_("vector");
245                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
246         case TYPE_COLOR:                return N_("color");
247                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
248         case TYPE_SEGMENT:              return N_("segment");
249                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
250         case TYPE_BLINEPOINT:   return N_("bline_point");
251                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
252         case TYPE_LIST:                 return N_("list");
253                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
254         case TYPE_CANVAS:               return N_("canvas");
255                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
256         case TYPE_STRING:               return N_("string");
257                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
258         case TYPE_GRADIENT:             return N_("gradient");
259                 /* TRANSLATORS: this is the name of a type -- see http://synfig.org/Types */
260         case TYPE_NIL:                  return N_("nil");
261         default:
262                 break;
263         }
264         synfig::warning("Encountered unknown ValueBase with an Type of %d",id);
265 //      assert(0);
266         return "UNKNOWN";
267 }
268
269 String
270 ValueBase::type_local_name(Type id)
271 {
272         return dgettext("synfig",type_name(id).c_str());
273 }
274
275 ValueBase::Type
276 ValueBase::ident_type(const String &str)
277 {
278         if(str=="nil" ||
279            str=="null")                         return TYPE_NIL;
280         else if(str=="time" ||
281                         str==_("time"))         return TYPE_TIME;
282         else if(str=="real" ||
283                         str=="float" ||
284                         str==_("real"))         return TYPE_REAL;
285         else if(str=="integer" ||
286                         str=="int" ||
287                         str==_("integer"))      return TYPE_INTEGER;
288         else if(str=="bool" ||
289                         str==_("bool"))         return TYPE_BOOL;
290         else if(str=="angle" ||
291                         str=="degrees" ||
292                         str=="radians" ||
293                         str=="rotations")       return TYPE_ANGLE;
294         else if(str=="vector" ||
295                         str=="point")           return TYPE_VECTOR;
296         else if(str=="color")           return TYPE_COLOR;
297         else if(str=="string")          return TYPE_STRING;
298         else if(str=="canvas")          return TYPE_CANVAS;
299         else if(str=="list")            return TYPE_LIST;
300         else if(str=="segment")         return TYPE_SEGMENT;
301         else if(str=="gradient")        return TYPE_GRADIENT;
302         else if(str=="bline_point" ||
303                         str=="blinepoint")      return TYPE_BLINEPOINT;
304
305         return TYPE_NIL;
306 }
307
308 bool
309 ValueBase::operator==(const ValueBase& rhs)const
310 {
311         if(get_type()!=rhs.get_type())
312                 return false;
313         if(data==rhs.data)
314                 return true;
315
316         switch(get_type())
317         {
318         case TYPE_TIME:                    return get(Time()).is_equal(rhs.get(Time()));
319         case TYPE_REAL:                    return abs(get(Real())-rhs.get(Real()))<=0.00000000000001;
320         case TYPE_INTEGER:                 return get(int())==rhs.get(int());
321         case TYPE_BOOL:                    return get(bool())==rhs.get(bool());
322         case TYPE_ANGLE:                   return get(Angle())==rhs.get(Angle());
323         case TYPE_VECTOR:                  return get(Vector()).is_equal_to(rhs.get(Vector()));
324         case TYPE_COLOR:                   return get(Color())==rhs.get(Color());
325         case TYPE_STRING:                  return get(String())==rhs.get(String());
326         case TYPE_CANVAS:                  return get(Canvas::LooseHandle())==rhs.get(Canvas::LooseHandle());
327         case TYPE_LIST:                    return get_list()==rhs.get_list();
328         case TYPE_SEGMENT:              // return get(Segment())==rhs.get(Segment());
329         case TYPE_GRADIENT:             // return get(Gradient())==rhs.get(Gradient());
330         case TYPE_BLINEPOINT:   // return get(BLinePoint())==rhs.get(BLinePoint());
331         case TYPE_NIL:
332         default:                                   return false;
333         }
334         return false;
335 }