Edit in the svn revision number for the canvas 0.3 change.
[synfig.git] / synfig-core / trunk / src / synfig / canvas.cpp
index e7a54f9..270a71f 100644 (file)
@@ -1016,7 +1016,7 @@ Canvas::get_meta_data_keys()const
                  refer to "motion blur", they mean either of these two
                  layers. */
 void
-synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_motion_blur_in_parent)
+synfig::optimize_layers(Time time, Context context, Canvas::Handle op_canvas, bool seen_motion_blur_in_parent)
 {
        Context iter;
 
@@ -1082,12 +1082,12 @@ synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_mot
                if(value.get_type()==ValueBase::TYPE_REAL && value.get(Real())==0)
                        continue;
 
-               Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
-
                // note: this used to include "&& paste_canvas->get_time_offset()==0", but then
                //               time-shifted layers weren't being sorted by z-depth (bug #1806852)
                if(layer->get_name()=="PasteCanvas")
                {
+                       Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
+
                        // we need to blur the sub canvas if:
                        // our parent is blurred,
                        // or the child is lower than a local blur,
@@ -1112,7 +1112,7 @@ synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_mot
                        Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
                        Canvas::Handle paste_sub_canvas = paste_canvas->get_sub_canvas();
                        if(paste_sub_canvas)
-                               optimize_layers(paste_sub_canvas->get_context(),sub_canvas,motion_blurred);
+                               optimize_layers(time, paste_sub_canvas->get_context(),sub_canvas,motion_blurred);
 
 // \todo: uncommenting the following breaks the rendering of at least examples/backdrop.sifz quite severely
 // #define SYNFIG_OPTIMIZE_PASTE_CANVAS
@@ -1170,6 +1170,30 @@ synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_mot
                        dynamic_cast<Layer_PasteCanvas*>(new_layer.get())->set_muck_with_time(true);
                        layer=new_layer;
                }
+               else                                    // not a PasteCanvas - does it use blend method 'Straight'?
+               {
+                       /* when we use the 'straight' blend method, every pixel on the layer affects the layers underneath,
+                        * not just the non-transparent pixels; the following workarea wraps non-pastecanvas layers in a
+                        * new pastecanvas to ensure that the straight blend affects the full plane, not just the area
+                        * within the layer's bounding box
+                        */
+
+                       // \todo: this code probably needs modification to work properly with motionblur and duplicate
+                       etl::handle<Layer_Composite> composite = etl::handle<Layer_Composite>::cast_dynamic(layer);
+                       if (composite && composite->get_blend_method() == Color::BLEND_STRAIGHT)
+                       {
+                               Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas));
+                               sub_canvas->push_back(composite = composite->clone());
+                               sub_canvas->set_time(time); // region and outline don't calculate their bounding rects until their time is set
+                               layer = Layer::create("PasteCanvas");
+                               layer->set_description(strprintf("PasteCanvas wrapper for '%s'", composite->get_non_empty_description().c_str()));
+                               Layer_PasteCanvas* paste_canvas(static_cast<Layer_PasteCanvas*>(layer.get()));
+                               paste_canvas->set_sub_canvas(sub_canvas);
+                               paste_canvas->set_blend_method(Color::BLEND_STRAIGHT);
+                               paste_canvas->set_amount(composite->get_amount());
+                               composite->set_amount(1.0f);
+                       }
+               }
 
                sort_list.push_back(std::pair<float,Layer::Handle>(z_depth,layer));
                //op_canvas->push_back_simple(layer);