diff options
Diffstat (limited to 'drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx')
-rw-r--r-- | drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx | 121 |
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( |