Problem when creating copies of Drawables


Following my investigations started when talking about this:

A couple of issues when copying Drawables (DrawableComposites and DrawableText in particular) have arised.

Here is my test code:

                Component content;

                Path horizSegmentPath;
                horizSegmentPath.startNewSubPath (50.0f, 50.0f);
                horizSegmentPath.lineTo (100.0f, 50.0f);
                ScopedPointer <DrawablePath> horizSegmentDrawable (new DrawablePath ());
                horizSegmentDrawable->setPath (horizSegmentPath);
                horizSegmentDrawable->setStrokeThickness (1.0f);
                horizSegmentDrawable->setStrokeFill (Colours::blue.withAlpha (0.5f));

                Path vertSegmentPath;
                vertSegmentPath.startNewSubPath (50.0f, 50.0f);
                vertSegmentPath.lineTo (50.0f, 100.0f);
                ScopedPointer <DrawablePath> vertSegmentDrawable (new DrawablePath ());
                vertSegmentDrawable->setPath (vertSegmentPath);
                vertSegmentDrawable->setStrokeThickness (1.0f);
                vertSegmentDrawable->setStrokeFill (Colours::green.withAlpha (0.5f));

                Path squarePath;
                squarePath.addRectangle (25.0f, 25.0f, 50.0f, 50.0f);
                ScopedPointer <DrawablePath> squareDrawable (new DrawablePath ());
                squareDrawable->setPath (squarePath);
                squareDrawable->setStrokeThickness (1.0f);
                squareDrawable->setStrokeFill (Colours::black.withAlpha (0.5f));
                squareDrawable->setFill (Colours::transparentBlack);

                ScopedPointer <DrawableText> textDrawable (new DrawableText ());
                textDrawable->setFontHeight (RelativeCoordinate (20.0));
                textDrawable->setBoundingBox (RelativeParallelogram (Rectangle <float> (50.0f, 50.0f, 50.0f, 50.0f)));
                textDrawable->setText ("TEXT");
                textDrawable->setColour (Colours::red.withAlpha (0.5f));

                ScopedPointer <DrawableComposite> composite (new DrawableComposite ());
                composite->addAndMakeVisible (horizSegmentDrawable.release ());
                composite->addAndMakeVisible (vertSegmentDrawable.release ());
                composite->addAndMakeVisible (squareDrawable.release ());
                composite->addAndMakeVisible (textDrawable.release ());
                composite->setContentArea (RelativeRectangle (Rectangle <float> (0, 0, 100, 100)));
                composite->setBoundingBox (RelativeParallelogram (Rectangle <float> (240, 20, 200, 200)));

                ScopedPointer <Drawable> compositeCopy (composite->createCopy ());

                content.setSize (460, 240);

                content.addAndMakeVisible (composite);
                content.addAndMakeVisible (compositeCopy);

                ResizableWindow window ("Drawables", true);
                window.setUsingNativeTitleBar (true);
                window.setContentNonOwned (&content, true);
                window.centreWithSize (window.getWidth(), window.getHeight ());
                window.setVisible (true);

It creates a DrawableComposite named 'composite' containing some DrawablePaths and DrawableText, then it creates a copy of it ('compositeCopy') and adds both to the content component for display.

This is what I get:

'composite' is properly shown in its bounding box, on the right, while 'compositeCopy' (visible in the upper left corner) has

1) lost the DrawableText

2) reset its bounding box and content area to something default, that makes it display in the upper left corner where it is

I must admit that I was expecting the copy to be a 'true' copy, thus retaining also the positioning and thus resulting in an image perfectly overlapped with 'composite'.

I can (kinda) cope with #2 by later adjusting the resulting copied Drawable with setTransformToFit (I cannot access setBoundingBox and setContentArea unless I cast it to a DrawableComposite), but certainly #1 is a showstopper because creating a copy is exactly how DrawableButtons store the Drawables to be used as button images. As soon as I add a DrawableText to the composite I want to display on my button, it disappears when actually shown because the button makes its internal copy upon setImages() 



I think I have resolved this:

I noticed that the copy constructor for DrawableText doesn't copy the 'resolvedPoints' and 'scaledFont' members.

Guessing that these may be internally calculated data and that their default values result in an invisible text item, I added a "refreshBounds()" call inside the copy constructor's body to recalculate them immediately for the copied item. Now everything seems to work like a charm

DrawableText::DrawableText (const DrawableText& other)
    : Drawable (other),
      bounds (other.bounds),
      fontHeight (other.fontHeight),
      fontHScale (other.fontHScale),
      font (other.font),
      text (other.text),
      colour (other.colour),
      justification (other.justification)
    refreshBounds ();    // added by me


Ah, thanks for finding that!