drawinglayer/Library_drawinglayer.mk | 1 drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx | 105 ++++++++++ drawinglayer/source/primitive2d/Tools.cxx | 2 drawinglayer/source/processor2d/cairopixelprocessor2d.cxx | 47 ++++ include/drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx | 82 +++++++ include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx | 1 include/drawinglayer/processor2d/cairopixelprocessor2d.hxx | 7 7 files changed, 241 insertions(+), 4 deletions(-)
New commits: commit 3dcee7e08008588181e69f13e223d3ed4d667dda Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Mon Jul 22 14:39:01 2024 +0200 Commit: Armin Le Grand <[email protected]> CommitDate: Mon Jul 22 20:06:20 2024 +0200 CairoSDPR: Prepare BitmapAlphaPrimitive2D This provides a BitmapPrimitive2D extended by a unified transparency component. It will decompose to a UnifiedTransparencePrimitive2D containing a BitmapPrimitive2D and the transparence, so no primitive processor has to support this primitive directly - but can if feasible. I plan to use that ASAP Change-Id: I83ec84eaadc8ba2b21f0ba0cb1fdcf43bdc455db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170852 Tested-by: Jenkins Reviewed-by: Armin Le Grand <[email protected]> diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk index 18578664cf67..7529c34a43b7 100644 --- a/drawinglayer/Library_drawinglayer.mk +++ b/drawinglayer/Library_drawinglayer.mk @@ -106,6 +106,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/primitive2d/animatedprimitive2d \ drawinglayer/source/primitive2d/backgroundcolorprimitive2d \ drawinglayer/source/primitive2d/bitmapprimitive2d \ + drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D \ drawinglayer/source/primitive2d/borderlineprimitive2d \ drawinglayer/source/primitive2d/BufferedDecompositionGroupPrimitive2D \ drawinglayer/source/primitive2d/controlprimitive2d \ diff --git a/drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx b/drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx new file mode 100644 index 000000000000..8aaca2e5fd15 --- /dev/null +++ b/drawinglayer/source/primitive2d/BitmapAlphaPrimitive2D.cxx @@ -0,0 +1,105 @@ +/* -*- 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/BitmapAlphaPrimitive2D.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> +#include <com/sun/star/awt/XBitmap.hpp> +#include <utility> + +using namespace com::sun::star; + +namespace drawinglayer::primitive2d +{ +Primitive2DReference BitmapAlphaPrimitive2D::create2DDecomposition( + const geometry::ViewInformation2D& /*rViewInformation*/) const +{ + if (basegfx::fTools::equal(getTransparency(), 1.0)) + { + // completely transparent, done + return nullptr; + } + + if (getBitmap().IsEmpty()) + { + // no geometry, done + return nullptr; + } + + if (basegfx::fTools::equalZero(getTransparency())) + { + // no transparency, use simple BitmapPrimitive2D + return Primitive2DReference{ new BitmapPrimitive2D(getBitmap(), getTransform()) }; + } + + // default: embed to UnifiedTransparencePrimitive2D + Primitive2DContainer aContent{ new BitmapPrimitive2D(getBitmap(), getTransform()) }; + return Primitive2DReference{ new UnifiedTransparencePrimitive2D(std::move(aContent), + getTransparency()) }; +} + +BitmapAlphaPrimitive2D::BitmapAlphaPrimitive2D(BitmapEx xXBitmap, basegfx::B2DHomMatrix aTransform, + double fTransparency) + : maBitmap(std::move(xXBitmap)) + , maTransform(std::move(aTransform)) + , mfTransparency(std::max(0.0, std::min(1.0, fTransparency))) +{ +} + +bool BitmapAlphaPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const +{ + if (BasePrimitive2D::operator==(rPrimitive)) + { + const BitmapAlphaPrimitive2D& rCompare + = static_cast<const BitmapAlphaPrimitive2D&>(rPrimitive); + + return (getBitmap() == rCompare.getBitmap() && getTransform() == rCompare.getTransform() + && basegfx::fTools::equal(getTransparency(), rCompare.getTransparency())); + } + + return false; +} + +basegfx::B2DRange +BitmapAlphaPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const +{ + basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0); + aRetval.transform(maTransform); + return aRetval; +} + +sal_Int64 BitmapAlphaPrimitive2D::estimateUsage() +{ + if (getBitmap().IsEmpty()) + { + return 0; + } + return getBitmap().GetSizeBytes(); +} + +// provide unique ID +sal_uInt32 BitmapAlphaPrimitive2D::getPrimitive2DID() const +{ + return PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D; +} + +} // 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 bd0011ab4625..2a4314c70ec4 100644 --- a/drawinglayer/source/primitive2d/Tools.cxx +++ b/drawinglayer/source/primitive2d/Tools.cxx @@ -237,6 +237,8 @@ OUString idToString(sal_uInt32 nId) return u"ANIMATEDGRAPHICPRIMITIVE2D"_ustr; case PRIMITIVE2D_ID_POLYPOLYGONRGBAPRIMITIVE2D: return u"POLYPOLYGONRGBAPRIMITIVE2D"_ustr; + case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D: + return u"BITMAPALPHAPRIMITIVE2D"_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 24695b0b0a8a..715fc8ce302c 100644 --- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx @@ -38,6 +38,7 @@ #include <drawinglayer/primitive2d/invertprimitive2d.hxx> #include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx> #include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx> +#include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx> #include <drawinglayer/converters.hxx> #include <basegfx/curve/b2dcubicbezier.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> @@ -826,10 +827,23 @@ CairoPixelProcessor2D::~CairoPixelProcessor2D() void CairoPixelProcessor2D::processBitmapPrimitive2D( const primitive2d::BitmapPrimitive2D& rBitmapCandidate) { + paintBitmapAlpha(rBitmapCandidate.getBitmap(), rBitmapCandidate.getTransform()); +} + +void CairoPixelProcessor2D::paintBitmapAlpha(const BitmapEx& rBitmapEx, + const basegfx::B2DHomMatrix& rTransform, + double fTransparency) +{ + // transparency invalid or completely transparent, done + if (fTransparency < 0.0 || fTransparency >= 1.0) + { + return; + } + // check if graphic content is inside discrete local ViewPort const basegfx::B2DRange& rDiscreteViewPort(getViewInformation2D().getDiscreteViewport()); const basegfx::B2DHomMatrix aLocalTransform( - getViewInformation2D().getObjectToViewTransformation() * rBitmapCandidate.getTransform()); + getViewInformation2D().getObjectToViewTransformation() * rTransform); if (!rDiscreteViewPort.isEmpty()) { @@ -844,7 +858,7 @@ void CairoPixelProcessor2D::processBitmapPrimitive2D( } } - BitmapEx aBitmapEx(rBitmapCandidate.getBitmap()); + BitmapEx aBitmapEx(rBitmapEx); if (aBitmapEx.IsEmpty() || aBitmapEx.GetSizePixel().IsEmpty()) { @@ -966,8 +980,11 @@ void CairoPixelProcessor2D::processBitmapPrimitive2D( cairo_pattern_set_matrix(sourcepattern, &aMatrix); - // paint bitmap data - cairo_paint(mpRT); + // paint bitmap data, evtl. with additional alpha channel + if (!basegfx::fTools::equalZero(fTransparency)) + cairo_paint_with_alpha(mpRT, 1.0 - fTransparency); + else + cairo_paint(mpRT); cairo_restore(mpRT); } @@ -2717,6 +2734,22 @@ void CairoPixelProcessor2D::processPolyPolygonRGBAPrimitive2D( rPolyPolygonRGBAPrimitive2D.getTransparency()); } +void CairoPixelProcessor2D::processBitmapAlphaPrimitive2D( + const primitive2d::BitmapAlphaPrimitive2D& rBitmapAlphaPrimitive2D) +{ + if (!rBitmapAlphaPrimitive2D.hasTransparency()) + { + // do what CairoPixelProcessor2D::processPolyPolygonColorPrimitive2D does + paintBitmapAlpha(rBitmapAlphaPrimitive2D.getBitmap(), + rBitmapAlphaPrimitive2D.getTransform()); + return; + } + + // draw wiath alpha directly + paintBitmapAlpha(rBitmapAlphaPrimitive2D.getBitmap(), rBitmapAlphaPrimitive2D.getTransform(), + rBitmapAlphaPrimitive2D.getTransparency()); +} + void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch (rCandidate.getPrimitive2DID()) @@ -2839,6 +2872,12 @@ void CairoPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimit static_cast<const primitive2d::PolyPolygonRGBAPrimitive2D&>(rCandidate)); break; } + case PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D: + { + processBitmapAlphaPrimitive2D( + static_cast<const primitive2d::BitmapAlphaPrimitive2D&>(rCandidate)); + break; + } // continue with decompose default: diff --git a/include/drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx b/include/drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx new file mode 100644 index 000000000000..105eb4c516c4 --- /dev/null +++ b/include/drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx @@ -0,0 +1,82 @@ +/* -*- 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/matrix/b2dhommatrix.hxx> +#include <vcl/bitmapex.hxx> + +namespace drawinglayer::primitive2d +{ +/** BitmapAlphaPrimitive2D class + + This class is a BitmapPrimitive2D extended by a unified transparency + aspect. It will decompose to a UnifiedTransparencePrimitive2D containing + a BitmapPrimitive2D and the transparence, so no primitive processor + has to support this primitive directly - but can if feasible. + */ +class DRAWINGLAYER_DLLPUBLIC BitmapAlphaPrimitive2D final : public BufferedDecompositionPrimitive2D +{ +private: + /// the Bitmap-data + BitmapEx maBitmap; + + /** the object transformation from unit coordinates, defining + size, shear, rotate and position + */ + basegfx::B2DHomMatrix maTransform; + + /// the transparency in range [0.0 .. 1.0] + double mfTransparency; + + /// create local decomposition + virtual Primitive2DReference + create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override; + +public: + /// constructor + BitmapAlphaPrimitive2D(BitmapEx xBitmap, basegfx::B2DHomMatrix aTransform, + double fTransparency = 0.0); + + /// data read access + const BitmapEx& getBitmap() const { return maBitmap; } + const basegfx::B2DHomMatrix& getTransform() const { return maTransform; } + double getTransparency() const { return mfTransparency; } + bool hasTransparency() const { return !basegfx::fTools::equalZero(mfTransparency); } + + /// compare operator + virtual bool operator==(const BasePrimitive2D& rPrimitive) const override; + + /// get range + virtual basegfx::B2DRange + getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override; + + // XAccounting + virtual sal_Int64 estimateUsage() 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 fcdee2ec8aed..8f86167dc5f7 100644 --- a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx +++ b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx @@ -110,6 +110,7 @@ #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) +#define PRIMITIVE2D_ID_BITMAPALPHAPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 79) // 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 e17d568bec0c..129daaef86fa 100644 --- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx +++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx @@ -38,6 +38,7 @@ class FillGradientPrimitive2D; class PolyPolygonRGBAGradientPrimitive2D; class FillGraphicPrimitive2D; class PolyPolygonRGBAPrimitive2D; +class BitmapAlphaPrimitive2D; } namespace basegfx @@ -45,6 +46,8 @@ namespace basegfx class B2DPolyPolygon; } +class BitmapEx; + namespace drawinglayer::processor2d { class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : public BaseProcessor2D @@ -92,6 +95,10 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) CairoPixelProcessor2D final : pub const primitive2d::FillGraphicPrimitive2D& rFillGraphicPrimitive2D); void processPolyPolygonRGBAPrimitive2D( const primitive2d::PolyPolygonRGBAPrimitive2D& rPolyPolygonRGBAPrimitive2D); + void paintBitmapAlpha(const BitmapEx& rBitmapEx, const basegfx::B2DHomMatrix& rTransform, + double fTransparency = 0.0); + void processBitmapAlphaPrimitive2D( + const primitive2d::BitmapAlphaPrimitive2D& rBitmapAlphaPrimitive2D); /* the local processor for BasePrimitive2D-Implementation based primitives, called from the common process()-implementation
