drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx  |   27 ++
 drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx         |   20 +-
 drawinglayer/source/primitive2d/graphicprimitive2d.cxx             |   19 -
 drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx       |   94 
++++++---
 drawinglayer/source/processor2d/cairopixelprocessor2d.cxx          |   34 ++-
 drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx            |   14 +
 drawinglayer/source/processor2d/hittestprocessor2d.cxx             |  100 
++++++----
 drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx         |    9 
 drawinglayer/source/processor2d/vclprocessor2d.cxx                 |   17 +
 include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx |   12 +
 include/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx        |   14 +
 include/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx      |    7 
 include/drawinglayer/processor2d/hittestprocessor2d.hxx            |    2 
 svx/source/sdr/contact/viewobjectcontact.cxx                       |    6 
 svx/source/sdr/primitive2d/sdrdecompositiontools.cxx               |   11 +
 15 files changed, 280 insertions(+), 106 deletions(-)

New commits:
commit 462d85709ead9c7cec33ce58fc608997263cb6aa
Author:     Armin Le Grand (Collabora) <[email protected]>
AuthorDate: Tue Jul 23 13:26:34 2024 +0200
Commit:     Armin Le Grand <[email protected]>
CommitDate: Tue Jul 23 18:35:26 2024 +0200

    CairoSDPR: Support alpha for BitmapPrimitives
    
    To more directly support an additional alpha channel
    for BitmapPrimitive data I have done some deeper
    changes to the primitive stack, in a compatible
    way. Quite some more graphic types and primitives
    now support an additional direct alpha value. All
    that is decomposed/created/broken down in a way
    that needs no changes for existing renderers, in
    already described ways.
    The CairoPixelProcessor2D already uses this in the
    processFillGraphicPrimitive2D implementation and
    thus in the FillGraphicPrimitive2D. This works since
    primitive productions now all try to create that
    FillGraphicPrimitive2D type including an additional
    alpha value - if possible and necessary.
    
    Change-Id: Ib1b16491a2b3aee16f14cc8196e28af30a7cf9be
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170900
    Reviewed-by: Armin Le Grand <[email protected]>
    Tested-by: Jenkins

diff --git a/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx 
b/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx
index 31a7acb03d7c..7853709b9541 100644
--- a/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx
+++ b/drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx
@@ -34,21 +34,36 @@ namespace drawinglayer::primitive2d
 Primitive2DReference PolyPolygonGraphicPrimitive2D::create2DDecomposition(
     const geometry::ViewInformation2D& /*rViewInformation*/) const
 {
+    if (basegfx::fTools::equal(getTransparency(), 1.0))
+    {
+        // completely transparent, done
+        return nullptr;
+    }
+
     if (getFillGraphic().isDefault())
+    {
+        // no geometry data, done
         return nullptr;
+    }
 
     const Graphic& rGraphic = getFillGraphic().getGraphic();
     const GraphicType aType(rGraphic.GetType());
 
     // is there a bitmap or a metafile (do we have content)?
     if (GraphicType::Bitmap != aType && GraphicType::GdiMetafile != aType)
+    {
+        // no geometry data, done
         return nullptr;
+    }
 
     const Size aPrefSize(rGraphic.GetPrefSize());
 
     // does content have a size?
     if (!(aPrefSize.Width() && aPrefSize.Height()))
+    {
+        // no geometry data with size, done
         return nullptr;
+    }
 
     // create SubSequence with FillGraphicPrimitive2D based on polygon range
     const basegfx::B2DRange aOutRange(getB2DPolyPolygon().getB2DRange());
@@ -85,11 +100,13 @@ Primitive2DReference 
PolyPolygonGraphicPrimitive2D::create2DDecomposition(
             getFillGraphic().getGraphic(), aAdaptedRange, 
getFillGraphic().getTiling(),
             getFillGraphic().getOffsetX(), getFillGraphic().getOffsetY());
 
-        xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, 
aAdaptedFillGraphicAttribute);
+        xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, 
aAdaptedFillGraphicAttribute,
+                                             getTransparency());
     }
     else
     {
-        xSubRef = new FillGraphicPrimitive2D(aNewObjectTransform, 
getFillGraphic());
+        xSubRef
+            = new FillGraphicPrimitive2D(aNewObjectTransform, 
getFillGraphic(), getTransparency());
     }
 
     // embed to mask primitive
@@ -98,10 +115,11 @@ Primitive2DReference 
PolyPolygonGraphicPrimitive2D::create2DDecomposition(
 
 PolyPolygonGraphicPrimitive2D::PolyPolygonGraphicPrimitive2D(
     basegfx::B2DPolyPolygon aPolyPolygon, const basegfx::B2DRange& 
rDefinitionRange,
-    const attribute::FillGraphicAttribute& rFillGraphic)
+    const attribute::FillGraphicAttribute& rFillGraphic, double fTransparency)
     : maPolyPolygon(std::move(aPolyPolygon))
     , maDefinitionRange(rDefinitionRange)
     , maFillGraphic(rFillGraphic)
+    , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
 {
 }
 
@@ -114,7 +132,8 @@ bool PolyPolygonGraphicPrimitive2D::operator==(const 
BasePrimitive2D& rPrimitive
 
         return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
                 && getDefinitionRange() == rCompare.getDefinitionRange()
-                && getFillGraphic() == rCompare.getFillGraphic());
+                && getFillGraphic() == rCompare.getFillGraphic()
+                && basegfx::fTools::equal(getTransparency(), 
rCompare.getTransparency()));
     }
 
     return false;
diff --git a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx 
b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
index 293f3738fa1b..5ef71c97aa33 100644
--- a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
@@ -69,7 +69,8 @@ namespace drawinglayer::primitive2d
                 Primitive2DContainer xSeq;
                 create2DDecompositionOfGraphic(xSeq,
                     rGraphic,
-                    basegfx::B2DHomMatrix());
+                    basegfx::B2DHomMatrix(),
+                    getTransparency());
 
                 rtl::Reference<GroupPrimitive2D> xGroup = new 
GroupPrimitive2D(std::move(xSeq));
                 for(const auto &a : aMatrices)
@@ -89,17 +90,21 @@ namespace drawinglayer::primitive2d
 
                 create2DDecompositionOfGraphic(aContainer,
                     rGraphic,
-                    aObjectTransform);
+                    aObjectTransform,
+                    getTransparency());
             }
+
             return new GroupPrimitive2D(std::move(aContainer));
         }
 
         FillGraphicPrimitive2D::FillGraphicPrimitive2D(
             basegfx::B2DHomMatrix aTransformation,
-            const attribute::FillGraphicAttribute& rFillGraphic)
-        :   maTransformation(std::move(aTransformation)),
-            maFillGraphic(rFillGraphic),
-            maOffsetXYCreatedBitmap()
+            const attribute::FillGraphicAttribute& rFillGraphic,
+            double fTransparency)
+        :   maTransformation(std::move(aTransformation))
+        , maFillGraphic(rFillGraphic)
+        , maOffsetXYCreatedBitmap()
+        , mfTransparency(std::max(0.0, std::min(1.0, fTransparency)))
         {
         }
 
@@ -110,7 +115,8 @@ namespace drawinglayer::primitive2d
                 const FillGraphicPrimitive2D& rCompare = static_cast< const 
FillGraphicPrimitive2D& >(rPrimitive);
 
                 return (getTransformation() == rCompare.getTransformation()
-                    && getFillGraphic() == rCompare.getFillGraphic());
+                    && getFillGraphic() == rCompare.getFillGraphic()
+                    && basegfx::fTools::equal(getTransparency(), 
rCompare.getTransparency()));
             }
 
             return false;
diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx 
b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
index 7d9f4233160b..457bd64c95c6 100644
--- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
@@ -113,9 +113,11 @@ GraphicPrimitive2D::create2DDecomposition(const 
geometry::ViewInformation2D&) co
     }
 
     // create sub-content; helper takes care of correct handling of
-    // bitmap, svg or metafile content
+    // bitmap, svg or metafile content. also handle alpha there directly
     Primitive2DContainer aRetval;
-    create2DDecompositionOfGraphic(aRetval, aTransformedGraphic, aTransform);
+    const double fTransparency(
+        std::clamp((255 - getGraphicAttr().GetAlpha()) * (1.0 / 255.0), 0.0, 
1.0));
+    create2DDecompositionOfGraphic(aRetval, aTransformedGraphic, aTransform, 
fTransparency);
 
     if (aRetval.empty())
     {
@@ -144,19 +146,6 @@ GraphicPrimitive2D::create2DDecomposition(const 
geometry::ViewInformation2D&) co
         }
     }
 
-    if (getGraphicAttr().IsTransparent())
-    {
-        // check for transparency
-        const double fTransparency(
-            std::clamp((255 - getGraphicAttr().GetAlpha()) * (1.0 / 255.0), 
0.0, 1.0));
-
-        if (!basegfx::fTools::equalZero(fTransparency))
-        {
-            aRetval = Primitive2DContainer{ new 
UnifiedTransparencePrimitive2D(std::move(aRetval),
-                                                                               
fTransparency) };
-        }
-    }
-
     if (getGraphicAttr().IsCropped())
     {
         // check for cropping
diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx 
b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
index d4d660228565..d97d1bd36245 100644
--- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
@@ -24,6 +24,8 @@
 #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
 #include <drawinglayer/animation/animationtiming.hxx>
 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
 #include <drawinglayer/primitive2d/animatedprimitive2d.hxx>
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
@@ -65,6 +67,9 @@ namespace drawinglayer::primitive2d
             /// local animation processing data, excerpt from maGraphic
             ::Animation                                 maAnimation;
 
+            /// the transparency in range [0.0 .. 1.0]
+            double mfTransparency;
+
             /// the on-demand created VirtualDevices for frame creation
             ScopedVclPtrInstance< VirtualDevice >       maVirtualDevice;
             ScopedVclPtrInstance< VirtualDevice >       maVirtualDeviceMask;
@@ -88,7 +93,8 @@ namespace drawinglayer::primitive2d
             {
                 return (GraphicType::Bitmap == maGraphic.GetType()
                     && maGraphic.IsAnimated()
-                    && maAnimation.Count());
+                    && maAnimation.Count()
+                    && !basegfx::fTools::equal(getTransparency(), 1.0));
             }
 
             void ensureVirtualDeviceSizeAndState()
@@ -192,7 +198,9 @@ namespace drawinglayer::primitive2d
                     bitmap = BitmapEx(aMainBitmap, aMaskBitmap);
                 }
 
-                return new BitmapPrimitive2D(bitmap, getTransform());
+                if(basegfx::fTools::equal(getTransparency(), 0.0))
+                    return new BitmapPrimitive2D(bitmap, getTransform());
+                return new BitmapAlphaPrimitive2D(bitmap, getTransform(), 
getTransparency());
             }
 
             void checkSafeToBuffer(sal_uInt32 nIndex)
@@ -355,11 +363,13 @@ namespace drawinglayer::primitive2d
             /// constructor
             AnimatedGraphicPrimitive2D(
                 const Graphic& rGraphic,
-                basegfx::B2DHomMatrix aTransform);
+                basegfx::B2DHomMatrix aTransform,
+                double fTransparency = 0.0);
             virtual ~AnimatedGraphicPrimitive2D();
 
             /// data read access
             const basegfx::B2DHomMatrix& getTransform() const { return 
maTransform; }
+            double getTransparency() const { return mfTransparency; }
 
             /// provide unique ID
             virtual sal_uInt32 getPrimitive2DID() const override { return 
PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D; }
@@ -378,7 +388,8 @@ namespace drawinglayer::primitive2d
 
         AnimatedGraphicPrimitive2D::AnimatedGraphicPrimitive2D(
             const Graphic& rGraphic,
-            basegfx::B2DHomMatrix aTransform)
+            basegfx::B2DHomMatrix aTransform,
+            double fTransparency)
         :   AnimatedSwitchPrimitive2D(
                 animation::AnimationEntryList(),
                 Primitive2DContainer(),
@@ -386,6 +397,7 @@ namespace drawinglayer::primitive2d
             maTransform(std::move(aTransform)),
             maGraphic(rGraphic),
             maAnimation(rGraphic.GetAnimation()),
+            mfTransparency(std::max(0.0, std::min(1.0, fTransparency))),
             maVirtualDevice(*Application::GetDefaultDevice()),
             maVirtualDeviceMask(*Application::GetDefaultDevice()),
             mnNextFrameToPrepare(SAL_MAX_UINT32),
@@ -529,9 +541,14 @@ namespace drawinglayer::primitive2d
         void create2DDecompositionOfGraphic(
             Primitive2DContainer& rContainer,
             const Graphic& rGraphic,
-            const basegfx::B2DHomMatrix& rTransform)
+            const basegfx::B2DHomMatrix& rTransform,
+            double fTransparency)
         {
-            Primitive2DContainer aRetval;
+            if (basegfx::fTools::equal(fTransparency, 1.0))
+            {
+                // completely transparent, done
+                return;
+            }
 
             switch(rGraphic.GetType())
             {
@@ -539,10 +556,12 @@ namespace drawinglayer::primitive2d
                 {
                     if(rGraphic.IsAnimated())
                     {
-                        // prepare specialized AnimatedGraphicPrimitive2D
-                        aRetval = Primitive2DContainer { new 
AnimatedGraphicPrimitive2D(
+                        // prepare specialized AnimatedGraphicPrimitive2D, now 
with
+                        // support for alpha
+                        rContainer.append(new AnimatedGraphicPrimitive2D(
                             rGraphic,
-                            rTransform) };
+                            rTransform,
+                            fTransparency));
                     }
                     else if(rGraphic.getVectorGraphicData())
                     {
@@ -565,16 +584,37 @@ namespace drawinglayer::primitive2d
                             aEmbedVectorGraphic = rTransform * 
aEmbedVectorGraphic;
 
                             // add Vector Graphic Data primitives embedded
-                            aRetval = Primitive2DContainer { new 
TransformPrimitive2D(
-                                aEmbedVectorGraphic,
-                                
Primitive2DContainer(rGraphic.getVectorGraphicData()->getPrimitive2DSequence()))};
+                            rtl::Reference<BasePrimitive2D> aPrimitive(
+                                new TransformPrimitive2D(
+                                    aEmbedVectorGraphic,
+                                    
Primitive2DContainer(rGraphic.getVectorGraphicData()->getPrimitive2DSequence())));
+
+                            // if needed embed to 
UnifiedTransparencePrimitive2D
+                            if (!basegfx::fTools::equalZero(fTransparency, 
0.0))
+                                aPrimitive = new 
UnifiedTransparencePrimitive2D(
+                                    Primitive2DContainer { aPrimitive }, 
fTransparency);
+
+                            rContainer.append(aPrimitive);
                         }
                     }
                     else
                     {
-                        aRetval = Primitive2DContainer { new BitmapPrimitive2D(
-                            rGraphic.GetBitmapEx(),
-                            rTransform) };
+                        // dependent of transparency used create the needed 
bitmap primitive
+                        if(basegfx::fTools::equal(fTransparency, 0.0))
+                        {
+                            rContainer.append(
+                                new BitmapPrimitive2D(
+                                    rGraphic.GetBitmapEx(),
+                                    rTransform));
+                        }
+                        else
+                        {
+                            rContainer.append(
+                                new BitmapAlphaPrimitive2D(
+                                    rGraphic.GetBitmapEx(),
+                                    rTransform,
+                                    fTransparency));
+                        }
                     }
 
                     break;
@@ -585,9 +625,10 @@ namespace drawinglayer::primitive2d
                     // create MetafilePrimitive2D
                     const GDIMetaFile& rMetafile = rGraphic.GetGDIMetaFile();
 
-                    aRetval = Primitive2DContainer { new MetafilePrimitive2D(
-                        rTransform,
-                        rMetafile) };
+                    rtl::Reference<BasePrimitive2D> aPrimitive(
+                        new MetafilePrimitive2D(
+                            rTransform,
+                            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
@@ -604,12 +645,17 @@ namespace drawinglayer::primitive2d
                         basegfx::B2DPolygon 
aMaskPolygon(basegfx::utils::createUnitPolygon());
                         aMaskPolygon.transform(rTransform);
 
-                        aRetval = Primitive2DContainer {
-                            new MaskPrimitive2D(
-                                basegfx::B2DPolyPolygon(aMaskPolygon),
-                                std::move(aRetval))
-                        };
+                        aPrimitive = new MaskPrimitive2D(
+                            basegfx::B2DPolyPolygon(aMaskPolygon),
+                            Primitive2DContainer { aPrimitive });
                     }
+
+                    // if needed embed to UnifiedTransparencePrimitive2D
+                    if (!basegfx::fTools::equalZero(fTransparency, 0.0))
+                        aPrimitive = new UnifiedTransparencePrimitive2D(
+                            Primitive2DContainer { aPrimitive }, 
fTransparency);
+
+                    rContainer.append(aPrimitive);
                     break;
                 }
 
@@ -619,8 +665,6 @@ namespace drawinglayer::primitive2d
                     break;
                 }
             }
-
-            rContainer.append(std::move(aRetval));
         }
 
         Primitive2DContainer create2DColorModifierEmbeddingsAsNeeded(
diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
index 2fc46f4dda21..2f5fad1e2c59 100644
--- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
@@ -1828,6 +1828,13 @@ void CairoPixelProcessor2D::processSingleLinePrimitive2D(
 void CairoPixelProcessor2D::processFillGraphicPrimitive2D(
     const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D)
 {
+    if (rFillGraphicPrimitive2D.getTransparency() < 0.0
+        || rFillGraphicPrimitive2D.getTransparency() > 1.0)
+    {
+        // invalid transparence, done
+        return;
+    }
+
     BitmapEx aPreparedBitmap;
     basegfx::B2DRange 
aFillUnitRange(rFillGraphicPrimitive2D.getFillGraphic().getGraphicRange());
     constexpr double fBigDiscreteArea(300.0 * 300.0);
@@ -1870,12 +1877,24 @@ void 
CairoPixelProcessor2D::processFillGraphicPrimitive2D(
             // local primitive, that is not part of DisplayInfo yet
             aPolygon.transform(rFillGraphicPrimitive2D.getTransformation());
 
-            rtl::Reference<primitive2d::PolyPolygonColorPrimitive2D> aTemp(
-                new 
primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon),
-                                                             aModifiedColor));
+            if (rFillGraphicPrimitive2D.hasTransparency())
+            {
+                rtl::Reference<primitive2d::PolyPolygonRGBAPrimitive2D> aTemp(
+                    new primitive2d::PolyPolygonRGBAPrimitive2D(
+                        basegfx::B2DPolyPolygon(aPolygon), aModifiedColor,
+                        rFillGraphicPrimitive2D.getTransparency()));
+                // draw as colored and transparent Polygon, done
+                processPolyPolygonRGBAPrimitive2D(*aTemp);
+            }
+            else
+            {
+                rtl::Reference<primitive2d::PolyPolygonColorPrimitive2D> aTemp(
+                    new 
primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon),
+                                                                 
aModifiedColor));
+                // draw as colored Polygon, done
+                processPolyPolygonColorPrimitive2D(*aTemp);
+            }
 
-            // draw as colored Polygon, done
-            processPolyPolygonColorPrimitive2D(*aTemp);
             return;
         }
     }
@@ -1941,7 +1960,10 @@ void 
CairoPixelProcessor2D::processFillGraphicPrimitive2D(
     cairo_pattern_set_extend(sourcepattern, CAIRO_EXTEND_REPEAT);
 
     // paint
-    cairo_paint(mpRT);
+    if (rFillGraphicPrimitive2D.hasTransparency())
+        cairo_paint_with_alpha(mpRT, 1.0 - 
rFillGraphicPrimitive2D.getTransparency());
+    else
+        cairo_paint(mpRT);
 
     static bool bRenderTransformationBounds(false);
     if (bRenderTransformationBounds)
diff --git a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
index 7bc422a98f43..986515c6e339 100644
--- a/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx
@@ -1803,6 +1803,20 @@ void D2DPixelProcessor2D::processSingleLinePrimitive2D(
 void D2DPixelProcessor2D::processFillGraphicPrimitive2D(
     const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D)
 {
+    if (rFillGraphicPrimitive2D.getTransparency() < 0.0
+        || rFillGraphicPrimitive2D.getTransparency() > 1.0)
+    {
+        // invalid transparence, done
+        return;
+    }
+
+    if (rFillGraphicPrimitive2D.hasTransparency())
+    {
+        // cannot handle yet, use decomposition
+        process(rFillGraphicPrimitive2D);
+        return;
+    }
+
     BitmapEx aPreparedBitmap;
     basegfx::B2DRange 
aFillUnitRange(rFillGraphicPrimitive2D.getFillGraphic().getGraphicRange());
     constexpr double fBigDiscreteArea(300.0 * 300.0);
diff --git a/drawinglayer/source/processor2d/hittestprocessor2d.cxx 
b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
index a6fc3978b733..435bc7f804fe 100644
--- a/drawinglayer/source/processor2d/hittestprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/hittestprocessor2d.cxx
@@ -24,6 +24,7 @@
 #include <drawinglayer/primitive2d/PolygonMarkerPrimitive2D.hxx>
 #include <drawinglayer/primitive2d/PolygonWavePrimitive2D.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
 #include <basegfx/polygon/b2dpolypolygontools.hxx>
 #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
@@ -143,6 +144,46 @@ namespace drawinglayer::processor2d
             return bRetval;
         }
 
+        void HitTestProcessor2D::checkBitmapHit(basegfx::B2DRange aRange, 
const BitmapEx& rBitmapEx, const basegfx::B2DHomMatrix& rTransform)
+        {
+            if(!getHitTextOnly())
+            {
+                // The recently added BitmapEx::GetTransparency() makes it 
easy to extend
+                // the BitmapPrimitive2D HitTest to take the contained 
BitmapEx and it's
+                // transparency into account
+                if(!aRange.isEmpty())
+                {
+                    const Size& rSizePixel(rBitmapEx.GetSizePixel());
+
+                    // When tiled rendering, don't bother with the pixel size 
of the candidate.
+                    if(rSizePixel.Width() && rSizePixel.Height() && 
!comphelper::LibreOfficeKit::isActive())
+                    {
+                        basegfx::B2DHomMatrix aBackTransform(
+                            
getViewInformation2D().getObjectToViewTransformation() *
+                            rTransform);
+                        aBackTransform.invert();
+
+                        const basegfx::B2DPoint aRelativePoint(aBackTransform 
* getDiscreteHitPosition());
+                        const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+
+                        if(aUnitRange.isInside(aRelativePoint))
+                        {
+                            const sal_Int32 
nX(basegfx::fround(aRelativePoint.getX() * rSizePixel.Width()));
+                            const sal_Int32 
nY(basegfx::fround(aRelativePoint.getY() * rSizePixel.Height()));
+
+                            mbHit = (0 != rBitmapEx.GetAlpha(nX, nY));
+                        }
+                    }
+                    else
+                    {
+                        // fallback to standard HitTest
+                        const basegfx::B2DPolygon 
aOutline(basegfx::utils::createPolygonFromRect(aRange));
+                        mbHit = 
checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), 
getDiscreteHitTolerance());
+                    }
+                }
+            }
+        }
+
         void HitTestProcessor2D::check3DHit(const 
primitive2d::ScenePrimitive2D& rCandidate)
         {
             // calculate relative point in unified 2D scene
@@ -416,49 +457,28 @@ namespace drawinglayer::processor2d
 
                     break;
                 }
-                case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+                case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D :
                 {
-                    if(!getHitTextOnly())
-                    {
-                        // The recently added BitmapEx::GetTransparency() 
makes it easy to extend
-                        // the BitmapPrimitive2D HitTest to take the contained 
BitmapEx and it's
-                        // transparency into account
-                        const basegfx::B2DRange 
aRange(rCandidate.getB2DRange(getViewInformation2D()));
-
-                        if(!aRange.isEmpty())
-                        {
-                            const primitive2d::BitmapPrimitive2D& 
rBitmapCandidate(static_cast< const primitive2d::BitmapPrimitive2D& 
>(rCandidate));
-                            const BitmapEx 
aBitmapEx(rBitmapCandidate.getBitmap());
-                            const Size& rSizePixel(aBitmapEx.GetSizePixel());
-
-                            // When tiled rendering, don't bother with the 
pixel size of the candidate.
-                            if(rSizePixel.Width() && rSizePixel.Height() && 
!comphelper::LibreOfficeKit::isActive())
-                            {
-                                basegfx::B2DHomMatrix aBackTransform(
-                                    
getViewInformation2D().getObjectToViewTransformation() *
-                                    rBitmapCandidate.getTransform());
-                                aBackTransform.invert();
+                    // avoid decompose of this primitive by handling directly
+                    const primitive2d::BitmapAlphaPrimitive2D& 
rBitmapAlphaCandidate(static_cast< const primitive2d::BitmapAlphaPrimitive2D& 
>(rCandidate));
 
-                                const basegfx::B2DPoint 
aRelativePoint(aBackTransform * getDiscreteHitPosition());
-                                const basegfx::B2DRange aUnitRange(0.0, 0.0, 
1.0, 1.0);
-
-                                if(aUnitRange.isInside(aRelativePoint))
-                                {
-                                    const sal_Int32 
nX(basegfx::fround(aRelativePoint.getX() * rSizePixel.Width()));
-                                    const sal_Int32 
nY(basegfx::fround(aRelativePoint.getY() * rSizePixel.Height()));
-
-                                    mbHit = (0 != aBitmapEx.GetAlpha(nX, nY));
-                                }
-                            }
-                            else
-                            {
-                                // fallback to standard HitTest
-                                const basegfx::B2DPolygon 
aOutline(basegfx::utils::createPolygonFromRect(aRange));
-                                mbHit = 
checkFillHitWithTolerance(basegfx::B2DPolyPolygon(aOutline), 
getDiscreteHitTolerance());
-                            }
-                        }
+                    if 
(!basegfx::fTools::equal(rBitmapAlphaCandidate.getTransparency(), 1.0))
+                    {
+                        checkBitmapHit(
+                            rCandidate.getB2DRange(getViewInformation2D()),
+                            rBitmapAlphaCandidate.getBitmap(),
+                            rBitmapAlphaCandidate.getTransform());
                     }
-
+                    break;
+                }
+                case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D :
+                {
+                    // use common tooling
+                    const primitive2d::BitmapPrimitive2D& 
rBitmapCandidate(static_cast< const primitive2d::BitmapPrimitive2D& 
>(rCandidate));
+                    checkBitmapHit(
+                        rCandidate.getB2DRange(getViewInformation2D()),
+                        rBitmapCandidate.getBitmap(),
+                        rBitmapCandidate.getTransform());
                     break;
                 }
                 case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D :
diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index f12be451b03a..3ec3c4922260 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -1867,10 +1867,11 @@ void 
VclMetafileProcessor2D::processPolyPolygonGraphicPrimitive2D(
         aTransform.matrix[5] = aTransformPosition.getY();
 
         pSvtGraphicFill.reset(new SvtGraphicFill(
-            getFillPolyPolygon(aLocalPolyPolygon), Color(), 0.0, 
SvtGraphicFill::fillEvenOdd,
-            SvtGraphicFill::fillTexture, aTransform, 
rFillGraphicAttribute.getTiling(),
-            SvtGraphicFill::hatchSingle, Color(), 
SvtGraphicFill::GradientType::Linear, Color(),
-            Color(), 0, rFillGraphicAttribute.getGraphic()));
+            getFillPolyPolygon(aLocalPolyPolygon), Color(), 
rBitmapCandidate.getTransparency(),
+            SvtGraphicFill::fillEvenOdd, SvtGraphicFill::fillTexture, 
aTransform,
+            rFillGraphicAttribute.getTiling(), SvtGraphicFill::hatchSingle, 
Color(),
+            SvtGraphicFill::GradientType::Linear, Color(), Color(), 0,
+            rFillGraphicAttribute.getGraphic()));
     }
 
     // Do use decomposition; encapsulate with SvtGraphicFill
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx 
b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index f7fd3fda7606..b783bdc69723 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -550,6 +550,20 @@ void VclProcessor2D::RenderBitmapPrimitive2D(const 
primitive2d::BitmapPrimitive2
 void VclProcessor2D::RenderFillGraphicPrimitive2D(
     const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
 {
+    if (rFillBitmapCandidate.getTransparency() < 0.0
+        || rFillBitmapCandidate.getTransparency() > 1.0)
+    {
+        // invalid transparence, done
+        return;
+    }
+
+    if (rFillBitmapCandidate.hasTransparency())
+    {
+        // cannot handle yet, use decomposition
+        process(rFillBitmapCandidate);
+        return;
+    }
+
     bool bPrimitiveAccepted = 
RenderFillGraphicPrimitive2DImpl(rFillBitmapCandidate);
 
     if (!bPrimitiveAccepted)
@@ -820,7 +834,8 @@ void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(
             case GraphicType::Bitmap:
             {
                 if (!rFillGraphicAttribute.getGraphic().IsTransparent()
-                    && !rFillGraphicAttribute.getGraphic().IsAlpha())
+                    && !rFillGraphicAttribute.getGraphic().IsAlpha()
+                    && !rPolygonCandidate.hasTransparency())
                 {
                     // bitmap is not transparent and has no alpha
                     const sal_uInt32 
nBColorModifierStackCount(maBColorModifierStack.count());
diff --git a/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx 
b/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx
index f364ba7f19db..0b0e2ee4dbf2 100644
--- a/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx
+++ b/include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx
@@ -32,6 +32,10 @@ namespace drawinglayer::primitive2d
     This primitive defines a tools::PolyPolygon filled with bitmap data
     (including transparence). The decomosition will create a MaskPrimitive2D
     containing a FillGraphicPrimitive2D.
+
+    SDPR: support alpha now directly: the decompositon creates
+    FillGraphicPrimitive2D which also supports alpha directly
+    now. All direct usages are covered
  */
 class DRAWINGLAYER_DLLPUBLIC PolyPolygonGraphicPrimitive2D final
     : public BufferedDecompositionPrimitive2D
@@ -46,6 +50,9 @@ private:
     /// the bitmap fill definition (may include tiling)
     attribute::FillGraphicAttribute maFillGraphic;
 
+    /// the transparency in range [0.0 .. 1.0]
+    double mfTransparency;
+
     /// local decomposition.
     virtual Primitive2DReference
     create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) 
const override;
@@ -53,12 +60,15 @@ private:
 public:
     PolyPolygonGraphicPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon,
                                   const basegfx::B2DRange& rDefinitionRange,
-                                  const attribute::FillGraphicAttribute& 
rFillGraphic);
+                                  const attribute::FillGraphicAttribute& 
rFillGraphic,
+                                  double fTransparency = 0.0);
 
     /// data read access
     const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return 
maPolyPolygon; }
     const basegfx::B2DRange& getDefinitionRange() const { return 
maDefinitionRange; }
     const attribute::FillGraphicAttribute& getFillGraphic() const { return 
maFillGraphic; }
+    double getTransparency() const { return mfTransparency; }
+    bool hasTransparency() const { return 
!basegfx::fTools::equalZero(mfTransparency); }
 
     /// compare operator
     virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
diff --git a/include/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx 
b/include/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx
index d43df3da84e4..784117ae880c 100644
--- a/include/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx
@@ -56,6 +56,12 @@ namespace drawinglayer::primitive2d
             Renderers should handle this primitive; it has a geometrically 
correct
             decomposition, but on pixel outputs the areas where the tiled 
pieces are
             aligned tend to show up (one overlapping or empty pixel)
+
+            SDPR: support alpha directly now. If a primitive processor
+            cannot deal with it, use it's decomposition. The decompositon
+            uses create2DDecompositionOfGraphic, there all paths are now
+            capable of handling a given alpha, including metafile, SVG and
+            animated graphics
          */
         class DRAWINGLAYER_DLLPUBLIC FillGraphicPrimitive2D final : public 
BufferedDecompositionPrimitive2D
         {
@@ -69,6 +75,9 @@ namespace drawinglayer::primitive2d
             /// the evtl. buffered OffsetXYCreatedBitmap
             BitmapEx                                    
maOffsetXYCreatedBitmap;
 
+            /// the transparency in range [0.0 .. 1.0]
+            double mfTransparency;
+
             /// local decomposition.
             virtual Primitive2DReference create2DDecomposition(const 
geometry::ViewInformation2D& rViewInformation) const override;
 
@@ -87,12 +96,15 @@ namespace drawinglayer::primitive2d
             /// constructor
             FillGraphicPrimitive2D(
                 basegfx::B2DHomMatrix aTransformation,
-                const attribute::FillGraphicAttribute& rFillGraphic);
+                const attribute::FillGraphicAttribute& rFillGraphic,
+                double fTransparency = 0.0);
 
             /// data read access
             const basegfx::B2DHomMatrix& getTransformation() const { return 
maTransformation; }
             const attribute::FillGraphicAttribute& getFillGraphic() const { 
return maFillGraphic; }
             const BitmapEx& getOffsetXYCreatedBitmap() const { return 
maOffsetXYCreatedBitmap; }
+            double getTransparency() const { return mfTransparency; }
+            bool hasTransparency() const { return 
!basegfx::fTools::equalZero(mfTransparency); }
 
             /// compare operator
             virtual bool operator==( const BasePrimitive2D& rPrimitive ) const 
override;
diff --git a/include/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx 
b/include/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx
index 6aa8ef5191ce..024ad3fce28a 100644
--- a/include/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx
+++ b/include/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx
@@ -33,11 +33,16 @@ namespace drawinglayer::primitive2d
             and GraphicPrimitive2D at the same time. It is able to handle
             Bitmaps (with the sub-categories animated bitmap, and SVG),
             and Metafiles.
+
+            SDPR: create2DDecompositionOfGraphic now supports a given
+            alpha directly: all paths are now capable of handling a
+            given alpha, including metafile, SVG and animated graphics
          */
         void DRAWINGLAYER_DLLPUBLIC create2DDecompositionOfGraphic(
             Primitive2DContainer& rContainer,
             const Graphic& rGraphic,
-            const basegfx::B2DHomMatrix& rTransform);
+            const basegfx::B2DHomMatrix& rTransform,
+            double fTransparency = 0.0);
 
         /** Helper to embed given sequence of primitives to evtl. a stack
             of ModifiedColorPrimitive2D's to get all the needed modifications
diff --git a/include/drawinglayer/processor2d/hittestprocessor2d.hxx 
b/include/drawinglayer/processor2d/hittestprocessor2d.hxx
index 6d092efe983a..0f1f6d232d85 100644
--- a/include/drawinglayer/processor2d/hittestprocessor2d.hxx
+++ b/include/drawinglayer/processor2d/hittestprocessor2d.hxx
@@ -27,6 +27,7 @@
 namespace basegfx { class B2DPolygon; }
 namespace basegfx { class B2DPolyPolygon; }
 namespace drawinglayer::primitive2d { class ScenePrimitive2D; }
+class BitmapEx;
 
 namespace drawinglayer::processor2d
     {
@@ -65,6 +66,7 @@ namespace drawinglayer::processor2d
                 const basegfx::B2DPolyPolygon& rPolyPolygon,
                 const basegfx::B2DVector& rDiscreteHitTolerancePerAxis) const;
             void check3DHit(const primitive2d::ScenePrimitive2D& rCandidate);
+            void checkBitmapHit(basegfx::B2DRange aRange, const BitmapEx& 
rBitmapEx, const basegfx::B2DHomMatrix& rTransform);
 
         public:
             HitTestProcessor2D(
diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx 
b/svx/source/sdr/contact/viewobjectcontact.cxx
index 987f51b6d0cb..e7ee53f55f74 100644
--- a/svx/source/sdr/contact/viewobjectcontact.cxx
+++ b/svx/source/sdr/contact/viewobjectcontact.cxx
@@ -126,7 +126,11 @@ void 
AnimatedExtractingProcessor2D::processBasePrimitive2D(const drawinglayer::p
             {
                 // create temporary GraphicPrimitive to recursively extract 
evtl. animation
                 drawinglayer::primitive2d::Primitive2DContainer aContainer;
-                
drawinglayer::primitive2d::create2DDecompositionOfGraphic(aContainer, rGraphic, 
rFill.getTransformation());
+                drawinglayer::primitive2d::create2DDecompositionOfGraphic(
+                    aContainer,
+                    rGraphic,
+                    rFill.getTransformation(),
+                    rFill.getTransparency());
                 process(aContainer);
             }
 
diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx 
b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
index 7f315cb2486a..53b0ae33b711 100644
--- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
+++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
@@ -434,6 +434,16 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
             }
             else if(!rFill.getFillGraphic().isDefault())
             {
+                // SDPR: check early if we have alpha and add directly
+                if(0.0 != rFill.getTransparence())
+                {
+                    return new PolyPolygonGraphicPrimitive2D(
+                        rPolyPolygon,
+                        rDefinitionRange,
+                        
rFill.getFillGraphic().createFillGraphicAttribute(rDefinitionRange),
+                        rFill.getTransparence());
+                }
+
                 pNewFillPrimitive = new PolyPolygonGraphicPrimitive2D(
                     rPolyPolygon,
                     rDefinitionRange,
@@ -448,6 +458,7 @@ sal_uInt32 
SlideBackgroundFillPrimitive2D::getPrimitive2DID() const
             }
             else
             {
+                // SDPR: check early if we have alpha and add directly
                 if(0.0 != rFill.getTransparence())
                 {
                     return new PolyPolygonRGBAPrimitive2D(

Reply via email to