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