drawinglayer/Library_drawinglayer.mk | 1 drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx | 99 ++++++++++ drawinglayer/source/primitive2d/Tools.cxx | 2 drawinglayer/source/processor2d/cairopixelprocessor2d.cxx | 50 ++++- drawinglayer/source/tools/primitive2dxmldump.cxx | 15 + include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx | 86 ++++++++ include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx | 1 include/drawinglayer/processor2d/cairopixelprocessor2d.hxx | 10 + svx/qa/unit/table.cxx | 4 svx/source/sdr/primitive2d/sdrdecompositiontools.cxx | 9 10 files changed, 271 insertions(+), 6 deletions(-)
New commits: commit 7297b0788f8f20ba6ab0973f944a4d522d666108 Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Fri Jul 19 14:35:39 2024 +0200 Commit: Armin Le Grand <[email protected]> CommitDate: Sat Jul 20 14:19:35 2024 +0200 CairoSDPR: Support direct RGBA paint of PolyPolygons Change-Id: Id1480297126bcc422945df7cd47993cc7fe5c22a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170768 Reviewed-by: Armin Le Grand <[email protected]> Tested-by: Jenkins diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk index beef19918f7c..18578664cf67 100644 --- a/drawinglayer/Library_drawinglayer.mk +++ b/drawinglayer/Library_drawinglayer.mk @@ -142,6 +142,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/primitive2d/PolyPolygonMarkerPrimitive2D \ drawinglayer/source/primitive2d/PolyPolygonStrokePrimitive2D \ drawinglayer/source/primitive2d/PolyPolygonColorPrimitive2D \ + drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D \ drawinglayer/source/primitive2d/PolyPolygonGradientPrimitive2D \ drawinglayer/source/primitive2d/PolyPolygonHatchPrimitive2D \ drawinglayer/source/primitive2d/PolyPolygonGraphicPrimitive2D \ diff --git a/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx b/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx new file mode 100644 index 000000000000..eb453116c97c --- /dev/null +++ b/drawinglayer/source/primitive2d/PolyPolygonRGBAPrimitive2D.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +using namespace com::sun::star; + +namespace drawinglayer::primitive2d +{ +Primitive2DReference PolyPolygonRGBAPrimitive2D::create2DDecomposition( + const geometry::ViewInformation2D& /*rViewInformation*/) const +{ + if (basegfx::fTools::equal(getTransparency(), 1.0)) + { + // completely transparent, done + return nullptr; + } + + if (0 == getB2DPolyPolygon().count()) + { + // no geometry, done + return nullptr; + } + + if (basegfx::fTools::equalZero(getTransparency())) + { + // no transparency, use simple PolyPolygonColorPrimitive2D + return Primitive2DReference{ new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(), + getBColor()) }; + } + + // default: embed to UnifiedTransparencePrimitive2D + Primitive2DContainer aContent{ new PolyPolygonColorPrimitive2D(getB2DPolyPolygon(), + getBColor()) }; + return Primitive2DReference{ new UnifiedTransparencePrimitive2D(std::move(aContent), + getTransparency()) }; +} + +PolyPolygonRGBAPrimitive2D::PolyPolygonRGBAPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon, + const basegfx::BColor& rBColor, + double fTransparency) + : maPolyPolygon(std::move(aPolyPolygon)) + , maBColor(rBColor) + , mfTransparency(std::max(0.0, std::min(1.0, fTransparency))) +{ +} + +bool PolyPolygonRGBAPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const +{ + if (BufferedDecompositionPrimitive2D::operator==(rPrimitive)) + { + const PolyPolygonRGBAPrimitive2D& rCompare + = static_cast<const PolyPolygonRGBAPrimitive2D&>(rPrimitive); + + return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon() + && getBColor() == rCompare.getBColor() + && basegfx::fTools::equal(getTransparency(), rCompare.getTransparency())); + } + + return false; +} + +basegfx::B2DRange PolyPolygonRGBAPrimitive2D::getB2DRange( + const geometry::ViewInformation2D& /*rViewInformation*/) const +{ + // return range + return basegfx::utils::getRange(getB2DPolyPolygon()); +} + +// provide unique ID +sal_uInt32 PolyPolygonRGBAPrimitive2D::getPrimitive2DID() const +{ + return PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D; +} +} // end of namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/primitive2d/Tools.cxx b/drawinglayer/source/primitive2d/Tools.cxx index cef1829e1567..bd0011ab4625 100644 --- a/drawinglayer/source/primitive2d/Tools.cxx +++ b/drawinglayer/source/primitive2d/Tools.cxx @@ -235,6 +235,8 @@ OUString idToString(sal_uInt32 nId) return u"EXCLUSIVEEDITVIEWPRIMITIVE2D"_ustr; case PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D: return u"ANIMATEDGRAPHICPRIMITIVE2D"_ustr; + case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D: + return u"POLYPOLYGONRGBAPRIMITIVE2D"_ustr; default: return OUString::number((nId >> 16) & 0xFF) + "|" + OUString::number(nId & 0xFF); } diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx index 365384375e05..e7183dbacaae 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -37,6 +37,7 @@ #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> #include <drawinglayer/primitive2d/invertprimitive2d.hxx> #include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx> +#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx> #include <drawinglayer/converters.hxx> #include <basegfx/curve/b2dcubicbezier.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> @@ -1052,7 +1053,20 @@ void CairoPixelProcessor2D::processPolygonHairlinePrimitive2D( void CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D( const primitive2d::PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D) { - const basegfx::B2DPolyPolygon& rPolyPolygon(rPolyPolygonColorPrimitive2D.getB2DPolyPolygon()); + paintPolyPoylgonRGBA(rPolyPolygonColorPrimitive2D.getB2DPolyPolygon(), + rPolyPolygonColorPrimitive2D.getBColor()); +} + +void CairoPixelProcessor2D::paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rColor, + double fTransparency) +{ + // transparency invalid or completely transparent, done + if (fTransparency < 0.0 || fTransparency >= 1.0) + { + return; + } + const sal_uInt32 nCount(rPolyPolygon.count()); if (!nCount) @@ -1074,9 +1088,14 @@ void CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D( cairo_set_matrix(mpRT, &aMatrix); // determine & set color - const basegfx::BColor aFillColor( - maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor())); - cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(), aFillColor.getBlue()); + const basegfx::BColor aFillColor(maBColorModifierStack.getModifiedColor(rColor)); + + if (!basegfx::fTools::equalZero(fTransparency)) + cairo_set_source_rgba(mpRT, aFillColor.getRed(), aFillColor.getGreen(), + aFillColor.getBlue(), 1.0 - fTransparency); + else + cairo_set_source_rgb(mpRT, aFillColor.getRed(), aFillColor.getGreen(), + aFillColor.getBlue()); // get PathGeometry & paint it cairo_new_path(mpRT); @@ -2636,6 +2655,23 @@ void CairoPixelProcessor2D::processFillGradientPrimitive2D( } } +void CairoPixelProcessor2D::processPolyPolygonRGBAPrimitive2D( + const primitive2d::PolyPolygonRGBAPrimitive2D& rPolyPolygonRGBAPrimitive2D) +{ + if (!rPolyPolygonRGBAPrimitive2D.hasTransparency()) + { + // do what CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D does + paintPolyPoylgonRGBA(rPolyPolygonRGBAPrimitive2D.getB2DPolyPolygon(), + rPolyPolygonRGBAPrimitive2D.getBColor()); + return; + } + + // draw wiath alpha directly + paintPolyPoylgonRGBA(rPolyPolygonRGBAPrimitive2D.getB2DPolyPolygon(), + rPolyPolygonRGBAPrimitive2D.getBColor(), + rPolyPolygonRGBAPrimitive2D.getTransparency()); +} + void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch (rCandidate.getPrimitive2DID()) @@ -2752,6 +2788,12 @@ void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimit static_cast<const primitive2d::FillGradientPrimitive2D&>(rCandidate)); break; } + case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D: + { + processPolyPolygonRGBAPrimitive2D( + static_cast<const primitive2d::PolyPolygonRGBAPrimitive2D&>(rCandidate)); + break; + } // continue with decompose default: diff --git a/drawinglayer/source/tools/primitive2dxmldump.cxx b/drawinglayer/source/tools/primitive2dxmldump.cxx index e16e2a5e6e0c..55c581dab510 100644 --- a/drawinglayer/source/tools/primitive2dxmldump.cxx +++ b/drawinglayer/source/tools/primitive2dxmldump.cxx @@ -42,6 +42,7 @@ #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> #include <drawinglayer/primitive2d/sceneprimitive2d.hxx> #include <drawinglayer/primitive2d/shadowprimitive2d.hxx> +#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx> #include <drawinglayer/geometry/viewinformation2d.hxx> #include <drawinglayer/attribute/lineattribute.hxx> #include <drawinglayer/attribute/fontattribute.hxx> @@ -1214,6 +1215,20 @@ void Primitive2dXmlDump::decomposeAndWrite( break; } + case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D: + { + const PolyPolygonRGBAPrimitive2D& rPolyPolygonRGBAPrimitive2D + = dynamic_cast<const PolyPolygonRGBAPrimitive2D&>(*pBasePrimitive); + rWriter.startElement("polypolygonrgba"); + rWriter.attribute("color", + convertColorToString(rPolyPolygonRGBAPrimitive2D.getBColor())); + rWriter.attribute("transparence", + std::lround(100 * rPolyPolygonRGBAPrimitive2D.getTransparency())); + writePolyPolygon(rWriter, rPolyPolygonRGBAPrimitive2D.getB2DPolyPolygon()); + rWriter.endElement(); + break; + } + default: { rWriter.startElement("unhandled"); diff --git a/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx b/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx new file mode 100644 index 000000000000..14a3a8199c2f --- /dev/null +++ b/include/drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <drawinglayer/drawinglayerdllapi.h> + +#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/numeric/ftools.hxx> + +namespace drawinglayer::primitive2d +{ +/** PolyPolygonRGBAPrimitive2D class + + This is a simple extension to PolyPolygonColorPrimitive2D + that allows to directly define an alpha value for the PolyPolygon + to be represented, additionally to the color. + + It will be decomposed simply to PolyPolygonColorPrimitive2D, + maybe embedded to a UnifiedTransparencePrimitive2D if + needed, so no changes have to be done to any primitive processor. + + OTOH e.g. SDPR implementations *may* use this directly if they + are capable to draw a filled PolyPoylgon with transparency + directly (e.g. CairoPixelProcessor2D) + */ +class DRAWINGLAYER_DLLPUBLIC PolyPolygonRGBAPrimitive2D final + : public BufferedDecompositionPrimitive2D +{ +private: + /// the tools::PolyPolygon geometry + basegfx::B2DPolyPolygon maPolyPolygon; + + /// the polygon fill color + basegfx::BColor maBColor; + + /// the transparency in range [0.0 .. 1.0] + double mfTransparency; + + /// create local decomposition + virtual Primitive2DReference + create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override; + +public: + /// constructor + PolyPolygonRGBAPrimitive2D(basegfx::B2DPolyPolygon aPolyPolygon, const basegfx::BColor& rBColor, + double fTransparency = 0.0); + + /// data read access + const basegfx::B2DPolyPolygon& getB2DPolyPolygon() const { return maPolyPolygon; } + const basegfx::BColor& getBColor() const { return maBColor; } + double getTransparency() const { return mfTransparency; } + bool hasTransparency() const { return !basegfx::fTools::equalZero(mfTransparency); } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const override; + + /// get B2Drange + virtual basegfx::B2DRange + getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override; + + /// provide unique ID + virtual sal_uInt32 getPrimitive2DID() const override; +}; + +} // end of namespace drawinglayer::primitive2d + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx index ba165bb23db2..fcdee2ec8aed 100644 --- a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx +++ b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx @@ -109,6 +109,7 @@ #define PRIMITIVE2D_ID_SINGLELINEPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 75) #define PRIMITIVE2D_ID_EXCLUSIVEEDITVIEWPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 76) #define PRIMITIVE2D_ID_ANIMATEDGRAPHICPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 77) +#define PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 78) // When you add a new primitive, please update the drawinglayer::primitive2d::idToString() function // in drawinglayer/source/primitive2d/Tools.cxx. diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx index 00d75e5f594c..e17d568bec0c 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -37,6 +37,12 @@ class SingleLinePrimitive2D; class FillGradientPrimitive2D; class PolyPolygonRGBAGradientPrimitive2D; class FillGraphicPrimitive2D; +class PolyPolygonRGBAPrimitive2D; +} + +namespace basegfx +{ +class B2DPolyPolygon; } namespace drawinglayer::processor2d @@ -50,6 +56,8 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub cairo_t* mpRT; // helpers for direct paints + void paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon, + const basegfx::BColor& rColor, double fTransparency = 0.0); void processPolygonHairlinePrimitive2D( const primitive2d::PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D); void processPolyPolygonColorPrimitive2D( @@ -82,6 +90,8 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub const primitive2d::FillGradientPrimitive2D& rFillGradientPrimitive2D); void processFillGraphicPrimitive2D( const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D); + void processPolyPolygonRGBAPrimitive2D( + const primitive2d::PolyPolygonRGBAPrimitive2D& rPolyPolygonRGBAPrimitive2D); /* the local processor for BasePrimitive2D-Implementation based primitives, called from the common process()-implementation diff --git a/svx/qa/unit/table.cxx b/svx/qa/unit/table.cxx index ce48f216026a..26946dac64f9 100644 --- a/svx/qa/unit/table.cxx +++ b/svx/qa/unit/table.cxx @@ -96,9 +96,9 @@ CPPUNIT_TEST_FIXTURE(Test, testTableShadowBlur) assertXPath(pDocument, "//objectinfo/group/sdrCell[1]/unifiedtransparence"_ostr, 0); assertXPath(pDocument, "//objectinfo/group/sdrCell[2]/unifiedtransparence"_ostr, 0); - assertXPath(pDocument, "//objectinfo/group/sdrCell[3]/group/unifiedtransparence"_ostr, + assertXPath(pDocument, "//objectinfo/group/sdrCell[3]/group/polypolygonrgba"_ostr, "transparence"_ostr, u"80"_ustr); - assertXPath(pDocument, "//objectinfo/group/sdrCell[4]/group/unifiedtransparence"_ostr, + assertXPath(pDocument, "//objectinfo/group/sdrCell[4]/group/polypolygonrgba"_ostr, "transparence"_ostr, u"80"_ustr); } diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx index d4ce74d1c025..7f315cb2486a 100644 --- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx +++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx @@ -28,6 +28,7 @@ #include <drawinglayer/primitive2d/softedgeprimitive2d.hxx> #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx> +#include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx> #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> #include <drawinglayer/attribute/strokeattribute.hxx> @@ -447,6 +448,14 @@ sal_uInt32 SlideBackgroundFillPrimitive2D::getPrimitive2DID() const } else { + if(0.0 != rFill.getTransparence()) + { + return new PolyPolygonRGBAPrimitive2D( + rPolyPolygon, + rFill.getColor(), + rFill.getTransparence()); + } + pNewFillPrimitive = new PolyPolygonColorPrimitive2D( rPolyPolygon, rFill.getColor());
