summaryrefslogtreecommitdiff
path: root/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx')
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx121
1 files changed, 74 insertions, 47 deletions
diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
index 9974117b5ae0..d756e6e3b74f 100644
--- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
@@ -36,6 +36,7 @@
// helper class for animated graphics
+#include <utility>
#include <vcl/animate/Animation.hxx>
#include <vcl/graph.hxx>
#include <vcl/virdev.hxx>
@@ -74,7 +75,7 @@ namespace drawinglayer::primitive2d
Primitive2DReference maBufferedFirstFrame;
/// buffering of all frames
- Primitive2DContainer maBufferedPrimitives;
+ std::vector<Primitive2DReference> maBufferedPrimitives;
bool mbBufferingAllowed;
/// set if the animation is huge so that just always the next frame
@@ -103,6 +104,10 @@ namespace drawinglayer::primitive2d
maVirtualDeviceMask->EnableMapMode(false);
maVirtualDevice->SetOutputSizePixel(aTarget);
maVirtualDeviceMask->SetOutputSizePixel(aTarget);
+
+ // tdf#156630 make erase calls fill with transparency
+ maVirtualDevice->SetBackground(COL_BLACK);
+ maVirtualDeviceMask->SetBackground(COL_ALPHA_TRANSPARENT);
}
maVirtualDevice->Erase();
@@ -115,13 +120,13 @@ namespace drawinglayer::primitive2d
sal_uInt32 generateStepTime(sal_uInt32 nIndex) const
{
- const AnimationBitmap& rAnimationBitmap = maAnimation.Get(sal_uInt16(nIndex));
- sal_uInt32 nWaitTime(rAnimationBitmap.mnWait * 10);
+ const AnimationFrame& rAnimationFrame = maAnimation.Get(sal_uInt16(nIndex));
+ sal_uInt32 nWaitTime(rAnimationFrame.mnWait * 10);
// Take care of special value for MultiPage TIFFs. ATM these shall just
// show their first page. Later we will offer some switching when object
// is selected.
- if (ANIMATION_TIMEOUT_ON_CLICK == rAnimationBitmap.mnWait)
+ if (ANIMATION_TIMEOUT_ON_CLICK == rAnimationFrame.mnWait)
{
// ATM the huge value would block the timer, so
// use a long time to show first page (whole day)
@@ -180,14 +185,13 @@ namespace drawinglayer::primitive2d
}
else
{
- const Bitmap aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
+ Bitmap aMaskBitmap(maVirtualDeviceMask->GetBitmap(Point(), maVirtualDeviceMask->GetOutputSizePixel()));
+ // tdf#156630 invert the alpha mask
+ aMaskBitmap.Invert(); // convert from transparency to alpha
bitmap = BitmapEx(aMainBitmap, aMaskBitmap);
}
- return Primitive2DReference(
- new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(bitmap),
- getTransform()));
+ return new BitmapPrimitive2D(bitmap, getTransform());
}
void checkSafeToBuffer(sal_uInt32 nIndex)
@@ -249,14 +253,23 @@ namespace drawinglayer::primitive2d
while (mnNextFrameToPrepare <= nTarget)
{
// prepare step
- const AnimationBitmap& rAnimationBitmap = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare));
+ const AnimationFrame& rAnimationFrame = maAnimation.Get(sal_uInt16(mnNextFrameToPrepare));
+
+ bool bSourceBlending = rAnimationFrame.meBlend == Blend::Source;
+
+ if (bSourceBlending)
+ {
+ tools::Rectangle aArea(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmapEx.GetSizePixel());
+ maVirtualDevice->Erase(aArea);
+ maVirtualDeviceMask->Erase(aArea);
+ }
- switch (rAnimationBitmap.meDisposal)
+ switch (rAnimationFrame.meDisposal)
{
case Disposal::Not:
{
- maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx);
- Bitmap aAlphaMask = rAnimationBitmap.maBitmapEx.GetAlpha();
+ maVirtualDevice->DrawBitmapEx(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmapEx);
+ AlphaMask aAlphaMask = rAnimationFrame.maBitmapEx.GetAlphaMask();
if (aAlphaMask.IsEmpty())
{
@@ -267,8 +280,8 @@ namespace drawinglayer::primitive2d
}
else
{
- BitmapEx aExpandVisibilityMask(aAlphaMask, aAlphaMask);
- maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask);
+ BitmapEx aExpandVisibilityMask(aAlphaMask.GetBitmap(), aAlphaMask);
+ maVirtualDeviceMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aExpandVisibilityMask);
}
break;
@@ -276,32 +289,31 @@ namespace drawinglayer::primitive2d
case Disposal::Back:
{
// #i70772# react on no mask, for primitives, too.
- const Bitmap & rMask(rAnimationBitmap.maBitmapEx.GetAlpha());
- const Bitmap & rContent(rAnimationBitmap.maBitmapEx.GetBitmap());
+ const AlphaMask & rMask(rAnimationFrame.maBitmapEx.GetAlphaMask());
maVirtualDeviceMask->Erase();
- maVirtualDevice->DrawBitmap(rAnimationBitmap.maPositionPixel, rContent);
+ maVirtualDevice->DrawBitmapEx(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmapEx);
if (rMask.IsEmpty())
{
- const ::tools::Rectangle aRect(rAnimationBitmap.maPositionPixel, rContent.GetSizePixel());
+ const ::tools::Rectangle aRect(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmapEx.GetSizePixel());
maVirtualDeviceMask->SetFillColor(COL_BLACK);
maVirtualDeviceMask->SetLineColor();
maVirtualDeviceMask->DrawRect(aRect);
}
else
{
- BitmapEx aExpandVisibilityMask(rMask, rMask);
- maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask);
+ BitmapEx aExpandVisibilityMask(rMask.GetBitmap(), rMask);
+ maVirtualDeviceMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aExpandVisibilityMask);
}
break;
}
case Disposal::Previous:
{
- maVirtualDevice->DrawBitmapEx(rAnimationBitmap.maPositionPixel, rAnimationBitmap.maBitmapEx);
- BitmapEx aExpandVisibilityMask(rAnimationBitmap.maBitmapEx.GetAlpha(), rAnimationBitmap.maBitmapEx.GetAlpha());
- maVirtualDeviceMask->DrawBitmapEx(rAnimationBitmap.maPositionPixel, aExpandVisibilityMask);
+ maVirtualDevice->DrawBitmapEx(rAnimationFrame.maPositionPixel, rAnimationFrame.maBitmapEx);
+ BitmapEx aExpandVisibilityMask(rAnimationFrame.maBitmapEx.GetAlphaMask().GetBitmap(), rAnimationFrame.maBitmapEx.GetAlphaMask());
+ maVirtualDeviceMask->DrawBitmapEx(rAnimationFrame.maPositionPixel, aExpandVisibilityMask);
break;
}
}
@@ -342,7 +354,8 @@ namespace drawinglayer::primitive2d
/// constructor
AnimatedGraphicPrimitive2D(
const Graphic& rGraphic,
- const basegfx::B2DHomMatrix& rTransform);
+ basegfx::B2DHomMatrix aTransform);
+ virtual ~AnimatedGraphicPrimitive2D();
/// data read access
const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
@@ -358,12 +371,12 @@ namespace drawinglayer::primitive2d
AnimatedGraphicPrimitive2D::AnimatedGraphicPrimitive2D(
const Graphic& rGraphic,
- const basegfx::B2DHomMatrix& rTransform)
+ basegfx::B2DHomMatrix aTransform)
: AnimatedSwitchPrimitive2D(
animation::AnimationEntryList(),
Primitive2DContainer(),
false),
- maTransform(rTransform),
+ maTransform(std::move(aTransform)),
maGraphic(rGraphic),
maAnimation(rGraphic.GetAnimation()),
maVirtualDevice(*Application::GetDefaultDevice()),
@@ -402,10 +415,27 @@ namespace drawinglayer::primitive2d
// prepare buffer space
if (mbBufferingAllowed && isValidData())
{
- maBufferedPrimitives = Primitive2DContainer(maAnimation.Count());
+ maBufferedPrimitives.resize(maAnimation.Count());
}
}
+ AnimatedGraphicPrimitive2D::~AnimatedGraphicPrimitive2D()
+ {
+ // Related: tdf#158807 mutex must be locked when disposing a VirtualDevice
+ // If the following .ppt document is opened in a debug build
+ // and the document is left open for a minute or two without
+ // changing any content, this destructor will be called on a
+ // non-main thread with the mutex unlocked:
+ // https://bugs.documentfoundation.org/attachment.cgi?id=46801
+ // This hits an assert in VirtualDevice::ReleaseGraphics() so
+ // explicitly lock the mutex and explicitly dispose and clear
+ // the VirtualDevice instances variables.
+ const SolarMutexGuard aSolarGuard;
+
+ maVirtualDevice.disposeAndClear();
+ maVirtualDeviceMask.disposeAndClear();
+ }
+
bool AnimatedGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
// do not use 'GroupPrimitive2D::operator==' here, that would compare
@@ -489,17 +519,16 @@ namespace drawinglayer::primitive2d
if(rGraphic.IsAnimated())
{
// prepare specialized AnimatedGraphicPrimitive2D
- aRetval.resize(1);
- aRetval[0] = new AnimatedGraphicPrimitive2D(
+ aRetval = Primitive2DContainer { new AnimatedGraphicPrimitive2D(
rGraphic,
- rTransform);
+ rTransform) };
}
else if(rGraphic.getVectorGraphicData())
{
// embedded Vector Graphic Data fill, create embed transform
const basegfx::B2DRange& rSvgRange(rGraphic.getVectorGraphicData()->getRange());
- if(basegfx::fTools::more(rSvgRange.getWidth(), 0.0) && basegfx::fTools::more(rSvgRange.getHeight(), 0.0))
+ if(rSvgRange.getWidth() > 0.0 && rSvgRange.getHeight() > 0.0)
{
// translate back to origin, scale to unit coordinates
basegfx::B2DHomMatrix aEmbedVectorGraphic(
@@ -515,18 +544,16 @@ namespace drawinglayer::primitive2d
aEmbedVectorGraphic = rTransform * aEmbedVectorGraphic;
// add Vector Graphic Data primitives embedded
- aRetval.resize(1);
- aRetval[0] = new TransformPrimitive2D(
+ aRetval = Primitive2DContainer { new TransformPrimitive2D(
aEmbedVectorGraphic,
- Primitive2DContainer(rGraphic.getVectorGraphicData()->getPrimitive2DSequence()));
+ Primitive2DContainer(rGraphic.getVectorGraphicData()->getPrimitive2DSequence()))};
}
}
else
{
- aRetval.resize(1);
- aRetval[0] = new BitmapPrimitive2D(
- VCLUnoHelper::CreateVCLXBitmap(rGraphic.GetBitmapEx()),
- rTransform);
+ aRetval = Primitive2DContainer { new BitmapPrimitive2D(
+ rGraphic.GetBitmapEx(),
+ rTransform) };
}
break;
@@ -537,10 +564,9 @@ namespace drawinglayer::primitive2d
// create MetafilePrimitive2D
const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile();
- aRetval.resize(1);
- aRetval[0] = new MetafilePrimitive2D(
+ aRetval = Primitive2DContainer { new MetafilePrimitive2D(
rTransform,
- rMetafile);
+ rMetafile) };
// #i100357# find out if clipping is needed for this primitive. Unfortunately,
// there exist Metafiles who's content is bigger than the proposed PrefSize set
@@ -557,10 +583,11 @@ namespace drawinglayer::primitive2d
basegfx::B2DPolygon aMaskPolygon(basegfx::utils::createUnitPolygon());
aMaskPolygon.transform(rTransform);
- Primitive2DReference mask = new MaskPrimitive2D(
- basegfx::B2DPolyPolygon(aMaskPolygon),
- std::move(aRetval));
- aRetval = Primitive2DContainer { mask };
+ aRetval = Primitive2DContainer {
+ new MaskPrimitive2D(
+ basegfx::B2DPolyPolygon(aMaskPolygon),
+ std::move(aRetval))
+ };
}
break;
}
@@ -572,7 +599,7 @@ namespace drawinglayer::primitive2d
}
}
- rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
+ rContainer.append(std::move(aRetval));
}
Primitive2DContainer create2DColorModifierEmbeddingsAsNeeded(