summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand (Collabora) <Armin.Le.Grand@me.com>2024-07-23 13:26:34 +0200
committerArmin Le Grand <Armin.Le.Grand@me.com>2024-07-23 18:35:26 +0200
commit462d85709ead9c7cec33ce58fc608997263cb6aa (patch)
tree3eef2f07a6bef84a3ba02d49c9536ab58d5abfbf
parent863b90e33c4b9964a697684887aeb42cc538b019 (diff)
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 <Armin.Le.Grand@me.com> Tested-by: Jenkins
-rw-r--r--drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D.cxx27
-rw-r--r--drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx20
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitive2d.cxx19
-rw-r--r--drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx94
-rw-r--r--drawinglayer/source/processor2d/cairopixelprocessor2d.cxx34
-rw-r--r--drawinglayer/source/processor2d/d2dpixelprocessor2d.cxx14
-rw-r--r--drawinglayer/source/processor2d/hittestprocessor2d.cxx100
-rw-r--r--drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx9
-rw-r--r--drawinglayer/source/processor2d/vclprocessor2d.cxx17
-rw-r--r--include/drawinglayer/primitive2d/PolyPolygonGraphicPrimitive2D.hxx12
-rw-r--r--include/drawinglayer/primitive2d/fillgraphicprimitive2d.hxx14
-rw-r--r--include/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx7
-rw-r--r--include/drawinglayer/processor2d/hittestprocessor2d.hxx2
-rw-r--r--svx/source/sdr/contact/viewobjectcontact.cxx6
-rw-r--r--svx/source/sdr/primitive2d/sdrdecompositiontools.cxx11
15 files changed, 280 insertions, 106 deletions
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(