X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcanvas.cpp;h=fcf8935b63facd8c8b2e388afe360b2cde4ad5c9;hb=2f015c519aa92f29144873527c109c21c171c6a7;hp=e7a54f979a19e57801912e7891d524d2b8e17d5d;hpb=3fe10abdf88b103b84825cd2bbac1e25090ecd9a;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/canvas.cpp b/synfig-core/trunk/src/synfig/canvas.cpp index e7a54f9..fcf8935 100644 --- a/synfig-core/trunk/src/synfig/canvas.cpp +++ b/synfig-core/trunk/src/synfig/canvas.cpp @@ -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.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.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,45 @@ synfig::optimize_layers(Context context, Canvas::Handle op_canvas, bool seen_mot dynamic_cast(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 composite = etl::handle::cast_dynamic(layer); + + /* some layers (such as circle) don't touch pixels that aren't + * part of the circle, so they don't get blended correctly when + * using a straight blend. so we encapsulate the circle, and the + * encapsulation layer takes care of the transparent pixels + * for us. if we do that for all layers, however, then the + * distortion layers no longer work, since they have no + * context to work on. the Layer::reads_context() method + * returns true for layers which need to be able to see + * their context. we can't encapsulate those. + */ + if (composite && + Color::is_straight(composite->get_blend_method()) && + !composite->reads_context()) + { + Canvas::Handle sub_canvas(Canvas::create_inline(op_canvas)); + sub_canvas->push_back(composite = composite->clone()); + layer = Layer::create("PasteCanvas"); + composite->set_description(strprintf("Wrapped clone of '%s'", composite->get_non_empty_description().c_str())); + layer->set_description(strprintf("PasteCanvas wrapper for '%s'", composite->get_non_empty_description().c_str())); + Layer_PasteCanvas* paste_canvas(static_cast(layer.get())); + paste_canvas->set_blend_method(composite->get_blend_method()); + paste_canvas->set_amount(composite->get_amount()); + sub_canvas->set_time(time); // region and outline don't calculate their bounding rects until their time is set + composite->set_blend_method(Color::BLEND_STRAIGHT); // do this before calling set_sub_canvas(), but after set_time() + composite->set_amount(1.0f); // after set_time() + paste_canvas->set_sub_canvas(sub_canvas); + } + } sort_list.push_back(std::pair(z_depth,layer)); //op_canvas->push_back_simple(layer);