X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fcanvas.cpp;h=fcf8935b63facd8c8b2e388afe360b2cde4ad5c9;hb=2f015c519aa92f29144873527c109c21c171c6a7;hp=967bc60e5f013da2c27f36464af5ee692fbfbca0;hpb=3e363592f62521ca3e0338f474deb1eb253f9e74;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/canvas.cpp b/synfig-core/trunk/src/synfig/canvas.cpp index 967bc60..fcf8935 100644 --- a/synfig-core/trunk/src/synfig/canvas.cpp +++ b/synfig-core/trunk/src/synfig/canvas.cpp @@ -1170,6 +1170,45 @@ synfig::optimize_layers(Time time, Context context, Canvas::Handle op_canvas, bo 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);