30697efa95df6f1d8dc045869e47593cee04f7d2
[synfig.git] / synfig-core / trunk / src / synfig / canvas.cpp
1 /* === S Y N F I G ========================================================= */
2 /*!     \file canvas.cpp
3 **      \brief Canvas Class Member Definitions
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 #define SYNFIG_NO_ANGLE
27
28 #ifdef USING_PCH
29 #       include "pch.h"
30 #else
31 #ifdef HAVE_CONFIG_H
32 #       include <config.h>
33 #endif
34
35 #include "layer.h"
36 #include "canvas.h"
37 #include <cassert>
38 #include "exception.h"
39 #include "time.h"
40 #include "context.h"
41 #include "layer_pastecanvas.h"
42 #include "loadcanvas.h"
43 #include <sigc++/bind.h>
44
45 #endif
46
47 using namespace synfig;
48 using namespace etl;
49 using namespace std;
50
51 namespace synfig { extern Canvas::Handle open_canvas(const String &filename, String &errors, String &warnings); };
52
53 /* === M A C R O S ========================================================= */
54
55 #define ALLOW_CLONE_NON_INLINE_CANVASES
56
57 struct _CanvasCounter
58 {
59         static int counter;
60         ~_CanvasCounter()
61         {
62                 if(counter)
63                         synfig::error("%d canvases not yet deleted!",counter);
64         }
65 } _canvas_counter;
66
67 int _CanvasCounter::counter(0);
68
69 /* === G L O B A L S ======================================================= */
70
71 /* === P R O C E D U R E S ================================================= */
72
73 /* === M E T H O D S ======================================================= */
74
75 Canvas::Canvas(const String &id):
76         id_                     (id),
77         version_        (CURRENT_CANVAS_VERSION),
78         cur_time_       (0),
79         is_inline_      (false),
80         is_dirty_       (true),
81         op_flag_        (false)
82 {
83         _CanvasCounter::counter++;
84         clear();
85 }
86
87 void
88 Canvas::on_changed()
89 {
90         is_dirty_=true;
91         Node::on_changed();
92 }
93
94 Canvas::~Canvas()
95 {
96         // we were having a crash where pastecanvas layers were still
97         // refering to a canvas after it had been destroyed;  this code
98         // will stop the pastecanvas layers from refering to the canvas
99         // before the canvas is destroyed
100
101         // the set_sub_canvas(0) ends up deleting the parent-child link,
102         // which deletes the current element from the set we're iterating
103         // through, so we have to make sure we've incremented the iterator
104         // before we mess with the pastecanvas
105         std::set<Node*>::iterator iter = parent_set.begin();
106         while (iter != parent_set.end())
107         {
108                 Layer_PasteCanvas* paste_canvas = dynamic_cast<Layer_PasteCanvas*>(*iter);
109                 iter++;
110                 if(paste_canvas)
111                         paste_canvas->set_sub_canvas(0);
112                 else
113                         warning("destroyed canvas has a parent that is not a pastecanvas - please report if repeatable");
114         }
115
116         //if(is_inline() && parent_) assert(0);
117         _CanvasCounter::counter--;
118         clear();
119         begin_delete();
120 }
121
122 Canvas::iterator
123 Canvas::end()
124 {
125         return CanvasBase::end()-1;
126 }
127
128 Canvas::const_iterator
129 Canvas::end()const
130 {
131         return CanvasBase::end()-1;
132 }
133
134 Canvas::reverse_iterator
135 Canvas::rbegin()
136 {
137         return CanvasBase::rbegin()+1;
138 }
139
140 Canvas::const_reverse_iterator
141 Canvas::rbegin()const
142 {
143         return CanvasBase::rbegin()+1;
144 }
145
146 int
147 Canvas::size()const
148 {
149         return CanvasBase::size()-1;
150 }
151
152 void
153 Canvas::clear()
154 {
155         while(!empty())
156         {
157                 Layer::Handle layer(front());
158                 //if(layer->count()>2)synfig::info("before layer->count()=%d",layer->count());
159
160                 erase(begin());
161                 //if(layer->count()>1)synfig::info("after layer->count()=%d",layer->count());
162         }
163         //CanvasBase::clear();
164
165         // We need to keep a blank handle at the
166         // end of the image list, and acts at
167         // the bottom. Without it, the layers
168         // would just continue going when polled
169         // for a color.
170         CanvasBase::push_back(Layer::Handle());
171
172         changed();
173 }
174
175 bool
176 Canvas::empty()const
177 {
178         return CanvasBase::size()<=1;
179 }
180
181 Layer::Handle &
182 Canvas::back()
183 {
184         return *(CanvasBase::end()-1);
185 }
186
187 const Layer::Handle &
188 Canvas::back()const
189 {
190         return *(CanvasBase::end()-1);
191 }
192
193 Context
194 Canvas::get_context()const
195 {
196         return begin();
197 }
198
199 const ValueNodeList &
200 Canvas::value_node_list()const
201 {
202         if(is_inline() && parent_)
203                 return parent_->value_node_list();
204         return value_node_list_;
205 }
206
207 KeyframeList &
208 Canvas::keyframe_list()
209 {
210         if(is_inline() && parent_)
211                 return parent_->keyframe_list();
212         return keyframe_list_;
213 }
214
215 const KeyframeList &
216 Canvas::keyframe_list()const
217 {
218         if(is_inline() && parent_)
219                 return parent_->keyframe_list();
220         return keyframe_list_;
221 }
222
223 etl::handle<Layer>
224 Canvas::find_layer(const Point &pos)
225 {
226         return get_context().hit_check(pos);
227 }
228
229 static bool
230 valid_id(const String &x)
231 {
232         static const char bad_chars[]=" :#@$^&()*";
233         unsigned int i;
234
235         if(!x.empty() && x[0]>='0' && x[0]<='9')
236                 return false;
237
238         for(i=0;i<sizeof(bad_chars);i++)
239                 if(x.find_first_of(bad_chars[i])!=string::npos)
240                         return false;
241
242         return true;
243 }
244
245 void
246 Canvas::set_id(const String &x)
247 {
248         if(is_inline() && parent_)
249                 throw runtime_error("Inline Canvas cannot have an ID");
250
251         if(!valid_id(x))
252                 throw runtime_error("Invalid ID");
253         id_=x;
254         signal_id_changed_();
255 }
256
257 void
258 Canvas::set_name(const String &x)
259 {
260         name_=x;
261         signal_meta_data_changed()("name");
262         signal_meta_data_changed("name")();
263 }
264
265 void
266 Canvas::set_author(const String &x)
267 {
268         author_=x;
269         signal_meta_data_changed()("author");
270         signal_meta_data_changed("author")();
271 }
272
273 void
274 Canvas::set_description(const String &x)
275 {
276         description_=x;
277         signal_meta_data_changed()("description");
278         signal_meta_data_changed("description")();
279 }
280
281 void
282 Canvas::set_time(Time t)const
283 {
284         if(is_dirty_ || !get_time().is_equal(t))
285         {
286 #if 0
287                 if(is_root())
288                 {
289                         synfig::info("is_dirty_=%d",is_dirty_);
290                         synfig::info("get_time()=%f",(float)get_time());
291                         synfig::info("t=%f",(float)t);
292                 }
293 #endif
294
295                 // ...questionable
296                 const_cast<Canvas&>(*this).cur_time_=t;
297
298                 is_dirty_=false;
299                 get_context().set_time(t);
300         }
301         is_dirty_=false;
302 }
303
304 Canvas::LooseHandle
305 Canvas::get_root()const
306 {
307         return parent_?parent_->get_root().get():const_cast<synfig::Canvas *>(this);
308 }
309
310 int
311 Canvas::get_depth(etl::handle<Layer> layer)const
312 {
313         const_iterator iter;
314         int i(0);
315         for(iter=begin();iter!=end();++iter,i++)
316         {
317                 if(layer==*iter)
318                         return i;
319         }
320         return -1;
321 }
322
323 String
324 Canvas::get_relative_id(etl::loose_handle<const Canvas> x)const
325 {
326         if(x->get_root()==this)
327                 return ":";
328         if(is_inline() && parent_)
329                 return parent_->_get_relative_id(x);
330         return _get_relative_id(x);
331 }
332
333 String
334 Canvas::_get_relative_id(etl::loose_handle<const Canvas> x)const
335 {
336         if(is_inline() && parent_)
337                 return parent_->_get_relative_id(x);
338
339         if(x.get()==this)
340                 return String();
341
342         if(parent()==x.get())
343                 return get_id();
344
345         String id;
346
347         const Canvas* canvas=this;
348
349         for(;!canvas->is_root();canvas=canvas->parent().get())
350                 id=':'+canvas->get_id()+id;
351
352         if(x && get_root()!=x->get_root())
353         {
354                 //String file_name=get_file_name();
355                 //String file_path=x->get_file_path();
356
357                 String file_name;
358                 if(is_absolute_path(get_file_name()))
359                         file_name=etl::relative_path(x->get_file_path(),get_file_name());
360                 else
361                         file_name=get_file_name();
362
363                 // If the path of X is inside of file_name,
364                 // then remove it.
365                 //if(file_name.size()>file_path.size())
366                 //      if(file_path==String(file_name,0,file_path.size()))
367                 //              file_name.erase(0,file_path.size()+1);
368
369                 id=file_name+'#'+id;
370         }
371
372         return id;
373 }
374
375 ValueNode::Handle
376 Canvas::find_value_node(const String &id)
377 {
378         return
379                 ValueNode::Handle::cast_const(
380                         const_cast<const Canvas*>(this)->find_value_node(id)
381                 );
382 }
383
384 ValueNode::ConstHandle
385 Canvas::find_value_node(const String &id)const
386 {
387         if(is_inline() && parent_)
388                 return parent_->find_value_node(id);
389
390         if(id.empty())
391                 throw Exception::IDNotFound("Empty ID");
392
393         // If we do not have any resolution, then we assume that the
394         // request is for this immediate canvas
395         if(id.find_first_of(':')==string::npos && id.find_first_of('#')==string::npos)
396                 return value_node_list_.find(id);
397
398         String canvas_id(id,0,id.rfind(':'));
399         String value_node_id(id,id.rfind(':')+1);
400         if(canvas_id.empty())
401                 canvas_id=':';
402         //synfig::warning("constfind:value_node_id: "+value_node_id);
403         //synfig::warning("constfind:canvas_id: "+canvas_id);
404
405         String warnings;
406         return find_canvas(canvas_id, warnings)->value_node_list_.find(value_node_id);
407 }
408
409 ValueNode::Handle
410 Canvas::surefind_value_node(const String &id)
411 {
412         if(is_inline() && parent_)
413                 return parent_->surefind_value_node(id);
414
415         if(id.empty())
416                 throw Exception::IDNotFound("Empty ID");
417
418         // If we do not have any resolution, then we assume that the
419         // request is for this immediate canvas
420         if(id.find_first_of(':')==string::npos && id.find_first_of('#')==string::npos)
421                 return value_node_list_.surefind(id);
422
423         String canvas_id(id,0,id.rfind(':'));
424         String value_node_id(id,id.rfind(':')+1);
425         if(canvas_id.empty())
426                 canvas_id=':';
427
428         String warnings;
429         return surefind_canvas(canvas_id,warnings)->value_node_list_.surefind(value_node_id);
430 }
431
432 void
433 Canvas::add_value_node(ValueNode::Handle x, const String &id)
434 {
435         if(is_inline() && parent_)
436                 return parent_->add_value_node(x,id);
437 //              throw runtime_error("You cannot add a ValueNode to an inline Canvas");
438
439         if(x->is_exported())
440                 throw runtime_error("ValueNode is already exported");
441
442         if(id.empty())
443                 throw Exception::BadLinkName("Empty ID");
444
445         if(id.find_first_of(':',0)!=string::npos)
446                 throw Exception::BadLinkName("Bad character");
447
448         try
449         {
450                 if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id)))
451                         throw Exception::IDNotFound("add_value_node()");
452
453                 throw Exception::IDAlreadyExists(id);
454         }
455         catch(Exception::IDNotFound)
456         {
457                 x->set_id(id);
458
459                 x->set_parent_canvas(this);
460
461                 if(!value_node_list_.add(x))
462                 {
463                         synfig::error("Unable to add ValueNode");
464                         throw std::runtime_error("Unable to add ValueNode");
465                 }
466
467                 return;
468         }
469 }
470
471 /*
472 void
473 Canvas::rename_value_node(ValueNode::Handle x, const String &id)
474 {
475         if(id.empty())
476                 throw Exception::BadLinkName("Empty ID");
477
478         if(id.find_first_of(": ",0)!=string::npos)
479                 throw Exception::BadLinkName("Bad character");
480
481         try
482         {
483                 if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id)))
484                         throw Exception::IDNotFound("rename_value_node");
485                 throw Exception::IDAlreadyExists(id);
486         }
487         catch(Exception::IDNotFound)
488         {
489                 x->set_id(id);
490
491                 return;
492         }
493 }
494 */
495
496 void
497 Canvas::remove_value_node(ValueNode::Handle x)
498 {
499         if(is_inline() && parent_)
500                 return parent_->remove_value_node(x);
501 //              throw Exception::IDNotFound("Canvas::remove_value_node() was called from an inline canvas");
502
503         if(!x)
504                 throw Exception::IDNotFound("Canvas::remove_value_node() was passed empty handle");
505
506         if(!value_node_list_.erase(x))
507                 throw Exception::IDNotFound("Canvas::remove_value_node(): ValueNode was not found inside of this canvas");
508
509         //x->set_parent_canvas(0);
510
511         x->set_id("");
512 }
513
514 Canvas::Handle
515 Canvas::surefind_canvas(const String &id, String &warnings)
516 {
517         if(is_inline() && parent_)
518                 return parent_->surefind_canvas(id,warnings);
519
520         if(id.empty())
521                 return this;
522
523         // If the ID contains a "#" character, then a filename is
524         // expected on the left side.
525         if(id.find_first_of('#')!=string::npos)
526         {
527                 // If '#' is the first character, remove it
528                 // and attempt to parse the ID again.
529                 if(id[0]=='#')
530                         return surefind_canvas(String(id,1),warnings);
531
532                 //! \todo This needs a lot more optimization
533                 String file_name(id,0,id.find_first_of('#'));
534                 String external_id(id,id.find_first_of('#')+1);
535
536                 file_name=unix_to_local_path(file_name);
537
538                 Canvas::Handle external_canvas;
539
540                 // If the composition is already open, then use it.
541                 if(externals_.count(file_name))
542                         external_canvas=externals_[file_name];
543                 else
544                 {
545                         String errors;
546                         if(is_absolute_path(file_name))
547                                 external_canvas=open_canvas(file_name, errors, warnings);
548                         else
549                                 external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors, warnings);
550
551                         if(!external_canvas)
552                                 throw runtime_error(errors);
553                         externals_[file_name]=external_canvas;
554                 }
555
556                 return Handle::cast_const(external_canvas.constant()->find_canvas(external_id, warnings));
557         }
558
559         // If we do not have any resolution, then we assume that the
560         // request is for this immediate canvas
561         if(id.find_first_of(':')==string::npos)
562         {
563                 Children::iterator iter;
564
565                 // Search for the image in the image list,
566                 // and return it if it is found
567                 for(iter=children().begin();iter!=children().end();iter++)
568                         if(id==(*iter)->get_id())
569                                 return *iter;
570
571                 // Create a new canvas and return it
572                 //synfig::warning("Implicitly creating canvas named "+id);
573                 return new_child_canvas(id);
574         }
575
576         // If the first character is the separator, then
577         // this references the root canvas.
578         if(id[0]==':')
579                 return get_root()->surefind_canvas(string(id,1),warnings);
580
581         // Now we know that the requested Canvas is in a child
582         // of this canvas. We have to find that canvas and
583         // call "find_canvas" on it, and return the result.
584
585         String canvas_name=string(id,0,id.find_first_of(':'));
586
587         Canvas::Handle child_canvas=surefind_canvas(canvas_name,warnings);
588
589         return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1),warnings);
590 }
591
592 Canvas::Handle
593 Canvas::find_canvas(const String &id, String &warnings)
594 {
595         return
596                 Canvas::Handle::cast_const(
597                         const_cast<const Canvas*>(this)->find_canvas(id, warnings)
598                 );
599 }
600
601 Canvas::ConstHandle
602 Canvas::find_canvas(const String &id, String &warnings)const
603 {
604         if(is_inline() && parent_)
605                 return parent_->find_canvas(id, warnings);
606
607         if(id.empty())
608                 return this;
609
610         // If the ID contains a "#" character, then a filename is
611         // expected on the left side.
612         if(id.find_first_of('#')!=string::npos)
613         {
614                 // If '#' is the first character, remove it
615                 // and attempt to parse the ID again.
616                 if(id[0]=='#')
617                         return find_canvas(String(id,1), warnings);
618
619                 //! \todo This needs a lot more optimization
620                 String file_name(id,0,id.find_first_of('#'));
621                 String external_id(id,id.find_first_of('#')+1);
622
623                 file_name=unix_to_local_path(file_name);
624
625                 Canvas::Handle external_canvas;
626
627                 // If the composition is already open, then use it.
628                 if(externals_.count(file_name))
629                         external_canvas=externals_[file_name];
630                 else
631                 {
632                         String errors, warnings;
633                         if(is_absolute_path(file_name))
634                                 external_canvas=open_canvas(file_name, errors, warnings);
635                         else
636                                 external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name, errors, warnings);
637
638                         if(!external_canvas)
639                                 throw runtime_error(errors);
640                         externals_[file_name]=external_canvas;
641                 }
642
643                 return Handle::cast_const(external_canvas.constant()->find_canvas(external_id, warnings));
644         }
645
646         // If we do not have any resolution, then we assume that the
647         // request is for this immediate canvas
648         if(id.find_first_of(':')==string::npos)
649         {
650                 Children::const_iterator iter;
651
652                 // Search for the image in the image list,
653                 // and return it if it is found
654                 for(iter=children().begin();iter!=children().end();iter++)
655                         if(id==(*iter)->get_id())
656                                 return *iter;
657
658                 throw Exception::IDNotFound("Child Canvas in Parent Canvas: (child)"+id);
659         }
660
661         // If the first character is the separator, then
662         // this references the root canvas.
663         if(id[0]==':')
664                 return get_root()->find_canvas(string(id,1), warnings);
665
666         // Now we know that the requested Canvas is in a child
667         // of this canvas. We have to find that canvas and
668         // call "find_canvas" on it, and return the result.
669
670         String canvas_name=string(id,0,id.find_first_of(':'));
671
672         Canvas::ConstHandle child_canvas=find_canvas(canvas_name, warnings);
673
674         return child_canvas->find_canvas(string(id,id.find_first_of(':')+1), warnings);
675 }
676
677 Canvas::Handle
678 Canvas::create()
679 {
680         return new Canvas("Untitled");
681 }
682
683 void
684 Canvas::push_back(etl::handle<Layer> x)
685 {
686 //      int i(x->count());
687         insert(end(),x);
688         //if(x->count()!=i+1)synfig::info("push_back before %d, after %d",i,x->count());
689 }
690
691 void
692 Canvas::push_front(etl::handle<Layer> x)
693 {
694 //      int i(x->count());
695         insert(begin(),x);
696         //if(x->count()!=i+1)synfig::error("push_front before %d, after %d",i,x->count());
697 }
698
699 void
700 Canvas::insert(iterator iter,etl::handle<Layer> x)
701 {
702 //      int i(x->count());
703         CanvasBase::insert(iter,x);
704
705         /*if(x->count()!=i+1)
706         {
707                 synfig::error(__FILE__":%d: Canvas::insert(): ***FAILURE*** before %d, after %d",__LINE__,i,x->count());
708                 return;
709                 //throw runtime_error("Canvas Insertion Failed");
710         }*/
711
712         x->set_canvas(this);
713
714         add_child(x.get());
715
716         LooseHandle correct_canvas(this);
717         //while(correct_canvas->is_inline())correct_canvas=correct_canvas->parent();
718         Layer::LooseHandle loose_layer(x);
719
720         add_connection(loose_layer,
721                                    sigc::connection::connection(
722                                            x->signal_added_to_group().connect(
723                                                    sigc::bind(
724                                                            sigc::mem_fun(
725                                                                    *correct_canvas,
726                                                                    &Canvas::add_group_pair),
727                                                            loose_layer))));
728         add_connection(loose_layer,
729                                    sigc::connection::connection(
730                                            x->signal_removed_from_group().connect(
731                                                    sigc::bind(
732                                                            sigc::mem_fun(
733                                                                    *correct_canvas,
734                                                                    &Canvas::remove_group_pair),
735                                                            loose_layer))));
736
737         if(!x->get_group().empty())
738                 add_group_pair(x->get_group(),x);
739
740         changed();
741 }
742
743 void
744 Canvas::push_back_simple(etl::handle<Layer> x)
745 {
746         CanvasBase::insert(end(),x);
747         changed();
748 }
749
750 void
751 Canvas::erase(iterator iter)
752 {
753         if(!(*iter)->get_group().empty())
754                 remove_group_pair((*iter)->get_group(),(*iter));
755
756         // HACK: We really shouldn't be wiping
757         // out these signals entirely. We should
758         // only be removing the specific connections
759         // that we made. At the moment, I'm too
760         // lazy to add the code to keep track
761         // of those connections, and no one else
762         // is using these signals, so I'll just
763         // leave these next two lines like they
764         // are for now - darco 07-30-2004
765
766         // so don't wipe them out entirely
767         // - dooglus 09-21-2007
768         disconnect_connections(*iter);
769
770         if(!op_flag_)remove_child(iter->get());
771
772         CanvasBase::erase(iter);
773         if(!op_flag_)changed();
774 }
775
776 Canvas::Handle
777 Canvas::clone(const GUID& deriv_guid)const
778 {
779         synfig::String name;
780         if(is_inline())
781                 name="inline";
782         else
783         {
784                 name=get_id()+"_CLONE";
785
786 #ifndef ALLOW_CLONE_NON_INLINE_CANVASES
787                 throw runtime_error("Cloning of non-inline canvases is not yet supported");
788 #endif  // ALLOW_CLONE_NON_INLINE_CANVASES
789         }
790
791         Handle canvas(new Canvas(name));
792
793         if(is_inline())
794         {
795                 canvas->is_inline_=true;
796                 // \todo this was setting parent_=0 - is there a reason for that?
797                 // this was causing bug 1838132, where cloning an inline canvas that contains an imported image fails
798                 // it was failing to ascertain the absolute pathname of the imported image, since it needs the pathname
799                 // of the canvas to get that, which is stored in the parent canvas
800                 canvas->parent_=parent();
801                 canvas->rend_desc() = rend_desc();
802                 //canvas->set_inline(parent());
803         }
804
805         canvas->set_guid(get_guid()^deriv_guid);
806
807         const_iterator iter;
808         for(iter=begin();iter!=end();++iter)
809         {
810                 Layer::Handle layer((*iter)->clone(deriv_guid));
811                 if(layer)
812                 {
813                         assert(layer.count()==1);
814                         int presize(size());
815                         canvas->push_back(layer);
816                         if(!(layer.count()>1))
817                         {
818                                 synfig::error("Canvas::clone(): Cloned layer insertion failure!");
819                                 synfig::error("Canvas::clone(): \tlayer.count()=%d",layer.count());
820                                 synfig::error("Canvas::clone(): \tlayer->get_name()=%s",layer->get_name().c_str());
821                                 synfig::error("Canvas::clone(): \tbefore size()=%d",presize);
822                                 synfig::error("Canvas::clone(): \tafter size()=%d",size());
823                         }
824                         assert(layer.count()>1);
825                 }
826                 else
827                 {
828                         synfig::error("Unable to clone layer");
829                 }
830         }
831
832         canvas->signal_group_pair_removed().clear();
833         canvas->signal_group_pair_added().clear();
834
835         return canvas;
836 }
837
838 void
839 Canvas::set_inline(LooseHandle parent)
840 {
841         if(is_inline_ && parent_)
842         {
843
844         }
845
846         id_="inline";
847         is_inline_=true;
848         parent_=parent;
849
850         // Have the parent inherit all of the group stuff
851
852         std::map<String,std::set<etl::handle<Layer> > >::const_iterator iter;
853
854         for(iter=group_db_.begin();iter!=group_db_.end();++iter)
855         {
856                 parent->group_db_[iter->first].insert(iter->second.begin(),iter->second.end());
857         }
858
859         rend_desc()=parent->rend_desc();
860 }
861
862 Canvas::Handle
863 Canvas::create_inline(Handle parent)
864 {
865         assert(parent);
866         //if(parent->is_inline())
867         //      return create_inline(parent->parent());
868
869         Handle canvas(new Canvas("inline"));
870         canvas->set_inline(parent);
871         return canvas;
872 }
873
874 Canvas::Handle
875 Canvas::new_child_canvas()
876 {
877         if(is_inline() && parent_)
878                 return parent_->new_child_canvas();
879 //              runtime_error("You cannot create a child Canvas in an inline Canvas");
880
881         // Create a new canvas
882         children().push_back(create());
883         Canvas::Handle canvas(children().back());
884
885         canvas->parent_=this;
886
887         canvas->rend_desc()=rend_desc();
888
889         return canvas;
890 }
891
892 Canvas::Handle
893 Canvas::new_child_canvas(const String &id)
894 {
895         if(is_inline() && parent_)
896                 return parent_->new_child_canvas(id);
897 //              runtime_error("You cannot create a child Canvas in an inline Canvas");
898
899         // Create a new canvas
900         children().push_back(create());
901         Canvas::Handle canvas(children().back());
902
903         canvas->set_id(id);
904         canvas->parent_=this;
905         canvas->rend_desc()=rend_desc();
906
907         return canvas;
908 }
909
910 Canvas::Handle
911 Canvas::add_child_canvas(Canvas::Handle child_canvas, const synfig::String& id)
912 {
913         if(is_inline() && parent_)
914                 return parent_->add_child_canvas(child_canvas,id);
915
916         if(child_canvas->parent() && !child_canvas->is_inline())
917                 throw std::runtime_error("Cannot add child canvas because it belongs to someone else!");
918
919         if(!valid_id(id))
920                 throw runtime_error("Invalid ID");
921
922         try
923         {
924                 String warnings;
925                 find_canvas(id, warnings);
926                 throw Exception::IDAlreadyExists(id);
927         }
928         catch(Exception::IDNotFound)
929         {
930                 if(child_canvas->is_inline())
931                         child_canvas->is_inline_=false;
932                 child_canvas->id_=id;
933                 children().push_back(child_canvas);
934                 child_canvas->parent_=this;
935         }
936
937         return child_canvas;
938 }
939
940 void
941 Canvas::remove_child_canvas(Canvas::Handle child_canvas)
942 {
943         if(is_inline() && parent_)
944                 return parent_->remove_child_canvas(child_canvas);
945
946         if(child_canvas->parent_!=this)
947                 throw runtime_error("Given child does not belong to me");
948
949         if(find(children().begin(),children().end(),child_canvas)==children().end())
950                 throw Exception::IDNotFound(child_canvas->get_id());
951
952         children().remove(child_canvas);
953
954         child_canvas->parent_=0;
955 }
956
957 void
958 Canvas::set_file_name(const String &file_name)
959 {
960         if(parent())
961                 parent()->set_file_name(file_name);
962         else
963         {
964                 String old_name(file_name_);
965                 file_name_=file_name;
966
967                 // when a canvas is made, its name is ""
968                 // then, before it's saved or even edited, it gets a name like "Synfig Animation 23", in the local language
969                 // we don't want to register the canvas' filename in the canvas map until it gets a real filename
970                 if (old_name != "")
971                 {
972                         file_name_=file_name;
973                         std::map<synfig::String, etl::loose_handle<Canvas> >::iterator iter;
974                         for(iter=get_open_canvas_map().begin();iter!=get_open_canvas_map().end();++iter)
975                                 if(iter->second==this)
976                                         break;
977                         if (iter == get_open_canvas_map().end())
978                                 CanvasParser::register_canvas_in_map(this, file_name);
979                         else
980                                 signal_file_name_changed_();
981                 }
982         }
983 }
984
985 sigc::signal<void>&
986 Canvas::signal_file_name_changed()
987 {
988         if(parent())
989                 return parent()->signal_file_name_changed();
990         else
991                 return signal_file_name_changed_;
992 }
993
994 String
995 Canvas::get_file_name()const
996 {
997         if(parent())
998                 return parent()->get_file_name();
999         return file_name_;
1000 }
1001
1002 String
1003 Canvas::get_file_path()const
1004 {
1005         if(parent())
1006                 return parent()->get_file_path();
1007         return dirname(file_name_);
1008 }
1009
1010 String
1011 Canvas::get_meta_data(const String& key)const
1012 {
1013         if(!meta_data_.count(key))
1014                 return String();
1015         return meta_data_.find(key)->second;
1016 }
1017
1018 void
1019 Canvas::set_meta_data(const String& key, const String& data)
1020 {
1021         if(meta_data_[key]!=data)
1022         {
1023                 meta_data_[key]=data;
1024                 signal_meta_data_changed()(key);
1025                 signal_meta_data_changed(key)();
1026         }
1027 }
1028
1029 void
1030 Canvas::erase_meta_data(const String& key)
1031 {
1032         if(meta_data_.count(key))
1033         {
1034                 meta_data_.erase(key);
1035                 signal_meta_data_changed()(key);
1036                 signal_meta_data_changed(key)();
1037         }
1038 }
1039
1040 std::list<String>
1041 Canvas::get_meta_data_keys()const
1042 {
1043         std::list<String> ret;
1044
1045         std::map<String,String>::const_iterator iter;
1046
1047         for(iter=meta_data_.begin();!(iter==meta_data_.end());++iter)
1048                 ret.push_back(iter->first);
1049
1050         return ret;
1051 }
1052
1053 /* note - the "Motion Blur" and "Duplicate" layers need the dynamic
1054                   parameters of any PasteCanvas layers they loop over to be
1055                   maintained.  When the variables in the following function
1056                   refer to "motion blur", they mean either of these two
1057                   layers. */
1058 void
1059 synfig::optimize_layers(Time time, Context context, Canvas::Handle op_canvas, bool seen_motion_blur_in_parent)
1060 {
1061         Context iter;
1062
1063         std::vector< std::pair<float,Layer::Handle> > sort_list;
1064         int i, motion_blur_i=0; // motion_blur_i is for resolving which layer comes first in the event of a z_depth tie
1065         float motion_blur_z_depth=0; // the z_depth of the least deep motion blur layer in this context
1066         bool seen_motion_blur_locally = false;
1067         bool motion_blurred; // the final result - is this layer blurred or not?
1068
1069         // If the parent didn't cause us to already be motion blurred,
1070         // check whether there's a motion blur in this context,
1071         // and if so, calculate its z_depth.
1072         if (!seen_motion_blur_in_parent)
1073                 for(iter=context,i=0;*iter;iter++,i++)
1074                 {
1075                         Layer::Handle layer=*iter;
1076
1077                         // If the layer isn't active, don't worry about it
1078                         if(!layer->active())
1079                                 continue;
1080
1081                         // Any layer with an amount of zero is implicitly disabled.
1082                         ValueBase value(layer->get_param("amount"));
1083                         if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
1084                                 continue;
1085
1086                         if(layer->get_name()=="MotionBlur" || layer->get_name()=="duplicate")
1087                         {
1088                                 float z_depth(layer->get_z_depth()*1.0001+i);
1089
1090                                 // If we've seen a motion blur before in this context...
1091                                 if (seen_motion_blur_locally)
1092                                 {
1093                                         // ... then we're only interested in this one if it's less deep...
1094                                         if (z_depth < motion_blur_z_depth)
1095                                         {
1096                                                 motion_blur_z_depth = z_depth;
1097                                                 motion_blur_i = i;
1098                                         }
1099                                 }
1100                                 // ... otherwise we're always interested in it.
1101                                 else
1102                                 {
1103                                         motion_blur_z_depth = z_depth;
1104                                         motion_blur_i = i;
1105                                         seen_motion_blur_locally = true;
1106                                 }
1107                         }
1108                 }
1109
1110         // Go ahead and start romping through the canvas to paste
1111         for(iter=context,i=0;*iter;iter++,i++)
1112         {
1113                 Layer::Handle layer=*iter;
1114                 float z_depth(layer->get_z_depth()*1.0001+i);
1115
1116                 // If the layer isn't active, don't worry about it
1117                 if(!layer->active())
1118                         continue;
1119
1120                 // Any layer with an amount of zero is implicitly disabled.
1121                 ValueBase value(layer->get_param("amount"));
1122                 if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
1123                         continue;
1124
1125                 // note: this used to include "&& paste_canvas->get_time_offset()==0", but then
1126                 //               time-shifted layers weren't being sorted by z-depth (bug #1806852)
1127                 if(layer->get_name()=="PasteCanvas")
1128                 {
1129                         Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
1130
1131                         // we need to blur the sub canvas if:
1132                         // our parent is blurred,
1133                         // or the child is lower than a local blur,
1134                         // or the child is at the same z_depth as a local blur, but later in the context
1135
1136 #if 0 // DEBUG
1137                         if (seen_motion_blur_in_parent)                                 synfig::info("seen BLUR in parent\n");
1138                         else if (seen_motion_blur_locally)
1139                                 if (z_depth > motion_blur_z_depth)                      synfig::info("paste is deeper than BLUR\n");
1140                                 else if (z_depth == motion_blur_z_depth) {      synfig::info("paste is same depth as BLUR\n");
1141                                         if (i > motion_blur_i)                                  synfig::info("paste is physically deeper than BLUR\n");
1142                                         else                                                                    synfig::info("paste is less physically deep than BLUR\n");
1143                                 } else                                                                          synfig::info("paste is less deep than BLUR\n");
1144                         else                                                                                    synfig::info("no BLUR at all\n");
1145 #endif  // DEBUG
1146
1147                         motion_blurred = (seen_motion_blur_in_parent ||
1148                                                           (seen_motion_blur_locally &&
1149                                                            (z_depth > motion_blur_z_depth ||
1150                                                                 (z_depth == motion_blur_z_depth && i > motion_blur_i))));
1151
1152                         Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
1153                         Canvas::Handle paste_sub_canvas = paste_canvas->get_sub_canvas();
1154                         if(paste_sub_canvas)
1155                                 optimize_layers(time, paste_sub_canvas->get_context(),sub_canvas,motion_blurred);
1156
1157 // \todo: uncommenting the following breaks the rendering of at least examples/backdrop.sifz quite severely
1158 // #define SYNFIG_OPTIMIZE_PASTE_CANVAS
1159 #ifdef SYNFIG_OPTIMIZE_PASTE_CANVAS
1160                         Canvas::iterator sub_iter;
1161
1162                         // Determine if we can just remove the paste canvas altogether
1163                         if (paste_canvas->get_blend_method()    == Color::BLEND_COMPOSITE       &&
1164                                 paste_canvas->get_amount()                      == 1.0f                                         &&
1165                                 paste_canvas->get_zoom()                        == 0                                            &&
1166                                 paste_canvas->get_time_offset()         == 0                                            &&
1167                                 paste_canvas->get_origin()                      == Point(0,0)                           )
1168                                 try {
1169                                         for(sub_iter=sub_canvas->begin();sub_iter!=sub_canvas->end();++sub_iter)
1170                                         {
1171                                                 Layer* layer=sub_iter->get();
1172
1173                                                 // any layers that deform end up breaking things
1174                                                 // so do things the old way if we run into anything like this
1175                                                 if(!dynamic_cast<Layer_NoDeform*>(layer))
1176                                                         throw int();
1177
1178                                                 ValueBase value(layer->get_param("blend_method"));
1179                                                 if(value.get_type()!=ValueBase::TYPE_INTEGER || value.get(int())!=(int)Color::BLEND_COMPOSITE)
1180                                                         throw int();
1181                                         }
1182
1183                                         // It has turned out that we don't need a paste canvas
1184                                         // layer, so just go ahead and add all the layers onto
1185                                         // the current stack and be done with it
1186                                         while(sub_canvas->size())
1187                                         {
1188                                                 sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,sub_canvas->front()));
1189                                                 //op_canvas->push_back_simple(sub_canvas->front());
1190                                                 sub_canvas->pop_front();
1191                                         }
1192                                         continue;
1193                                 }
1194                                 catch(int)
1195                                 { }
1196 #endif  // SYNFIG_OPTIMIZE_PASTE_CANVAS
1197
1198                         Layer::Handle new_layer(Layer::create("PasteCanvas"));
1199                         dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(false);
1200                         if (motion_blurred)
1201                         {
1202                                 Layer::DynamicParamList dynamic_param_list(paste_canvas->dynamic_param_list());
1203                                 for(Layer::DynamicParamList::const_iterator iter(dynamic_param_list.begin()); iter != dynamic_param_list.end(); ++iter)
1204                                         new_layer->connect_dynamic_param(iter->first, iter->second);
1205                         }
1206                         Layer::ParamList param_list(paste_canvas->get_param_list());
1207                         //param_list.erase("canvas");
1208                         new_layer->set_param_list(param_list);
1209                         dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_sub_canvas(sub_canvas);
1210                         dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(true);
1211                         layer=new_layer;
1212                 }
1213                 else                                    // not a PasteCanvas - does it use blend method 'Straight'?
1214                 {
1215                         /* when we use the 'straight' blend method, every pixel on the layer affects the layers underneath,
1216                          * not just the non-transparent pixels; the following workarea wraps non-pastecanvas layers in a
1217                          * new pastecanvas to ensure that the straight blend affects the full plane, not just the area
1218                          * within the layer's bounding box
1219                          */
1220
1221                         // \todo: this code probably needs modification to work properly with motionblur and duplicate
1222                         etl::handle<Layer_Composite> composite = etl::handle<Layer_Composite>::cast_dynamic(layer);
1223
1224                         /* some layers (such as circle) don't touch pixels that aren't
1225                          * part of the circle, so they don't get blended correctly when
1226                          * using a straight blend.  so we encapsulate the circle, and the
1227                          * encapsulation layer takes care of the transparent pixels
1228                          * for us.  if we do that for all layers, however, then the
1229                          * distortion layers no longer work, since they have no
1230                          * context to work on.  the Layer::reads_context() method
1231                          * returns true for layers which need to be able to see
1232                          * their context.  we can't encapsulate those.
1233                          */
1234                         if (composite &&
1235                                 Color::is_straight(composite->get_blend_method()) &&
1236                                 !composite->reads_context())
1237                         {
1238                                 Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
1239                                 // don't use clone() because it re-randomizes the seeds of any random valuenodes
1240                                 sub_canvas->push_back(composite = composite->simple_clone());
1241                                 layer = Layer::create("PasteCanvas");
1242                                 composite->set_description(strprintf("Wrapped clone of '%s'", composite->get_non_empty_description().c_str()));
1243                                 layer->set_description(strprintf("PasteCanvas wrapper for '%s'", composite->get_non_empty_description().c_str()));
1244                                 Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
1245                                 paste_canvas->set_blend_method(composite->get_blend_method());
1246                                 paste_canvas->set_amount(composite->get_amount());
1247                                 sub_canvas->set_time(time); // region and outline don't calculate their bounding rects until their time is set
1248                                 composite->set_blend_method(Color::BLEND_STRAIGHT); // do this before calling set_sub_canvas(), but after set_time()
1249                                 composite->set_amount(1.0f); // after set_time()
1250                                 paste_canvas->set_sub_canvas(sub_canvas);
1251                         }
1252                 }
1253
1254                 sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,layer));
1255                 //op_canvas->push_back_simple(layer);
1256         }
1257
1258         //sort_list.sort();
1259         stable_sort(sort_list.begin(),sort_list.end());
1260         std::vector< std::pair<float,Layer::Handle> >::iterator iter2;
1261         for(iter2=sort_list.begin();iter2!=sort_list.end();++iter2)
1262                 op_canvas->push_back_simple(iter2->second);
1263         op_canvas->op_flag_=true;
1264 }
1265
1266 void
1267 Canvas::get_times_vfunc(Node::time_set &set) const
1268 {
1269         const_iterator  i = begin(),
1270                                 iend = end();
1271
1272         for(; i != iend; ++i)
1273         {
1274                 const Node::time_set &tset = (*i)->get_times();
1275                 set.insert(tset.begin(),tset.end());
1276         }
1277 }
1278
1279 std::set<etl::handle<Layer> >
1280 Canvas::get_layers_in_group(const String&group)
1281 {
1282         if(is_inline() && parent_)
1283                 return parent_->get_layers_in_group(group);
1284
1285         if(group_db_.count(group)==0)
1286                 return std::set<etl::handle<Layer> >();
1287         return group_db_.find(group)->second;
1288 }
1289
1290 std::set<String>
1291 Canvas::get_groups()const
1292 {
1293         if(is_inline() && parent_)
1294                 return parent_->get_groups();
1295
1296         std::set<String> ret;
1297         std::map<String,std::set<etl::handle<Layer> > >::const_iterator iter;
1298         for(iter=group_db_.begin();iter!=group_db_.end();++iter)
1299                 ret.insert(iter->first);
1300         return ret;
1301 }
1302
1303 int
1304 Canvas::get_group_count()const
1305 {
1306         if(is_inline() && parent_)
1307                 return parent_->get_group_count();
1308
1309         return group_db_.size();
1310 }
1311
1312 void
1313 Canvas::add_group_pair(String group, etl::handle<Layer> layer)
1314 {
1315         group_db_[group].insert(layer);
1316         if(group_db_[group].size()==1)
1317                 signal_group_added()(group);
1318         else
1319                 signal_group_changed()(group);
1320
1321         signal_group_pair_added()(group,layer);
1322
1323         if(is_inline()  && parent_)
1324                 return parent_->add_group_pair(group,layer);
1325 }
1326
1327 void
1328 Canvas::remove_group_pair(String group, etl::handle<Layer> layer)
1329 {
1330         group_db_[group].erase(layer);
1331
1332         signal_group_pair_removed()(group,layer);
1333
1334         if(group_db_[group].empty())
1335         {
1336                 group_db_.erase(group);
1337                 signal_group_removed()(group);
1338         }
1339         else
1340                 signal_group_changed()(group);
1341
1342         if(is_inline() && parent_)
1343                 return parent_->remove_group_pair(group,layer);
1344 }
1345
1346 void
1347 Canvas::add_connection(etl::loose_handle<Layer> layer, sigc::connection connection)
1348 {
1349         connections_[layer].push_back(connection);
1350 }
1351
1352 void
1353 Canvas::disconnect_connections(etl::loose_handle<Layer> layer)
1354 {
1355         std::vector<sigc::connection>::iterator iter;
1356         for(iter=connections_[layer].begin();iter!=connections_[layer].end();++iter)
1357                 iter->disconnect();
1358         connections_[layer].clear();
1359 }
1360
1361 void
1362 Canvas::rename_group(const String&old_name,const String&new_name)
1363 {
1364         if(is_inline() && parent_)
1365                 return parent_->rename_group(old_name,new_name);
1366
1367         {
1368                 std::map<String,std::set<etl::handle<Layer> > >::iterator iter;
1369                 iter=group_db_.find(old_name);
1370                 if(iter!=group_db_.end())
1371                 for(++iter;iter!=group_db_.end() && iter->first.find(old_name)==0;iter=group_db_.find(old_name),++iter)
1372                 {
1373                         String name(iter->first,old_name.size(),String::npos);
1374                         name=new_name+name;
1375                         rename_group(iter->first,name);
1376                 }
1377         }
1378
1379         std::set<etl::handle<Layer> > layers(get_layers_in_group(old_name));
1380         std::set<etl::handle<Layer> >::iterator iter;
1381
1382         for(iter=layers.begin();iter!=layers.end();++iter)
1383         {
1384                 (*iter)->remove_from_group(old_name);
1385                 (*iter)->add_to_group(new_name);
1386         }
1387 }
1388
1389 void
1390 Canvas::register_external_canvas(String file_name, Handle canvas)
1391 {
1392         if(!is_absolute_path(file_name)) file_name = get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name;
1393         externals_[file_name] = canvas;
1394 }
1395
1396 #ifdef _DEBUG
1397 void
1398 Canvas::show_externals(String file, int line, String text) const
1399 {
1400         printf("  .----- (externals for %lx '%s')\n  |  %s:%d %s\n", ulong(this), get_name().c_str(), file.c_str(), line, text.c_str());
1401         std::map<String, Handle>::iterator iter;
1402         for (iter = externals_.begin(); iter != externals_.end(); iter++)
1403         {
1404                 synfig::String first(iter->first);
1405                 etl::loose_handle<Canvas> second(iter->second);
1406                 printf("  |    %40s : %lx (%d)\n", first.c_str(), ulong(&*second), second->count());
1407         }
1408         printf("  `-----\n\n");
1409 }
1410 #endif  // _DEBUG