I still think it would be great to get rid of reference counting - read the new comme...
authordooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Fri, 1 Feb 2008 01:58:45 +0000 (01:58 +0000)
committerdooglus <dooglus@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Fri, 1 Feb 2008 01:58:45 +0000 (01:58 +0000)
git-svn-id: http://svn.voria.com/code@1542 1f10aa63-cdf2-0310-b900-c93c546f37ac

synfig-core/trunk/src/synfig/layer_pastecanvas.cpp
synfig-core/trunk/src/synfig/layer_pastecanvas.h

index 04ed8b9..edc3d0b 100644 (file)
@@ -85,7 +85,8 @@ Layer_PasteCanvas::Layer_PasteCanvas():
        origin(0,0),
        depth(0),
        zoom(0),
-       time_offset(0)
+       time_offset(0),
+       extra_reference(false)
 {
        children_lock=false;
        muck_with_time_=true;
@@ -103,6 +104,7 @@ Layer_PasteCanvas::~Layer_PasteCanvas()
        set_sub_canvas(0);
 
        //if(canvas && (canvas->is_inline() || !get_canvas() || get_canvas()->get_root()!=canvas->get_root()))
+       //if(extra_reference)
        //      canvas->unref();
 }
 
@@ -186,7 +188,8 @@ Layer_PasteCanvas::set_sub_canvas(etl::handle<synfig::Canvas> x)
        if(canvas && muck_with_time_)
                remove_child(canvas.get());
 
-       if(canvas && (canvas->is_inline() || !get_canvas() || get_canvas()->get_root()!=canvas->get_root()))
+       // if(canvas && (canvas->is_inline() || !get_canvas() || get_canvas()->get_root()!=canvas->get_root()))
+       if (extra_reference)
                canvas->unref();
 
        child_changed_connection.disconnect();
@@ -209,7 +212,12 @@ Layer_PasteCanvas::set_sub_canvas(etl::handle<synfig::Canvas> x)
                add_child(canvas.get());
 
        if(canvas && (canvas->is_inline() || !get_canvas() || get_canvas()->get_root()!=canvas->get_root()))
+       {
                canvas->ref();
+               extra_reference = true;
+       }
+       else
+               extra_reference = false;
 
        if(canvas)
                on_canvas_set();
index 0aa3d6b..1dc9506 100644 (file)
@@ -70,6 +70,33 @@ private:
        mutable Rect bounds;
 
        sigc::connection child_changed_connection;
+
+       // Nasty hack: Remember whether we called an extra ref() when
+       // setting the canvas, so we know whether to call an extra unref()
+       // when finished with the canvas.
+       //
+       // Here's the story:
+       //
+       // The root canvas is destructed first.  That sets the
+       // Layer::canvas_ (the parent canvas) of any PasteCanvas layer it
+       // contains to nil, due to a call to Layer::set_canvas(0),
+       // triggered by the connection made when Layer::set_canvas
+       // originally set its canvas_ member to point to the root canvas.
+       // ~Canvas does begin_delete() which triggers that connection.
+       //
+       // After ~Canvas has run, the members of the root canvas are
+       // freed, including its children_ list.  If this was the last
+       // reference to the child canvas that the pastecanvas uses, that
+       // child canvas will Layer_PasteCanvas::set_sub_canvas(0) on the
+       // PasteCanvas layer to set its canvas (the child, pasted canvas)
+       // not to refer to the soon-to-be destroys child canvas.  But
+       // set_sub_canvas() originally looked at the value of
+       // Layer::canvas_ (the parent canvas, obtained via
+       // Layer::get_canvas()) to decide whether to do an extra ref() on
+       // canvas (the child canvas).  We need to unref() it now if we
+       // did, but we've forgotten whether we did.  So we use this
+       // 'extra_reference' member to store that decision.
+       bool extra_reference;
 public:
 
        virtual void on_canvas_set();