1 /* === S Y N F I G ========================================================= */
2 /*! \file layer.cpp
3 ** \brief Layer class implementation
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 ** Copyright (c) 2011-2013 Carlos López
11 **
12 ** This package is free software; you can redistribute it and/or
13 ** modify it under the terms of the GNU General Public License as
14 ** published by the Free Software Foundation; either version 2 of
15 ** the License, or (at your option) any later version.
16 **
17 ** This package is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ** General Public License for more details.
21 ** \endlegal
22 */
23 /* ========================================================================= */
24
25 /* === H E A D E R S ======================================================= */
26
27 #ifdef USING_PCH
28 # include "pch.h"
29 #else
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <sigc++/adaptors/bind.h>
35
36 #include "layer.h"
37
38 #include "general.h"
39 #include <synfig/localization.h>
40 #include "rect.h"
41 #include "guid.h"
42 #include "value.h"
43 #include "render.h"
44 #include "canvas.h"
45 #include "context.h"
46 #include "surface.h"
47 #include "paramdesc.h"
48 #include "transform.h"
49
50 #include "layers/layer_composite.h"
51 #include "layers/layer_bitmap.h"
52 #include "layers/layer_duplicate.h"
53 #include "layers/layer_filtergroup.h"
54 #include "layers/layer_group.h"
55 #include "layers/layer_mime.h"
56 #include "layers/layer_motionblur.h"
57 #include "layers/layer_polygon.h"
58 #include "layers/layer_skeleton.h"
59 #include "layers/layer_skeletondeformation.h"
60 #include "layers/layer_solidcolor.h"
61 #include "layers/layer_sound.h"
62 #include "layers/layer_switch.h"
63
64 #include "valuenodes/valuenode_const.h"
65
66 #include "rendering/common/task/tasklayer.h"
67 #include "rendering/common/task/tasksurfaceempty.h"
68
69 #include "importer.h"
70
71 #endif
72
73 /* === U S I N G =========================================================== */
74
75 using namespace etl;
76 using namespace std;
77 using namespace synfig;
78
79 /* === G L O B A L S ======================================================= */
80
81 static Layer::Book* _layer_book;
82
83 struct _LayerCounter
84 {
85 static int counter;
~_LayerCounter_LayerCounter86 ~_LayerCounter()
87 {
88 if (counter)
89 synfig::error("%d layers not yet deleted!",counter);
90 }
91 } _layer_counter;
92
93 int _LayerCounter::counter(0);
94
95 /* === P R O C E D U R E S ================================================= */
96
97 Layer::Book&
book()98 Layer::book()
99 {
100 return *_layer_book;
101 }
102
103 void
register_in_book(const BookEntry & entry)104 Layer::register_in_book(const BookEntry &entry)
105 {
106 book()[entry.name]=entry;
107 }
108
109 bool
subsys_init()110 Layer::subsys_init()
111 {
112 _layer_book=new Book();
113
114 #define INCLUDE_LAYER(class) \
115 synfig::Layer::book() [synfig::String(class::name__)] = \
116 BookEntry(class::create, \
117 class::name__, \
118 dgettext("synfig", class::local_name__), \
119 class::category__, \
120 class::cvs_id__, \
121 class::version__)
122
123 #define LAYER_ALIAS(class,alias) \
124 synfig::Layer::book()[synfig::String(alias)] = \
125 BookEntry(class::create, \
126 alias, \
127 alias, \
128 CATEGORY_DO_NOT_USE, \
129 class::cvs_id__, \
130 class::version__)
131
132 INCLUDE_LAYER(Layer_SolidColor);
133 LAYER_ALIAS(Layer_SolidColor, "solid_color");
134 INCLUDE_LAYER(Layer_FilterGroup);
135 INCLUDE_LAYER(Layer_Group);
136 LAYER_ALIAS(Layer_Group, "paste_canvas");
137 LAYER_ALIAS(Layer_Group, "PasteCanvas");
138 INCLUDE_LAYER(Layer_Switch);
139 INCLUDE_LAYER(Layer_Polygon);
140 LAYER_ALIAS(Layer_Polygon, "Polygon");
141 INCLUDE_LAYER(Layer_MotionBlur);
142 LAYER_ALIAS(Layer_MotionBlur, "motion_blur");
143 INCLUDE_LAYER(Layer_Duplicate);
144 INCLUDE_LAYER(Layer_Skeleton);
145 INCLUDE_LAYER(Layer_SkeletonDeformation);
146 INCLUDE_LAYER(Layer_Sound);
147
148 #undef LAYER_ALIAS
149 #undef INCLUDE_LAYER
150
151 return true;
152 }
153
154 bool
subsys_stop()155 Layer::subsys_stop()
156 {
157 delete _layer_book;
158 return true;
159 }
160
161 /* === M E T H O D S ======================================================= */
162
Layer()163 Layer::Layer():
164 active_(true),
165 optimized_(false),
166 exclude_from_rendering_(false),
167 param_z_depth(Real(0.0f)),
168 time_mark(Time::end()),
169 outline_grow_mark(0.0)
170 {
171 _LayerCounter::counter++;
172 SET_INTERPOLATION_DEFAULTS();
173 SET_STATIC_DEFAULTS();
174 }
175
176 Layer::LooseHandle
create(const String & name)177 synfig::Layer::create(const String &name)
178 {
179 if(!book().count(name))
180 {
181 return Layer::LooseHandle(new Layer_Mime(name));
182 }
183
184 Layer* layer(book()[name].factory());
185 return Layer::LooseHandle(layer);
186 }
187
~Layer()188 synfig::Layer::~Layer()
189 {
190 if (monitor_connection) monitor_connection.disconnect(); // disconnect signal handler
191
192 _LayerCounter::counter--;
193
194 while(!dynamic_param_list_.empty())
195 {
196 remove_child(dynamic_param_list_.begin()->second.get());
197 dynamic_param_list_.erase(dynamic_param_list_.begin());
198 }
199
200 remove_from_all_groups();
201
202 parent_death_connect_.disconnect();
203 begin_delete();
204 }
205
206 void
set_canvas(etl::loose_handle<Canvas> x)207 synfig::Layer::set_canvas(etl::loose_handle<Canvas> x)
208 {
209 if(canvas_!=x)
210 {
211 parent_death_connect_.disconnect();
212 canvas_=x;
213 if(x)
214 {
215 parent_death_connect_=x->signal_deleted().connect(
216 sigc::bind(
217 sigc::mem_fun(
218 *this,
219 &Layer::set_canvas
220 ),
221 etl::loose_handle<synfig::Canvas>(0)
222 )
223 );
224 }
225 on_canvas_set();
226 }
227 }
228
229 void
on_canvas_set()230 synfig::Layer::on_canvas_set()
231 { }
232
233 void
on_static_param_changed(const String &)234 synfig::Layer::on_static_param_changed(const String & /* param */)
235 { }
236
237 void
on_dynamic_param_changed(const String &)238 synfig::Layer::on_dynamic_param_changed(const String & /* param */)
239 { }
240
241
242 etl::loose_handle<synfig::Canvas>
get_canvas() const243 synfig::Layer::get_canvas()const
244 {
245 return canvas_;
246 }
247
248 int
get_depth() const249 Layer::get_depth()const
250 {
251 if(!get_canvas())
252 return -1;
253 return get_canvas()->get_depth(const_cast<synfig::Layer*>(this));
254 }
255
256 void
set_active(bool x)257 Layer::set_active(bool x)
258 {
259 if(active_!=x)
260 {
261 active_=x;
262
263 Node::on_changed();
264 signal_status_changed_();
265 }
266 }
267
268 void
set_exclude_from_rendering(bool x)269 Layer::set_exclude_from_rendering(bool x)
270 {
271 if(exclude_from_rendering_!=x)
272 {
273 exclude_from_rendering_=x;
274
275 Node::on_changed();
276 signal_status_changed_();
277 }
278 }
279
280 void
set_description(const String & x)281 Layer::set_description(const String& x)
282 {
283 if(description_!=x)
284 {
285 description_=x;
286 signal_description_changed_();
287 }
288 }
289
290 void
static_param_changed(const String & param)291 Layer::static_param_changed(const String ¶m)
292 {
293 on_static_param_changed(param);
294 if (!dynamic_param_list().count(param))
295 signal_static_param_changed_(param);
296 }
297
298 void
dynamic_param_changed(const String & param)299 Layer::dynamic_param_changed(const String ¶m)
300 {
301 on_dynamic_param_changed(param);
302 if (!dynamic_param_list().count(param))
303 signal_dynamic_param_changed_(param);
304 }
305
306 bool
connect_dynamic_param(const String & param,etl::loose_handle<ValueNode> value_node)307 Layer::connect_dynamic_param(const String& param, etl::loose_handle<ValueNode> value_node)
308 {
309 if (!value_node) return disconnect_dynamic_param(param);
310
311 ValueNode::Handle previous;
312 DynamicParamList::iterator i = dynamic_param_list_.find(param);
313 if (i != dynamic_param_list_.end()) previous = i->second;
314
315 if (previous == value_node)
316 return true;
317
318 String param_noref = param;
319 dynamic_param_list_[param]=ValueNode::Handle(value_node);
320
321 if (previous)
322 {
323 // fix 2353284: if two parameters in the same layer are
324 // connected to the same valuenode and we disconnect one of
325 // them, the parent-child relationship for the remaining
326 // connection was being deleted. now we search the parameter
327 // list to see if another parameter uses the same valuenode
328 DynamicParamList::const_iterator iter;
329 for (iter = dynamic_param_list().begin(); iter != dynamic_param_list().end(); iter++)
330 if (iter->second == previous)
331 break;
332 if (iter == dynamic_param_list().end())
333 remove_child(previous.get());
334 }
335
336 add_child(value_node.get());
337 if(!value_node->is_exported() && get_canvas())
338 value_node->set_parent_canvas(get_canvas());
339
340 dynamic_param_changed(param);
341 changed();
342 return true;
343 }
344
345 bool
disconnect_dynamic_param(const String & param)346 Layer::disconnect_dynamic_param(const String& param)
347 {
348 DynamicParamList::iterator i = dynamic_param_list_.find(param);
349 if (i == dynamic_param_list_.end()) return true;
350
351 ValueNode::Handle previous(i->second);
352 dynamic_param_list_.erase(i);
353
354 if(previous)
355 {
356 // fix 2353284: if two parameters in the same layer are
357 // connected to the same valuenode and we disconnect one of
358 // them, the parent-child relationship for the remaining
359 // connection was being deleted. now we search the parameter
360 // list to see if another parameter uses the same valuenode
361 DynamicParamList::const_iterator iter;
362 for (iter = dynamic_param_list().begin(); iter != dynamic_param_list().end(); iter++)
363 if (iter->second == previous)
364 break;
365 if (iter == dynamic_param_list().end())
366 remove_child(previous.get());
367 }
368
369 static_param_changed(param);
370 changed();
371
372 return true;
373 }
374
375 void
on_changed()376 Layer::on_changed()
377 {
378 if (getenv("SYNFIG_DEBUG_ON_CHANGED"))
379 printf("%s:%d Layer::on_changed()\n", __FILE__, __LINE__);
380
381 clear_time_mark();
382 Node::on_changed();
383 }
384
385 void
on_child_changed(const Node * x)386 Layer::on_child_changed(const Node *x)
387 {
388 Node::on_child_changed(x);
389 for(DynamicParamList::const_iterator i = dynamic_param_list().begin(); i != dynamic_param_list().end();)
390 {
391 DynamicParamList::const_iterator j = i;
392 ++i;
393 if (j->second.get() == x)
394 dynamic_param_changed(j->first);
395 }
396 }
397
398 bool
set_param(const String & param,const ValueBase & value)399 Layer::set_param(const String ¶m, const ValueBase &value)
400 {
401 IMPORT_VALUE(param_z_depth)
402 return false;
403 }
404
405 etl::handle<Transform>
get_transform() const406 Layer::get_transform()const
407 {
408 return 0;
409 }
410
411 float
get_z_depth(const synfig::Time & t) const412 Layer::get_z_depth(const synfig::Time& t)const
413 {
414 if(!dynamic_param_list().count("z_depth"))
415 return param_z_depth.get(Real());
416 return (*dynamic_param_list().find("z_depth")->second)(t).get(Real());
417 }
418
419 float
get_true_z_depth(const synfig::Time & t) const420 Layer::get_true_z_depth(const synfig::Time& t)const
421 {
422 // TODO: the 1.0001 constant should be somehow user defined
423 return get_z_depth(t)*1.0001+get_depth();
424 }
425
426 float
get_true_z_depth() const427 Layer::get_true_z_depth()const
428 {
429 // TODO: the 1.0001 constant should be somehow user defined
430 return get_z_depth()*1.0001+get_depth();
431 }
432
433 Layer::Handle
simple_clone() const434 Layer::simple_clone()const
435 {
436 if(!book().count(get_name())) return 0;
437 Handle ret = create(get_name()).get();
438 ret->group_=group_;
439 //ret->set_canvas(get_canvas());
440 ret->set_description(get_description());
441 ret->set_active(active());
442 ret->set_optimized(optimized());
443 ret->set_exclude_from_rendering(get_exclude_from_rendering());
444 ret->set_param_list(get_param_list());
445 for(DynamicParamList::const_iterator iter=dynamic_param_list().begin();iter!=dynamic_param_list().end();++iter)
446 ret->connect_dynamic_param(iter->first, iter->second);
447 return ret;
448 }
449
450 Layer::Handle
clone(Canvas::LooseHandle canvas,const GUID & deriv_guid) const451 Layer::clone(Canvas::LooseHandle canvas, const GUID& deriv_guid) const
452 {
453 if(!book().count(get_name())) return 0;
454
455 //Layer *ret = book()[get_name()].factory();//create(get_name()).get();
456 Handle ret = create(get_name()).get();
457
458 ret->group_=group_;
459 //ret->set_canvas(get_canvas());
460 ret->set_description(get_description());
461 ret->set_active(active());
462 ret->set_optimized(optimized());
463 ret->set_exclude_from_rendering(get_exclude_from_rendering());
464 ret->set_guid(get_guid()^deriv_guid);
465
466 ret->set_time_mark(get_time_mark());
467 ret->set_outline_grow_mark(get_outline_grow_mark());
468
469 //ret->set_param_list(get_param_list());
470 // Process the parameter list so that
471 // we can duplicate any inline canvases
472 ParamList param_list(get_param_list());
473 for(ParamList::const_iterator iter(param_list.begin()); iter != param_list.end(); ++iter)
474 {
475 if(dynamic_param_list().count(iter->first)==0 && iter->second.get_type()==type_canvas)
476 {
477 // This parameter is a canvas. We need a close look.
478 Canvas::Handle canvas(iter->second.get(Canvas::Handle()));
479 if(canvas && canvas->is_inline())
480 {
481 // This parameter is an inline canvas! we need to clone it
482 // before we set it as a parameter.
483
484 // clone canvas (all code that clones a canvas has this comment)
485 Canvas::Handle new_canvas(canvas->clone(deriv_guid));
486
487 ValueBase value(new_canvas);
488 ret->set_param(iter->first, value);
489 continue;
490 }
491 }
492
493 // This is a normal parameter,go ahead and set it.
494 ret->set_param(iter->first, iter->second);
495 }
496
497 // Duplicate the dynamic paramlist, but only the exported data nodes
498 DynamicParamList::const_iterator iter;
499 for(iter=dynamic_param_list().begin();iter!=dynamic_param_list().end();++iter)
500 {
501 // Make sure we clone inline canvases
502 if(iter->second->get_type()==type_canvas)
503 {
504 Canvas::Handle canvas((*iter->second)(0).get(Canvas::Handle()));
505 if(canvas->is_inline())
506 {
507 // clone canvas (all code that clones a canvas has this comment)
508 Canvas::Handle new_canvas(canvas->clone(deriv_guid));
509 ValueBase value(new_canvas);
510 ret->connect_dynamic_param(iter->first,ValueNode_Const::create(value));
511 continue;
512 }
513 }
514
515 if(iter->second->is_exported())
516 ret->connect_dynamic_param(iter->first,iter->second);
517 else
518 ret->connect_dynamic_param(iter->first,iter->second->clone(canvas, deriv_guid));
519 }
520
521 //ret->set_canvas(0);
522
523 return ret;
524 }
525
526 bool
reads_context() const527 Layer::reads_context() const
528 {
529 return false;
530 }
531
532 Rect
get_full_bounding_rect(Context context) const533 Layer::get_full_bounding_rect(Context context)const
534 {
535 // No one of overrides of this function don't check the "active" flag
536 // So this check also disabled here
537 //if(Context::active(context.get_params(),*this))
538 return context.get_full_bounding_rect()|get_bounding_rect();
539 //return context.get_full_bounding_rect();
540 }
541
542 Rect
get_bounding_rect() const543 Layer::get_bounding_rect()const
544 {
545 return Rect::full_plane();
546 }
547
548 bool
set_param_list(const ParamList & list)549 Layer::set_param_list(const ParamList &list)
550 {
551 bool ret=true;
552 if(!list.size())
553 return false;
554 ParamList::const_iterator iter(list.begin());
555 for(;iter!=list.end();++iter)
556 {
557 if(!set_param(iter->first, iter->second))ret=false;
558 }
559 return ret;
560 }
561
562 Layer::ParamList
get_param_list() const563 Layer::get_param_list()const
564 {
565 ParamList ret;
566
567 Vocab vocab(get_param_vocab());
568
569 Vocab::const_iterator iter=vocab.begin();
570 for(;iter!=vocab.end();++iter)
571 {
572 ret[iter->get_name()]=get_param(iter->get_name());
573 }
574 return ret;
575 }
576
577 ValueBase
get_param(const String & param) const578 Layer::get_param(const String & param)const
579 {
580 EXPORT_VALUE(param_z_depth);
581 return ValueBase();
582 }
583
584 String
get_version() const585 Layer::get_version()const
586 {
587 return get_param("version__").get(String());
588 }
589
590 bool
set_version(const String &)591 Layer::set_version(const String &/*ver*/)
592 {
593 return false;
594 }
595
596 void
reset_version()597 Layer::reset_version()
598 { }
599
600
601 void
set_time(IndependentContext context,Time time) const602 Layer::set_time(IndependentContext context, Time time)const
603 {
604 Layer::ParamList params;
605 Layer::DynamicParamList::const_iterator iter;
606 // For each parameter of the layer sets the time by the operator()(time)
607 for(iter=dynamic_param_list().begin();iter!=dynamic_param_list().end();iter++)
608 params[iter->first]=(*iter->second)(time);
609 // Sets the modified parameter list to the current context layer
610 const_cast<Layer*>(this)->set_param_list(params);
611
612 set_time_mark(time);
613
614 set_time_vfunc(context, time);
615 }
616
617 void
set_time_vfunc(IndependentContext context,Time time) const618 Layer::set_time_vfunc(IndependentContext context, Time time)const
619 {
620 context.set_time(time);
621 }
622
623 void
set_outline_grow(IndependentContext context,Real outline_grow) const624 Layer::set_outline_grow(IndependentContext context, Real outline_grow)const
625 {
626 set_outline_grow_mark(outline_grow);
627 set_outline_grow_vfunc(context, outline_grow);
628 }
629
630 void
set_outline_grow_vfunc(IndependentContext context,Real outline_grow) const631 Layer::set_outline_grow_vfunc(IndependentContext context, Real outline_grow)const
632 {
633 context.set_outline_grow(outline_grow);
634 }
635
636 void
set_render_method(Context context,RenderMethod x)637 Layer::set_render_method(Context context, RenderMethod x)
638 {
639 context.set_render_method(x);
640 }
641
642 Color
get_color(Context context,const Point & pos) const643 Layer::get_color(Context context, const Point &pos)const
644 {
645 return context.get_color(pos);
646 }
647
648 CairoColor
get_cairocolor(Context context,const Point & pos) const649 Layer::get_cairocolor(Context context, const Point &pos)const
650 {
651 // When the layer doesn't define its own get_cairocolor
652 // then the normal get_cairo color will be used and
653 // a Color to CairoColor conversion will be done.
654 return CairoColor(get_color(context, pos));
655 }
656
657
658 synfig::Layer::Handle
hit_check(synfig::Context context,const synfig::Point & pos) const659 Layer::hit_check(synfig::Context context, const synfig::Point &pos)const
660 {
661 return context.hit_check(pos);
662 }
663
664 // Temporary function to render transformed layer for layers which yet not suppurt transformed rendering
665 #ifdef _DEBUG
666 bool
render_transformed(const Layer * layer,Context context,Surface * surface,int quality,const RendDesc & renddesc,ProgressCallback * cb,const char * file,int line)667 Layer::render_transformed(const Layer *layer, Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb, const char *file, int line)
668 {
669 warning("%s:%d Resampling used while rendering - possible overhead (called from %s:%d)", __FILE__, __LINE__, file, line);
670 #else
671 bool
672 Layer::render_transformed(const Layer *layer, Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb, const char *, int)
673 {
674 #endif
675
676 Transformation transformation(renddesc.get_transformation_matrix());
677
678 if(cb && !cb->amount_complete(0,10000)) return false;
679
680 SuperCallback stageone(cb,0,4500,10000);
681 SuperCallback stagetwo(cb,4500,9000,10000);
682 SuperCallback stagethree(cb,9000,9999,10000);
683
684 surface->set_wh(renddesc.get_w(),renddesc.get_h());
685 surface->clear();
686
687 const Rect full_bounding_rect(layer->get_full_bounding_rect(context));
688 Rect inner_bounds(
689 full_bounding_rect.get_min(),
690 full_bounding_rect.get_max()
691 );
692 inner_bounds &= transformation.back_transform_bounds(renddesc.get_rect());
693 Rect outer_bounds(transformation.transform_bounds(inner_bounds));
694 outer_bounds &= renddesc.get_rect();
695
696 // sometimes the user changes the parameters while we're
697 // rendering, causing our pasted canvas' bounding box to shrink
698 // and no longer overlap with our tile. if that has happened,
699 // let's just stop now - we'll be refreshing soon anyway
700 //! \todo shouldn't a mutex ensure this isn't needed?
701 // http://synfig.org/images/d/d2/Bbox-change.sifz is an example
702 // that shows this happening - open the encapsulation, select the
703 // 'shade', and toggle the 'invert' parameter quickly.
704 // Occasionally you'll see:
705 // error: Context::accelerated_render(): Layer "shade" threw a bad_alloc exception!
706 // where the shade layer tries to allocate itself a canvas of
707 // negative proportions, due to changing bounding boxes.
708 if (!inner_bounds.is_valid())
709 {
710 warning("%s:%d bounding box shrank while rendering?", __FILE__, __LINE__);
711 return true;
712 }
713
714 Vector width_vector(
715 transformation.transform(
716 Vector(inner_bounds.maxx - inner_bounds.minx, 0.0), false ));
717 Vector pixels_width_vector(
718 width_vector[0]/renddesc.get_pw(),
719 width_vector[1]/renddesc.get_ph() );
720 int inner_width_pixels = (int)ceil(pixels_width_vector.mag());
721
722 Vector ortho_axis_x(width_vector.norm());
723 Vector ortho_axis_y(-ortho_axis_x.perp());
724
725 Vector height_vector(
726 transformation.transform(
727 Vector(0.0, inner_bounds.maxy - inner_bounds.miny), false ));
728 Vector ortho_height_vector(
729 ortho_axis_y * (height_vector*ortho_axis_y) );
730 Vector pixels_height_vector(
731 ortho_height_vector[0]/renddesc.get_pw(),
732 ortho_height_vector[1]/renddesc.get_ph() );
733 int inner_height_pixels = (int)ceil(pixels_height_vector.mag());
734
735 // make 8 pixels border for bicubic resampling
736 float intermediate_pw = (inner_bounds.maxx-inner_bounds.minx)/(float)inner_width_pixels;
737 float intermediate_ph = (inner_bounds.maxy-inner_bounds.miny)/(float)inner_height_pixels;
738 inner_bounds.maxx += 8.f*intermediate_pw;
739 inner_bounds.minx -= 8.f*intermediate_pw;
740 inner_bounds.maxy += 8.f*intermediate_ph;
741 inner_bounds.miny -= 8.f*intermediate_ph;
742 inner_width_pixels += 16;
743 inner_height_pixels += 16;
744
745 RendDesc intermediate_desc(renddesc);
746 intermediate_desc.clear_flags();
747 intermediate_desc.set_transformation_matrix(Matrix());
748 intermediate_desc.set_tl(Vector(inner_bounds.minx,inner_bounds.maxy));
749 intermediate_desc.set_br(Vector(inner_bounds.maxx,inner_bounds.miny));
750 intermediate_desc.set_flags(0);
751 intermediate_desc.set_w(inner_width_pixels);
752 intermediate_desc.set_h(inner_height_pixels);
753
754 Surface intermediate_surface;
755 if(!layer->accelerated_render(context,&intermediate_surface,quality,intermediate_desc,&stagetwo))
756 return false;
757
758 Rect pixels_outer_bounds(
759 Vector((outer_bounds.minx-renddesc.get_tl()[0])/renddesc.get_pw(),
760 (outer_bounds.miny-renddesc.get_tl()[1])/renddesc.get_ph()),
761 Vector((outer_bounds.maxx-renddesc.get_tl()[0])/renddesc.get_pw(),
762 (outer_bounds.maxy-renddesc.get_tl()[1])/renddesc.get_ph())
763 );
764
765 int left = (int)floor(pixels_outer_bounds.minx);
766 int top = (int)floor(pixels_outer_bounds.miny);
767 int right = (int)ceil (pixels_outer_bounds.maxx);
768 int bottom = (int)ceil (pixels_outer_bounds.maxy);
769
770 int w = min(surface->get_w(), renddesc.get_w());
771 int h = min(surface->get_h(), renddesc.get_h());
772
773 if (left < 0) left = 0;
774 if (top < 0) top = 0;
775 if (right > w) right = w;
776 if (bottom > h) bottom = h;
777
778 int decx = right - left;
779 if (top < bottom && left < right) {
780 Vector initial_outer_pos(left*renddesc.get_pw(), top*renddesc.get_ph());
781 initial_outer_pos += renddesc.get_tl();
782 Vector initial_inner_pos = transformation.back_transform(initial_outer_pos);
783 Vector initial_inner_surface_pos(initial_inner_pos - intermediate_desc.get_tl());
784 initial_inner_surface_pos[0] /= intermediate_desc.get_pw();
785 initial_inner_surface_pos[1] /= intermediate_desc.get_ph();
786
787 Vector initial_outer_pos01((left+1)*renddesc.get_pw(), top*renddesc.get_ph());
788 initial_outer_pos01 += renddesc.get_tl();
789 Vector initial_inner_pos01 = transformation.back_transform(initial_outer_pos01);
790 Vector initial_inner_surface_pos01(initial_inner_pos01 - intermediate_desc.get_tl());
791 initial_inner_surface_pos01[0] /= intermediate_desc.get_pw();
792 initial_inner_surface_pos01[1] /= intermediate_desc.get_ph();
793
794 Vector initial_outer_pos10(left*renddesc.get_pw(), (top+1)*renddesc.get_ph());
795 initial_outer_pos10 += renddesc.get_tl();
796 Vector initial_inner_pos10 = transformation.back_transform(initial_outer_pos10);
797 Vector initial_inner_surface_pos10(initial_inner_pos10 - intermediate_desc.get_tl());
798 initial_inner_surface_pos10[0] /= intermediate_desc.get_pw();
799 initial_inner_surface_pos10[1] /= intermediate_desc.get_ph();
800
801 Vector dx(initial_inner_surface_pos01 - initial_inner_surface_pos);
802 Vector dy(initial_inner_surface_pos10 - initial_inner_surface_pos);
803
804 Vector row_inner_surface_pos(initial_inner_surface_pos);
805 Vector inner_surface_pos;
806
807 Surface::pen pen(surface->get_pen(left, top));
808 for(int y = top; y < bottom; y++) {
809 inner_surface_pos = row_inner_surface_pos;
810 for(int x = left; x < right; x++) {
811 pen.put_value( intermediate_surface.cubic_sample(inner_surface_pos[0], inner_surface_pos[1]) );
812 pen.inc_x();
813 inner_surface_pos += dx;
814 }
815 pen.dec_x(decx);
816 pen.inc_y();
817 row_inner_surface_pos += dy;
818 }
819 }
820
821 if(cb && !cb->amount_complete(10000,10000)) return false;
822
823 return true;
824 }
825
826 /* The default accelerated renderer
827 ** is anything but accelerated...
828 */
829 bool
830 Layer::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb) const
831 {
832 RENDER_TRANSFORMED_IF_NEED(__FILE__, __LINE__)
833
834 handle<Target_Scanline> target=surface_target_scanline(surface);
835 if(!target)
836 {
837 if(cb)cb->error(_("Unable to create surface target"));
838 return false;
839 }
840 RendDesc desc=renddesc;
841 target->set_rend_desc(&desc);
842
843 // When we render, we want to
844 // make sure that we are rendered too...
845 // Since the context iterator is for
846 // the layer after us, we need to back up.
847 // This could be considered a hack, as
848 // it is a possibility that we are indeed
849 // not the previous layer.
850 --context;
851
852 return render(context,target,desc,cb);
853 //return render_threaded(context,target,desc,cb,2);
854 }
855
856
857 bool
858 Layer::accelerated_cairorender(Context context, cairo_t *cr, int /*quality*/, const RendDesc &renddesc, ProgressCallback *cb) const
859 {
860 // When we render, we want to
861 // make sure that we are rendered too...
862 // Since the context iterator is for
863 // the layer after us, we need to back up.
864 // This could be considered a hack, as
865 // it is a possibility that we are indeed
866 // not the previous layer.
867 --context;
868
869 return cairorender(context,cr,renddesc,cb);
870 }
871
872 RendDesc
873 Layer::get_sub_renddesc_vfunc(const RendDesc &renddesc) const
874 {
875 return renddesc;
876 }
877
878 void
879 Layer::get_sub_renddesc_vfunc(const RendDesc &renddesc, std::vector<RendDesc> &out_descs) const
880 {
881 out_descs.push_back( get_sub_renddesc_vfunc(renddesc) );
882 }
883
884 void
885 Layer::get_sub_renddesc(const RendDesc &renddesc, std::vector<RendDesc> &out_descs) const
886 {
887 get_sub_renddesc_vfunc(renddesc, out_descs);
888 }
889
890 RendDesc
891 Layer::get_sub_renddesc(const RendDesc &renddesc, int index) const
892 {
893 std::vector<RendDesc> descs;
894 get_sub_renddesc(renddesc, descs);
895 return index >=0 && index < (int)descs.size() ? descs[index] : RendDesc::zero();
896 }
897
898 rendering::Task::Handle
899 Layer::build_rendering_task_vfunc(Context context)const
900 {
901 rendering::TaskLayer::Handle task = new rendering::TaskLayer();
902 // TODO: This is not thread-safe
903 //task->layer = const_cast<Layer*>(this);//clone(NULL);
904 task->layer = clone(NULL);
905 task->layer->set_canvas(get_canvas());
906
907 Real amount = Context::z_depth_visibility(context.get_params(), *this);
908 if (approximate_not_equal(amount, 1.0) && task->layer.type_is<Layer_Composite>())
909 {
910 //task->layer = task->layer->clone(NULL);
911 etl::handle<Layer_Composite> composite = etl::handle<Layer_Composite>::cast_dynamic(task->layer);
912 composite->set_amount( composite->get_amount()*amount );
913 }
914
915 task->sub_task() = context.build_rendering_task();
916 return task;
917 }
918
919 rendering::Task::Handle
920 Layer::build_rendering_task(Context context)const
921 {
922 rendering::Task::Handle task = build_rendering_task_vfunc(context);
923 return task ? task : rendering::Task::Handle(new rendering::TaskSurfaceEmpty());
924 }
925
926 String
927 Layer::get_name()const
928 {
929 return get_param("name__").get(String());
930 }
931
932 String
933 Layer::get_local_name()const
934 {
935 return get_param("local_name__").get(String());
936 }
937
938
939 Layer::Vocab
940 Layer::get_param_vocab()const
941 {
942 Layer::Vocab ret;
943
944 ret.push_back(ParamDesc(param_z_depth,"z_depth")
945 .set_local_name(_("Z Depth"))
946 .set_animation_only(true)
947 .set_description(_("Modifies the position of the layer in the layer stack"))
948 );
949
950 return ret;
951 }
952
953 void
954 Layer::get_times_vfunc(Node::time_set &set) const
955 {
956 DynamicParamList::const_iterator i = dynamic_param_list_.begin(),
957 end = dynamic_param_list_.end();
958
959 for(; i != end; ++i)
960 {
961 const Node::time_set &tset = i->second->get_times();
962 set.insert(tset.begin(),tset.end());
963 }
964 }
965
966
967 void
968 Layer::add_to_group(const String&x)
969 {
970 if(x==group_)
971 return;
972 if(!group_.empty())
973 remove_from_all_groups();
974 group_=x;
975 signal_added_to_group()(group_);
976 }
977
978 void
979 Layer::remove_from_group(const String&x)
980 {
981 if(group_==x)
982 remove_from_all_groups();
983 }
984
985 void
986 Layer::remove_from_all_groups()
987 {
988 if(group_.empty())
989 return;
990 signal_removed_from_group()(group_);
991 group_.clear();
992 }
993
994 String
995 Layer::get_group()const
996 {
997 return group_;
998 }
999
1000 const String
1001 Layer::get_param_local_name(const String ¶m_name)const
1002 {
1003 ParamVocab vocab = get_param_vocab();
1004 // loop to find the parameter in the parameter vocab - this gives us its local name
1005 for (ParamVocab::iterator iter = vocab.begin(); iter != vocab.end(); iter++)
1006 if (iter->get_name() == param_name)
1007 return iter->get_local_name();
1008 return String();
1009 }
1010
1011 synfig::Layer::LooseHandle
1012 synfig::Layer::get_parent_paste_canvas_layer()const
1013 {
1014 synfig::Canvas::LooseHandle canvas=get_canvas();
1015 if(canvas->parent())
1016 {
1017 synfig::Canvas::LooseHandle parent_canvas=canvas->parent();
1018 Canvas::iterator iter;
1019 for(iter=parent_canvas->begin();iter!=parent_canvas->end();++iter)
1020 {
1021 Layer::LooseHandle layer=iter->get();
1022 if(dynamic_cast<Layer_PasteCanvas*>(layer.get()) != NULL)
1023 {
1024 Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
1025 Canvas::Handle sub_canvas=paste_canvas->get_sub_canvas();
1026 if(sub_canvas==canvas)
1027 return layer;
1028 }
1029 }
1030 synfig::warning("Layer's canvas has parent canvas but I can't find a proper Layer_PasteCanvas in it");
1031 return NULL;
1032 }
1033 return NULL;
1034 }
1035
1036 String
1037 Layer::get_string()const
1038 {
1039 return String("Layer: ") + get_non_empty_description();
1040
1041 }
1042
1043 void
1044 Layer::fill_sound_processor(SoundProcessor & /* soundProcessor */) const
1045 { }
1046
1047 using Glib::RefPtr;
1048
1049 void Layer::on_file_changed(const RefPtr<Gio::File> &/*file*/, const RefPtr<Gio::File> &/*other_file*/, Gio::FileMonitorEvent event) {
1050 if (event == Gio::FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
1051 {
1052 synfig::warning("file changed! (" + monitored_path + ")");
1053 set_param("filename", ValueBase("")); // first clear filename to force image reload
1054 Importer::forget(get_canvas()->get_file_system()->get_identifier(monitored_path)); // clear file in list of loaded files
1055 set_param("filename", ValueBase(monitored_path));
1056 get_canvas()->signal_changed()();
1057 }
1058 }
1059
1060 bool Layer::monitor(const std::string& path) { // append file monitor (returns true on success, false on fail)
1061 if (file_monitor)
1062 {
1063 synfig::warning("File monitor for file '" + path + "' is already attached!");
1064 return false;
1065 }
1066
1067 RefPtr<Gio::File> file = Gio::File::create_for_path(path);
1068 file_monitor = file->monitor_file(); // defaults to Gio::FileMonitorFlags::FILE_MONITOR_NONE
1069 monitor_connection = file_monitor->signal_changed().connect(sigc::mem_fun(*this, &Layer::on_file_changed));
1070 monitored_path = path;
1071 synfig::info("File monitor attached to file: (" + path + ")");
1072
1073 return true;
1074 }
1075