X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;ds=inline;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcanvas.cpp;h=74c737f6b2e77624c29e31286acafa1b96c7ea11;hb=4cd211467061154545ef7b5f5617dce7b177bf16;hp=59d54af9a473ec36b51381354ff859ca22b3c694;hpb=e922a431503d13d27863c6ecd40659836dbbfd9f;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/canvas.cpp b/synfig-core/trunk/src/synfig/canvas.cpp index 59d54af..74c737f 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,9 +1112,10 @@ 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); -//#define SYNFIG_OPTIMIZE_PASTE_CANVAS 1 + 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 #ifdef SYNFIG_OPTIMIZE_PASTE_CANVAS Canvas::iterator sub_iter; @@ -1169,6 +1170,44 @@ 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"); + 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()); + composite->set_blend_method(Color::BLEND_STRAIGHT); // do this before calling set_time() or set_sub_canvas() + composite->set_amount(1.0f); + sub_canvas->set_time(time); // region and outline don't calculate their bounding rects until their time is set + paste_canvas->set_sub_canvas(sub_canvas); + } + } sort_list.push_back(std::pair(z_depth,layer)); //op_canvas->push_back_simple(layer);