1 /* === S Y N F I G ========================================================= */
3 ** \brief Canvas Class Member Definitions
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007 Chris Moore
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.
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.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
26 #define SYNFIG_NO_ANGLE
38 #include "exception.h"
41 #include "layer_pastecanvas.h"
42 #include <sigc++/bind.h>
46 using namespace synfig;
50 namespace synfig { extern Canvas::Handle open_canvas(const String &filename); };
52 /* === M A C R O S ========================================================= */
60 synfig::error("%d canvases not yet deleted!",counter);
64 int _CanvasCounter::counter(0);
66 /* === G L O B A L S ======================================================= */
68 /* === P R O C E D U R E S ================================================= */
70 /* === M E T H O D S ======================================================= */
72 Canvas::Canvas(const String &id):
74 version_ (CURRENT_CANVAS_VERSION),
80 _CanvasCounter::counter++;
93 //if(is_inline() && parent_) assert(0);
94 _CanvasCounter::counter--;
103 return CanvasBase::end()-1;
106 Canvas::const_iterator
109 return CanvasBase::end()-1;
112 Canvas::reverse_iterator
115 return CanvasBase::rbegin()+1;
118 Canvas::const_reverse_iterator
119 Canvas::rbegin()const
121 return CanvasBase::rbegin()+1;
127 return CanvasBase::size()-1;
135 Layer::Handle layer(front());
136 //if(layer->count()>2)synfig::info("before layer->count()=%d",layer->count());
139 //if(layer->count()>1)synfig::info("after layer->count()=%d",layer->count());
141 //CanvasBase::clear();
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
148 CanvasBase::push_back(Layer::Handle());
156 return CanvasBase::size()<=1;
162 return *(CanvasBase::end()-1);
165 const Layer::Handle &
168 return *(CanvasBase::end()-1);
172 Canvas::get_context()const
177 const ValueNodeList &
178 Canvas::value_node_list()const
180 if(is_inline() && parent_)
181 return parent_->value_node_list();
182 return value_node_list_;
186 Canvas::keyframe_list()
188 if(is_inline() && parent_)
189 return parent_->keyframe_list();
190 return keyframe_list_;
194 Canvas::keyframe_list()const
196 if(is_inline() && parent_)
197 return parent_->keyframe_list();
198 return keyframe_list_;
202 Canvas::find_layer(const Point &pos)
204 return get_context().hit_check(pos);
208 valid_id(const String &x)
210 static const char bad_chars[]=" :#@$^&()*";
213 if(!x.empty() && x[0]>='0' && x[0]<='9')
216 for(i=0;i<sizeof(bad_chars);i++)
217 if(x.find_first_of(bad_chars[i])!=string::npos)
224 Canvas::set_id(const String &x)
226 if(is_inline() && parent_)
227 throw runtime_error("Inline Canvas cannot have an ID");
230 throw runtime_error("Invalid ID");
232 signal_id_changed_();
236 Canvas::set_name(const String &x)
239 signal_meta_data_changed()("name");
240 signal_meta_data_changed("name")();
244 Canvas::set_author(const String &x)
247 signal_meta_data_changed()("author");
248 signal_meta_data_changed("author")();
252 Canvas::set_description(const String &x)
255 signal_meta_data_changed()("description");
256 signal_meta_data_changed("description")();
260 Canvas::set_time(Time t)const
262 if(is_dirty_ || !get_time().is_equal(t))
267 synfig::info("is_dirty_=%d",is_dirty_);
268 synfig::info("get_time()=%f",(float)get_time());
269 synfig::info("t=%f",(float)t);
274 const_cast<Canvas&>(*this).cur_time_=t;
277 get_context().set_time(t);
283 Canvas::get_root()const
285 return parent_?parent_->get_root().get():const_cast<synfig::Canvas *>(this);
289 Canvas::get_depth(etl::handle<Layer> layer)const
293 for(iter=begin();iter!=end();++iter,i++)
302 Canvas::get_relative_id(etl::loose_handle<const Canvas> x)const
304 if(x->get_root()==this)
306 if(is_inline() && parent_)
307 return parent_->_get_relative_id(x);
308 return _get_relative_id(x);
312 Canvas::_get_relative_id(etl::loose_handle<const Canvas> x)const
314 if(is_inline() && parent_)
315 return parent_->_get_relative_id(x);
320 if(parent()==x.get())
325 const Canvas* canvas=this;
327 for(;!canvas->is_root();canvas=canvas->parent().get())
328 id=':'+canvas->get_id()+id;
330 if(x && get_root()!=x->get_root())
332 //String file_name=get_file_name();
333 //String file_path=x->get_file_path();
336 if(is_absolute_path(get_file_name()))
337 file_name=etl::relative_path(x->get_file_path(),get_file_name());
339 file_name=get_file_name();
341 // If the path of X is inside of file_name,
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);
355 Canvas::find_value_node(const String &id)
358 ValueNode::Handle::cast_const(
359 const_cast<const Canvas*>(this)->find_value_node(id)
363 ValueNode::ConstHandle
364 Canvas::find_value_node(const String &id)const
366 if(is_inline() && parent_)
367 return parent_->find_value_node(id);
370 throw Exception::IDNotFound("Empty ID");
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);
377 String canvas_id(id,0,id.rfind(':'));
378 String value_node_id(id,id.rfind(':')+1);
379 if(canvas_id.empty())
381 //synfig::warning("constfind:value_node_id: "+value_node_id);
382 //synfig::warning("constfind:canvas_id: "+canvas_id);
384 return find_canvas(canvas_id)->value_node_list_.find(value_node_id);
388 Canvas::surefind_value_node(const String &id)
390 if(is_inline() && parent_)
391 return parent_->surefind_value_node(id);
394 throw Exception::IDNotFound("Empty ID");
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);
401 String canvas_id(id,0,id.rfind(':'));
402 String value_node_id(id,id.rfind(':')+1);
403 if(canvas_id.empty())
406 return surefind_canvas(canvas_id)->value_node_list_.surefind(value_node_id);
410 Canvas::add_value_node(ValueNode::Handle x, const String &id)
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");
418 throw runtime_error("ValueNode is already exported");
421 throw Exception::BadLinkName("Empty ID");
423 if(id.find_first_of(':',0)!=string::npos)
424 throw Exception::BadLinkName("Bad character");
429 if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id)))
430 throw Exception::IDNotFound("add_value_node()");
433 throw Exception::IDAlreadyExists(id);
435 catch(Exception::IDNotFound)
440 x->set_parent_canvas(this);
442 if(!value_node_list_.add(x))
444 synfig::error("Unable to add ValueNode");
445 throw std::runtime_error("Unable to add ValueNode");
455 Canvas::rename_value_node(ValueNode::Handle x, const String &id)
458 throw Exception::BadLinkName("Empty ID");
460 if(id.find_first_of(": ",0)!=string::npos)
461 throw Exception::BadLinkName("Bad character");
465 if(PlaceholderValueNode::Handle::cast_dynamic(value_node_list_.find(id)))
466 throw Exception::IDNotFound("rename_value_node");
467 throw Exception::IDAlreadyExists(id);
469 catch(Exception::IDNotFound)
479 Canvas::remove_value_node(ValueNode::Handle x)
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");
486 throw Exception::IDNotFound("Canvas::remove_value_node() was passed empty handle");
488 if(!value_node_list_.erase(x))
489 throw Exception::IDNotFound("Canvas::remove_value_node(): ValueNode was not found inside of this canvas");
491 //x->set_parent_canvas(0);
498 Canvas::surefind_canvas(const String &id)
500 if(is_inline() && parent_)
501 return parent_->surefind_canvas(id);
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)
510 // If '#' is the first character, remove it
511 // and attempt to parse the ID again.
513 return surefind_canvas(String(id,1));
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);
519 file_name=unix_to_local_path(file_name);
521 Canvas::Handle external_canvas;
523 // If the composition is already open, then use it.
524 if(externals_.count(file_name))
525 external_canvas=externals_[file_name];
528 if(is_absolute_path(file_name))
529 external_canvas=open_canvas(file_name);
531 external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name);
534 throw Exception::FileNotFound(file_name);
535 externals_[file_name]=external_canvas;
538 return Handle::cast_const(external_canvas.constant()->find_canvas(external_id));
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)
545 Children::iterator iter;
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())
553 // Create a new canvas and return it
554 //synfig::warning("Implicitly creating canvas named "+id);
555 return new_child_canvas(id);
558 // If the first character is the separator, then
559 // this references the root canvas.
561 return get_root()->surefind_canvas(string(id,1));
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.
567 String canvas_name=string(id,0,id.find_first_of(':'));
569 Canvas::Handle child_canvas=surefind_canvas(canvas_name);
571 return child_canvas->surefind_canvas(string(id,id.find_first_of(':')+1));
575 Canvas::find_canvas(const String &id)
578 Canvas::Handle::cast_const(
579 const_cast<const Canvas*>(this)->find_canvas(id)
584 Canvas::find_canvas(const String &id)const
586 if(is_inline() && parent_)return parent_->find_canvas(id);
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)
595 // If '#' is the first character, remove it
596 // and attempt to parse the ID again.
598 return find_canvas(String(id,1));
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);
604 file_name=unix_to_local_path(file_name);
606 Canvas::Handle external_canvas;
608 // If the composition is already open, then use it.
609 if(externals_.count(file_name))
610 external_canvas=externals_[file_name];
613 if(is_absolute_path(file_name))
614 external_canvas=open_canvas(file_name);
616 external_canvas=open_canvas(get_file_path()+ETL_DIRECTORY_SEPARATOR+file_name);
619 throw Exception::FileNotFound(file_name);
620 externals_[file_name]=external_canvas;
623 return Handle::cast_const(external_canvas.constant()->find_canvas(external_id));
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)
630 Children::const_iterator iter;
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())
638 throw Exception::IDNotFound("Child Canvas in Parent Canvas: (child)"+id);
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));
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.
650 String canvas_name=string(id,0,id.find_first_of(':'));
652 Canvas::ConstHandle child_canvas=find_canvas(canvas_name);
654 return child_canvas->find_canvas(string(id,id.find_first_of(':')+1));
661 return new Canvas("Untitled");
665 Canvas::push_back(etl::handle<Layer> x)
668 // int i(x->count());
670 //if(x->count()!=i+1)synfig::info("push_back before %d, after %d",i,x->count());
674 Canvas::push_front(etl::handle<Layer> x)
677 // int i(x->count());
679 //if(x->count()!=i+1)synfig::error("push_front before %d, after %d",i,x->count());
683 Canvas::insert(iterator iter,etl::handle<Layer> x)
685 // int i(x->count());
686 CanvasBase::insert(iter,x);
688 /*if(x->count()!=i+1)
690 synfig::error(__FILE__":%d: Canvas::insert(): ***FAILURE*** before %d, after %d",__LINE__,i,x->count());
692 //throw runtime_error("Canvas Insertion Failed");
701 LooseHandle correct_canvas(this);
702 //while(correct_canvas->is_inline())correct_canvas=correct_canvas->parent();
703 Layer::LooseHandle loose_layer(x);
705 add_connection(loose_layer,
706 sigc::connection::connection(
707 x->signal_added_to_group().connect(
711 &Canvas::add_group_pair),
713 add_connection(loose_layer,
714 sigc::connection::connection(
715 x->signal_removed_from_group().connect(
719 &Canvas::remove_group_pair),
723 if(!x->get_group().empty())
724 add_group_pair(x->get_group(),x);
731 Canvas::push_back_simple(etl::handle<Layer> x)
733 CanvasBase::insert(end(),x);
738 Canvas::erase(iterator iter)
740 if(!(*iter)->get_group().empty())
741 remove_group_pair((*iter)->get_group(),(*iter));
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
753 // so don't wipe them out entirely
754 // - dooglus 09-21-2007
755 disconnect_connections(*iter);
757 if(!op_flag_)remove_child(iter->get());
759 CanvasBase::erase(iter);
760 if(!op_flag_)changed();
764 Canvas::clone(const GUID& deriv_guid)const
771 name=get_id()+"_CLONE";
773 throw runtime_error("Cloning of non-inline canvases is not yet supported");
776 Handle canvas(new Canvas(name));
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());
789 canvas->set_guid(get_guid()^deriv_guid);
792 for(iter=begin();iter!=end();++iter)
794 Layer::Handle layer((*iter)->clone(deriv_guid));
797 assert(layer.count()==1);
799 canvas->push_back(layer);
800 if(!(layer.count()>1))
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());
808 assert(layer.count()>1);
812 synfig::error("Unable to clone layer");
816 canvas->signal_group_pair_removed().clear();
817 canvas->signal_group_pair_added().clear();
823 Canvas::set_inline(LooseHandle parent)
825 if(is_inline_ && parent_)
834 // Have the parent inherit all of the group stuff
836 std::map<String,std::set<etl::handle<Layer> > >::const_iterator iter;
838 for(iter=group_db_.begin();iter!=group_db_.end();++iter)
840 parent->group_db_[iter->first].insert(iter->second.begin(),iter->second.end());
843 rend_desc()=parent->rend_desc();
847 Canvas::create_inline(Handle parent)
850 //if(parent->is_inline())
851 // return create_inline(parent->parent());
853 Handle canvas(new Canvas("inline"));
854 canvas->set_inline(parent);
859 Canvas::new_child_canvas()
861 if(is_inline() && parent_)
862 return parent_->new_child_canvas();
863 // runtime_error("You cannot create a child Canvas in an inline Canvas");
865 // Create a new canvas
866 children().push_back(create());
867 Canvas::Handle canvas(children().back());
869 canvas->parent_=this;
871 canvas->rend_desc()=rend_desc();
877 Canvas::new_child_canvas(const String &id)
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");
883 // Create a new canvas
884 children().push_back(create());
885 Canvas::Handle canvas(children().back());
888 canvas->parent_=this;
889 canvas->rend_desc()=rend_desc();
895 Canvas::add_child_canvas(Canvas::Handle child_canvas, const synfig::String& id)
897 if(is_inline() && parent_)
898 return parent_->add_child_canvas(child_canvas,id);
900 if(child_canvas->parent() && !child_canvas->is_inline())
901 throw std::runtime_error("Cannot add child canvas because it belongs to someone else!");
904 throw runtime_error("Invalid ID");
909 throw Exception::IDAlreadyExists(id);
911 catch(Exception::IDNotFound)
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;
924 Canvas::remove_child_canvas(Canvas::Handle child_canvas)
926 if(is_inline() && parent_)
927 return parent_->remove_child_canvas(child_canvas);
929 if(child_canvas->parent_!=this)
930 throw runtime_error("Given child does not belong to me");
932 if(find(children().begin(),children().end(),child_canvas)==children().end())
933 throw Exception::IDNotFound(child_canvas->get_id());
935 children().remove(child_canvas);
937 child_canvas->parent_=0;
941 Canvas::set_file_name(const String &file_name)
944 parent()->set_file_name(file_name);
947 file_name_=file_name;
948 signal_file_name_changed_();
953 Canvas::signal_file_name_changed()
956 return signal_file_name_changed();
958 return signal_file_name_changed_;
962 Canvas::get_file_name()const
965 return parent()->get_file_name();
970 Canvas::get_file_path()const
973 return parent()->get_file_path();
974 return dirname(file_name_);
979 Canvas::get_meta_data(const String& key)const
981 if(!meta_data_.count(key))
983 return meta_data_.find(key)->second;
987 Canvas::set_meta_data(const String& key, const String& data)
989 if(meta_data_[key]!=data)
991 meta_data_[key]=data;
992 signal_meta_data_changed()(key);
993 signal_meta_data_changed(key)();
998 Canvas::erase_meta_data(const String& key)
1000 if(meta_data_.count(key))
1002 meta_data_.erase(key);
1003 signal_meta_data_changed()(key);
1004 signal_meta_data_changed(key)();
1009 Canvas::get_meta_data_keys()const
1011 std::list<String> ret;
1013 std::map<String,String>::const_iterator iter;
1015 for(iter=meta_data_.begin();!(iter==meta_data_.end());++iter)
1016 ret.push_back(iter->first);
1022 synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_motion_blur_in_parent)
1026 std::vector< std::pair<float,Layer::Handle> > sort_list;
1027 int i, motion_blur_i=0; // motion_blur_i is for resolving which layer comes first in the event of a z_depth tie
1028 float motion_blur_z_depth=0; // the z_depth of the least deep motion blur layer in this context
1029 bool seen_motion_blur_locally = false;
1030 bool motion_blurred; // the final result - is this layer blurred or not?
1032 // If the parent didn't cause us to already be motion blurred,
1033 // check whether there's a motion blur in this context,
1034 // and if so, calculate its z_depth.
1035 if (!seen_motion_blur_in_parent)
1036 for(iter=context,i=0;*iter;iter++,i++)
1038 Layer::Handle layer=*iter;
1040 // If the layer isn't active, don't worry about it
1041 if(!layer->active())
1044 // Any layer with an amount of zero is implicitly disabled.
1045 ValueBase value(layer->get_param("amount"));
1046 if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
1049 if(layer->get_name()=="MotionBlur")
1051 float z_depth(layer->get_z_depth()*1.0001+i);
1053 // If we've seen a motion blur before in this context...
1054 if (seen_motion_blur_locally)
1056 // ... then we're only interested in this one if it's less deep...
1057 if (z_depth < motion_blur_z_depth)
1059 motion_blur_z_depth = z_depth;
1063 // ... otherwise we're always interested in it.
1066 motion_blur_z_depth = z_depth;
1068 seen_motion_blur_locally = true;
1073 // Go ahead and start romping through the canvas to paste
1074 for(iter=context,i=0;*iter;iter++,i++)
1076 Layer::Handle layer=*iter;
1077 float z_depth(layer->get_z_depth()*1.0001+i);
1079 // If the layer isn't active, don't worry about it
1080 if(!layer->active())
1083 // Any layer with an amount of zero is implicitly disabled.
1084 ValueBase value(layer->get_param("amount"));
1085 if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
1088 Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
1090 // note: this used to include "&& paste_canvas->get_time_offset()==0", but then
1091 // time-shifted layers weren't being sorted by z-depth (bug #1806852)
1092 if(layer->get_name()=="PasteCanvas")
1094 // we need to blur the sub canvas if:
1095 // our parent is blurred,
1096 // or the child is lower than a local blur,
1097 // or the child is at the same z_depth as a local blur, but later in the context
1100 if (seen_motion_blur_in_parent) synfig::info("seen BLUR in parent\n");
1101 else if (seen_motion_blur_locally)
1102 if (z_depth > motion_blur_z_depth) synfig::info("paste is deeper than BLUR\n");
1103 else if (z_depth == motion_blur_z_depth) { synfig::info("paste is same depth as BLUR\n");
1104 if (i > motion_blur_i) synfig::info("paste is physically deeper than BLUR\n");
1105 else synfig::info("paste is less physically deep than BLUR\n");
1106 } else synfig::info("paste is less deep than BLUR\n");
1107 else synfig::info("no BLUR at all\n");
1110 motion_blurred = (seen_motion_blur_in_parent ||
1111 (seen_motion_blur_locally &&
1112 (z_depth > motion_blur_z_depth ||
1113 (z_depth == motion_blur_z_depth && i > motion_blur_i))));
1115 Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
1116 Canvas::Handle paste_sub_canvas = paste_canvas->get_sub_canvas();
1117 if(paste_sub_canvas)
1118 optimize_layers(paste_sub_canvas->get_context(),sub_canvas,motion_blurred);
1119 //#define SYNFIG_OPTIMIZE_PASTE_CANVAS 1
1121 #ifdef SYNFIG_OPTIMIZE_PASTE_CANVAS
1122 Canvas::iterator sub_iter;
1123 // Determine if we can just remove the paste canvas
1125 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))
1127 for(sub_iter=sub_canvas->begin();sub_iter!=sub_canvas->end();++sub_iter)
1129 Layer* layer=sub_iter->get();
1131 // any layers that deform end up breaking things
1132 // so do things the old way if we run into anything like this
1133 if(!dynamic_cast<Layer_NoDeform*>(layer))
1136 ValueBase value(layer->get_param("blend_method"));
1137 if(value.get_type()!=ValueBase::TYPE_INTEGER || value.get(int())!=(int)Color::BLEND_COMPOSITE)
1141 // It has turned out that we don't need a paste canvas
1142 // layer, so just go ahead and add all the layers onto
1143 // the current stack and be done with it
1144 while(sub_canvas->size())
1146 sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,sub_canvas->front()));
1147 //op_canvas->push_back_simple(sub_canvas->front());
1148 sub_canvas->pop_front();
1153 Layer::Handle new_layer(Layer::create("PasteCanvas"));
1154 dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(false);
1157 Layer::DynamicParamList dynamic_param_list(paste_canvas->dynamic_param_list());
1158 for(Layer::DynamicParamList::const_iterator iter(dynamic_param_list.begin()); iter != dynamic_param_list.end(); ++iter)
1159 new_layer->connect_dynamic_param(iter->first, iter->second);
1161 Layer::ParamList param_list(paste_canvas->get_param_list());
1162 //param_list.erase("canvas");
1163 new_layer->set_param_list(param_list);
1164 dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_sub_canvas(sub_canvas);
1165 dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(true);
1169 sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,layer));
1170 //op_canvas->push_back_simple(layer);
1174 stable_sort(sort_list.begin(),sort_list.end());
1175 std::vector< std::pair<float,Layer::Handle> >::iterator iter2;
1176 for(iter2=sort_list.begin();iter2!=sort_list.end();++iter2)
1177 op_canvas->push_back_simple(iter2->second);
1178 op_canvas->op_flag_=true;
1182 Canvas::get_times_vfunc(Node::time_set &set) const
1184 const_iterator i = begin(),
1187 for(; i != iend; ++i)
1189 const Node::time_set &tset = (*i)->get_times();
1190 set.insert(tset.begin(),tset.end());
1194 std::set<etl::handle<Layer> >
1195 Canvas::get_layers_in_group(const String&group)
1197 if(is_inline() && parent_)
1198 return parent_->get_layers_in_group(group);
1200 if(group_db_.count(group)==0)
1201 return std::set<etl::handle<Layer> >();
1202 return group_db_.find(group)->second;
1206 Canvas::get_groups()const
1208 if(is_inline() && parent_)
1209 return parent_->get_groups();
1211 std::set<String> ret;
1212 std::map<String,std::set<etl::handle<Layer> > >::const_iterator iter;
1213 for(iter=group_db_.begin();iter!=group_db_.end();++iter)
1214 ret.insert(iter->first);
1219 Canvas::get_group_count()const
1221 if(is_inline() && parent_)
1222 return parent_->get_group_count();
1224 return group_db_.size();
1228 Canvas::add_group_pair(String group, etl::handle<Layer> layer)
1230 group_db_[group].insert(layer);
1231 if(group_db_[group].size()==1)
1232 signal_group_added()(group);
1234 signal_group_changed()(group);
1236 signal_group_pair_added()(group,layer);
1238 if(is_inline() && parent_)
1239 return parent_->add_group_pair(group,layer);
1243 Canvas::remove_group_pair(String group, etl::handle<Layer> layer)
1245 group_db_[group].erase(layer);
1247 signal_group_pair_removed()(group,layer);
1249 if(group_db_[group].empty())
1251 group_db_.erase(group);
1252 signal_group_removed()(group);
1255 signal_group_changed()(group);
1257 if(is_inline() && parent_)
1258 return parent_->remove_group_pair(group,layer);
1262 Canvas::add_connection(etl::loose_handle<Layer> layer, sigc::connection connection)
1264 connections_[layer].push_back(connection);
1268 Canvas::disconnect_connections(etl::loose_handle<Layer> layer)
1270 std::vector<sigc::connection>::iterator iter;
1271 for(iter=connections_[layer].begin();iter!=connections_[layer].end();++iter)
1273 connections_[layer].clear();
1277 Canvas::rename_group(const String&old_name,const String&new_name)
1279 if(is_inline() && parent_)
1280 return parent_->rename_group(old_name,new_name);
1283 std::map<String,std::set<etl::handle<Layer> > >::iterator iter;
1284 iter=group_db_.find(old_name);
1285 if(iter!=group_db_.end())
1286 for(++iter;iter!=group_db_.end() && iter->first.find(old_name)==0;iter=group_db_.find(old_name),++iter)
1288 String name(iter->first,old_name.size(),String::npos);
1290 rename_group(iter->first,name);
1294 std::set<etl::handle<Layer> > layers(get_layers_in_group(old_name));
1295 std::set<etl::handle<Layer> >::iterator iter;
1297 for(iter=layers.begin();iter!=layers.end();++iter)
1299 (*iter)->remove_from_group(old_name);
1300 (*iter)->add_to_group(new_name);