diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /include/basegfx/utils | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/basegfx/utils')
-rw-r--r-- | include/basegfx/utils/b2dclipstate.hxx | 92 | ||||
-rw-r--r-- | include/basegfx/utils/bgradient.hxx | 329 | ||||
-rw-r--r-- | include/basegfx/utils/canvastools.hxx | 167 | ||||
-rw-r--r-- | include/basegfx/utils/common.hxx | 33 | ||||
-rw-r--r-- | include/basegfx/utils/gradienttools.hxx | 526 | ||||
-rw-r--r-- | include/basegfx/utils/keystoplerp.hxx | 85 | ||||
-rw-r--r-- | include/basegfx/utils/lerp.hxx | 43 | ||||
-rw-r--r-- | include/basegfx/utils/rectcliptools.hxx | 72 | ||||
-rw-r--r-- | include/basegfx/utils/systemdependentdata.hxx | 111 | ||||
-rw-r--r-- | include/basegfx/utils/tools.hxx | 124 | ||||
-rw-r--r-- | include/basegfx/utils/unopolypolygon.hxx | 104 | ||||
-rw-r--r-- | include/basegfx/utils/zoomtools.hxx | 22 |
12 files changed, 1708 insertions, 0 deletions
diff --git a/include/basegfx/utils/b2dclipstate.hxx b/include/basegfx/utils/b2dclipstate.hxx new file mode 100644 index 0000000000..f4d9d9e7d6 --- /dev/null +++ b/include/basegfx/utils/b2dclipstate.hxx @@ -0,0 +1,92 @@ +/* -*- 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 <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + class B2DRange; + class B2DPolyPolygon; + class B2DHomMatrix; +} + +namespace basegfx::utils +{ + class ImplB2DClipState; + + /** This class provides an optimized, symbolic clip state for graphical output + + Having a current 'clip' state is a common attribute of + almost all graphic output APIs, most of which internally + represent it via a list of rectangular bands. In contrast, + this implementation purely uses symbolic clips, but in a + quite efficient manner, deferring actual evaluation until + a clip representation is requested, and using faster code + paths for common special cases (like all-rectangle clips) + */ + class BASEGFX_DLLPUBLIC B2DClipState + { + public: + typedef o3tl::cow_wrapper< ImplB2DClipState > ImplType; + + private: + ImplType mpImpl; + + public: + /// Init clip, in 'cleared' state - everything is visible + B2DClipState(); + ~B2DClipState(); + B2DClipState( const B2DClipState& ); + B2DClipState( B2DClipState&& ); + explicit B2DClipState( const B2DPolyPolygon& ); + B2DClipState& operator=( const B2DClipState& ); + B2DClipState& operator=( B2DClipState&& ); + + /// Set clip to 'null' - nothing is visible + void makeNull(); + + /// returns true when clip is 'cleared' - everything is visible + bool isCleared() const; + + bool operator==(const B2DClipState&) const; + bool operator!=(const B2DClipState&) const; + + void unionRange(const B2DRange& ); + void unionPolyPolygon(const B2DPolyPolygon& ); + + void intersectRange(const B2DRange& ); + void intersectPolyPolygon(const B2DPolyPolygon& ); + + void subtractRange(const B2DRange& ); + void subtractPolyPolygon(const B2DPolyPolygon& ); + + void xorRange(const B2DRange& ); + void xorPolyPolygon(const B2DPolyPolygon& ); + + void transform(const B2DHomMatrix& ); + + B2DPolyPolygon const & getClipPoly() const; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/bgradient.hxx b/include/basegfx/utils/bgradient.hxx new file mode 100644 index 0000000000..7d360beee4 --- /dev/null +++ b/include/basegfx/utils/bgradient.hxx @@ -0,0 +1,329 @@ +/* -*- 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/. + */ + +#pragma once + +#include <basegfx/color/bcolor.hxx> +#include <basegfx/basegfxdllapi.h> +#include <vector> +#include <com/sun/star/awt/GradientStyle.hpp> +#include <tools/degree.hxx> +#include <boost/property_tree/ptree_fwd.hpp> + +namespace basegfx +{ +/* MCGR: Provide ColorStop definition + + This is the needed combination of offset and color: + + Offset is defined as: + - being in the range of [0.0 .. 1.0] (unit range) + - offsets outside are an error + - lowest/1st value equivalent to StartColor + - highest/last value equivalent to EndColor + - missing 0.0/1.0 entries are allowed + - at least one value (usually 0.0, StartColor) is required + - this allows to avoid massive testing in all places where + this data has to be accessed + + Color is defined as: + - RGB with unit values [0.0 .. 1.0] + + These definitions are packed in a std::vector<ColorStop> ColorStops, + see typedef below. + */ +class BASEGFX_DLLPUBLIC BColorStop +{ +private: + // offset in the range of [0.0 .. 1.0] + double mfStopOffset; + + // RGB color of ColorStop entry + BColor maStopColor; + +public: + // constructor - defaults are needed to have a default constructor + // e.g. for usage in std::vector::insert (even when only reducing) + // ensure [0.0 .. 1.0] range for mfStopOffset + BColorStop(double fStopOffset = 0.0, const BColor& rStopColor = BColor()) + : mfStopOffset(fStopOffset) + , maStopColor(rStopColor) + { + // NOTE: I originally *corrected* mfStopOffset here by using + // mfStopOffset(std::max(0.0, std::min(fOffset, 1.0))) + // While that is formally correct, it moves an invalid + // entry to 0.0 or 1.0, thus creating additional wrong + // Start/EndColor entries. That may then 'overlay' the + // correct entry when corrections are applied to the + // vector of entries (see sortAndCorrectColorStops) + // which leads to getting the wanted Start/EndColor + // to be factically deleted, what is an error. + } + + double getStopOffset() const { return mfStopOffset; } + const BColor& getStopColor() const { return maStopColor; } + + // needed for std::sort + bool operator<(const BColorStop& rCandidate) const + { + return getStopOffset() < rCandidate.getStopOffset(); + } + + bool operator==(const BColorStop& rCandidate) const + { + return getStopOffset() == rCandidate.getStopOffset() + && getStopColor() == rCandidate.getStopColor(); + } + + bool operator!=(const BColorStop& rCandidate) const { return !(*this == rCandidate); } +}; + +/* MCGR: Provide ColorStops definition to the FillGradientAttribute + + This array should be sorted ascending by offsets, from lowest to + highest. Since all the primitive data definition where it is used + is read-only, this can/will be guaranteed by forcing/checking this + in the constructor, see ::FillGradientAttribute + */ +class BASEGFX_DLLPUBLIC BColorStops final : public std::vector<BColorStop> +{ +public: + explicit BColorStops() + : vector() + { + } + BColorStops(const BColorStops& other) + : vector(other) + { + } + BColorStops(BColorStops&& other) noexcept + : vector(std::move(other)) + { + } + BColorStops(std::initializer_list<BColorStop> init) + : vector(init) + { + } + BColorStops(const_iterator first, const_iterator last) + : vector(first, last) + { + } + + // constructor with two colors to explicitly create a + // BColorStops for StartColor @0.0 & EndColor @1.0 + BColorStops(const BColor& rStart, const BColor& rEnd); + + BColorStops& operator=(const BColorStops& r) + { + vector::operator=(r); + return *this; + } + BColorStops& operator=(BColorStops&& r) noexcept + { + vector::operator=(std::move(r)); + return *this; + } + + // helper data struct to support buffering entries in + // gradient texture mapping, see usages for more info + struct BColorStopRange + { + basegfx::BColor maColorStart; + basegfx::BColor maColorEnd; + double mfOffsetStart; + double mfOffsetEnd; + + BColorStopRange() + : maColorStart() + , maColorEnd() + , mfOffsetStart(0.0) + , mfOffsetEnd(0.0) + { + } + }; + + /* Helper to grep the correct ColorStop out of + ColorStops and interpolate as needed for given + relative value in fPosition in the range of [0.0 .. 1.0]. + It also takes care of evtl. given RequestedSteps. + */ + BColor getInterpolatedBColor(double fPosition, sal_uInt32 nRequestedSteps, + BColorStopRange& rLastColorStopRange) const; + + /* Tooling method that allows to replace the StartColor in a + vector of ColorStops. A vector in 'ordered state' is expected, + so you may use/have used sortAndCorrect. + This method is for convenience & backwards compatibility, please + think about handling multi-colored gradients directly. + */ + void replaceStartColor(const BColor& rStart); + + /* Tooling method that allows to replace the EndColor in a + vector of ColorStops. A vector in 'ordered state' is expected, + so you may use/have used sortAndCorrect. + This method is for convenience & backwards compatibility, please + think about handling multi-colored gradients directly. + */ + void replaceEndColor(const BColor& rEnd); + + /* Tooling method to linearly blend the Colors contained in + a given ColorStop vector against a given Color using the + given intensity values. + The intensity values fStartIntensity, fEndIntensity are + in the range of [0.0 .. 1.0] and describe how much the + blend is supposed to be done at the start color position + and the end color position respectively, where 0.0 means + to fully use the given BlendColor, 1.0 means to not change + the existing color in the ColorStop. + Every color entry in the given ColorStop is blended + relative to it's StopPosition, interpolating the + given intensities with the range [0.0 .. 1.0] to do so. + */ + void blendToIntensity(double fStartIntensity, double fEndIntensity, const BColor& rBlendColor); + + /* Tooling method to guarantee sort and correctness for + the given ColorStops vector. + A vector fulfilling these conditions is called to be + in 'ordered state'. + + At return, the following conditions are guaranteed: + - contains no ColorStops with offset < 0.0 (will + be removed) + - contains no ColorStops with offset > 1.0 (will + be removed) + - ColorStops with identical offsets are now allowed + - will be sorted from lowest offset to highest + + Some more notes: + - It can happen that the result is empty + - It is allowed to have consecutive entries with + the same color, this represents single-color + regions inside the gradient + - A entry with 0.0 is not required or forced, so + no 'StartColor' is technically required + - A entry with 1.0 is not required or forced, so + no 'EndColor' is technically required + + All this is done in one run (sort + O(N)) without + creating a copy of the data in any form + */ + void sortAndCorrect(); + + // check if we need last-ColorStop-correction. This returns true if the last + // two ColorStops have the same offset but different Colors. In that case the + // tessellation for gradients does have to create an extra ending/closing entry + bool checkPenultimate() const; + + /* Tooling method to check if a ColorStop vector is defined + by a single color. It returns true if this is the case. + If true is returned, rSingleColor contains that single + color for convenience. + NOTE: If no ColorStop is defined, a fallback to BColor-default + (which is black) and true will be returned + */ + bool isSingleColor(BColor& rSingleColor) const; + + /* Tooling method to reverse ColorStops, including offsets. + When also mirroring offsets a valid sort keeps valid. + */ + void reverseColorStops(); + + // createSpaceAtStart creates fOffset space at start by + // translating/scaling all entries to the right + void createSpaceAtStart(double fOffset); + + // removeSpaceAtStart removes fOffset space from start by + // translating/scaling entries more or equal to fOffset + // to the left. Entries less than fOffset will be removed + void removeSpaceAtStart(double fOffset); + + // try to detect if an empty/no-color-change area exists + // at the start and return offset to it. Returns 0.0 if not. + double detectPossibleOffsetAtStart() const; + + // returns true if the color stops are symmetrical in color and offset, otherwise false. + bool isSymmetrical() const; + // assume that the color stops represent an Axial gradient + // and replace with gradient stops to represent the same + // gradient as linear gradient + void doApplyAxial(); + + // apply Steps as 'hard' color stops + void doApplySteps(sal_uInt16 nStepCount); +}; + +class BASEGFX_DLLPUBLIC BGradient final +{ +private: + css::awt::GradientStyle eStyle; + + // MCGS: ColorStops in the range [0.0 .. 1.0], including StartColor/EndColor + basegfx::BColorStops aColorStops; + + Degree10 nAngle; + sal_uInt16 nBorder; + sal_uInt16 nOfsX; + sal_uInt16 nOfsY; + sal_uInt16 nIntensStart; + sal_uInt16 nIntensEnd; + sal_uInt16 nStepCount; + + static std::string GradientStyleToString(css::awt::GradientStyle eStyle); + +public: + BGradient(); + BGradient(const basegfx::BColorStops& rColorStops, + css::awt::GradientStyle eStyle = css::awt::GradientStyle_LINEAR, + Degree10 nAngle = 0_deg10, sal_uInt16 nXOfs = 50, sal_uInt16 nYOfs = 50, + sal_uInt16 nBorder = 0, sal_uInt16 nStartIntens = 100, sal_uInt16 nEndIntens = 100, + sal_uInt16 nSteps = 0); + + bool operator==(const BGradient& rGradient) const; + + void SetGradientStyle(css::awt::GradientStyle eNewStyle) { eStyle = eNewStyle; } + void SetColorStops(const basegfx::BColorStops& rSteps); + void SetAngle(Degree10 nNewAngle) { nAngle = nNewAngle; } + void SetBorder(sal_uInt16 nNewBorder) { nBorder = nNewBorder; } + void SetXOffset(sal_uInt16 nNewOffset) { nOfsX = nNewOffset; } + void SetYOffset(sal_uInt16 nNewOffset) { nOfsY = nNewOffset; } + void SetStartIntens(sal_uInt16 nNewIntens) { nIntensStart = nNewIntens; } + void SetEndIntens(sal_uInt16 nNewIntens) { nIntensEnd = nNewIntens; } + void SetSteps(sal_uInt16 nSteps) { nStepCount = nSteps; } + + css::awt::GradientStyle GetGradientStyle() const { return eStyle; } + const basegfx::BColorStops& GetColorStops() const { return aColorStops; } + Degree10 GetAngle() const { return nAngle; } + sal_uInt16 GetBorder() const { return nBorder; } + sal_uInt16 GetXOffset() const { return nOfsX; } + sal_uInt16 GetYOffset() const { return nOfsY; } + sal_uInt16 GetStartIntens() const { return nIntensStart; } + sal_uInt16 GetEndIntens() const { return nIntensEnd; } + sal_uInt16 GetSteps() const { return nStepCount; } + + boost::property_tree::ptree dumpAsJSON() const; + static BGradient fromJSON(std::u16string_view rJSON); + + // Tooling to handle + // - border correction/integration + // - apply StartStopIntensity to color stops + // - convert type from 'axial' to linear + // - apply Steps as 'hard' color stops + void tryToRecreateBorder(basegfx::BColorStops* pAssociatedTransparencyStops = nullptr); + void tryToApplyBorder(); + void tryToApplyStartEndIntensity(); + + // If a linear gradient is symmetrical it is converted to an axial gradient. + // Does nothing in other cases and for other gradient types. + void tryToConvertToAxial(); + void tryToApplyAxial(); + void tryToApplySteps(); +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/canvastools.hxx b/include/basegfx/utils/canvastools.hxx new file mode 100644 index 0000000000..4646609772 --- /dev/null +++ b/include/basegfx/utils/canvastools.hxx @@ -0,0 +1,167 @@ +/* -*- 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 <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace com::sun::star::geometry +{ + struct AffineMatrix2D; + struct AffineMatrix3D; + struct RealPoint2D; + struct RealSize2D; + struct RealRectangle2D; + struct RealRectangle3D; + struct IntegerSize2D; + struct IntegerRectangle2D; + struct RealBezierSegment2D; +} + +namespace com::sun::star::rendering +{ + class XGraphicDevice; + class XPolyPolygon2D; +} + +namespace com::sun::star::awt +{ + struct Rectangle; +} + +namespace basegfx +{ + class B2DHomMatrix; + class B3DHomMatrix; + class B2DVector; + class B2DPoint; + class B2DRange; + class B3DRange; + class B2IVector; + class B2IRange; + class B2DPolygon; + class B2DPolyPolygon; + class B2DSize; + class B2ISize; +} + +namespace basegfx::unotools +{ + // Polygon conversions + + + BASEGFX_DLLPUBLIC css::uno::Reference< css::rendering::XPolyPolygon2D > + xPolyPolygonFromB2DPolygon( const css::uno::Reference< css::rendering::XGraphicDevice >& xGraphicDevice, + const ::basegfx::B2DPolygon& rPoly ); + + BASEGFX_DLLPUBLIC css::uno::Reference< css::rendering::XPolyPolygon2D > + xPolyPolygonFromB2DPolyPolygon( const css::uno::Reference< css::rendering::XGraphicDevice >& xGraphicDevice, + const ::basegfx::B2DPolyPolygon& rPolyPoly ); + + + css::uno::Sequence< + css::uno::Sequence< css::geometry::RealBezierSegment2D > > + bezierSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ); + + css::uno::Sequence< + css::uno::Sequence< css::geometry::RealPoint2D > > + pointSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ); + + ::basegfx::B2DPolygon polygonFromPoint2DSequence( + const css::uno::Sequence< css::geometry::RealPoint2D >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolyPolygon polyPolygonFromPoint2DSequenceSequence( + const css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > >& rPoints ); + + ::basegfx::B2DPolygon polygonFromBezier2DSequence( + const css::uno::Sequence< css::geometry::RealBezierSegment2D >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolyPolygon polyPolygonFromBezier2DSequenceSequence( + const css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolyPolygon b2DPolyPolygonFromXPolyPolygon2D( + const css::uno::Reference< css::rendering::XPolyPolygon2D >& rPoly ); + + // Matrix conversions + + + BASEGFX_DLLPUBLIC css::geometry::AffineMatrix2D& + affineMatrixFromHomMatrix( css::geometry::AffineMatrix2D& matrix, + const ::basegfx::B2DHomMatrix& transform); + + css::geometry::AffineMatrix3D& affineMatrixFromHomMatrix3D( + css::geometry::AffineMatrix3D& matrix, + const ::basegfx::B3DHomMatrix& transform); + + BASEGFX_DLLPUBLIC ::basegfx::B2DHomMatrix& + homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix& transform, + const css::geometry::AffineMatrix2D& matrix ); + + BASEGFX_DLLPUBLIC ::basegfx::B3DHomMatrix homMatrixFromAffineMatrix3D( const css::geometry::AffineMatrix3D& matrix ); + + // Geometry conversions + + + BASEGFX_DLLPUBLIC css::geometry::RealSize2D size2DFromB2DSize( const ::basegfx::B2DSize& ); + BASEGFX_DLLPUBLIC css::geometry::RealPoint2D point2DFromB2DPoint( const ::basegfx::B2DPoint& ); + BASEGFX_DLLPUBLIC css::geometry::RealRectangle2D rectangle2DFromB2DRectangle( const ::basegfx::B2DRange& ); + BASEGFX_DLLPUBLIC css::geometry::RealRectangle3D rectangle3DFromB3DRectangle( const ::basegfx::B3DRange& ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPoint b2DPointFromRealPoint2D( const css::geometry::RealPoint2D& ); + BASEGFX_DLLPUBLIC ::basegfx::B2DRange b2DRectangleFromRealRectangle2D( const css::geometry::RealRectangle2D& ); + ::basegfx::B3DRange b3DRectangleFromRealRectangle3D( const css::geometry::RealRectangle3D& ); + + BASEGFX_DLLPUBLIC css::geometry::IntegerSize2D integerSize2DFromB2ISize(basegfx::B2ISize const& rSize); + + BASEGFX_DLLPUBLIC ::basegfx::B2ISize b2ISizeFromIntegerSize2D( const css::geometry::IntegerSize2D& ); + BASEGFX_DLLPUBLIC ::basegfx::B2IRange b2IRectangleFromIntegerRectangle2D( const css::geometry::IntegerRectangle2D& ); + + BASEGFX_DLLPUBLIC ::basegfx::B2IRange b2IRectangleFromAwtRectangle( const css::awt::Rectangle& ); + + // Geometry comparisons + + + /** Return smalltest integer range, which completely contains + given floating point range. + + @param rRange + Input range. Values must be within the representable + bounds of sal_Int32 + + @return the closest integer range, which completely + contains rRange. + */ + BASEGFX_DLLPUBLIC ::basegfx::B2IRange b2ISurroundingRangeFromB2DRange( const ::basegfx::B2DRange& rRange ); + + /** Return smalltest B2DRange with integer values, which + completely contains given floating point range. + + @param rRange + Input range. + + @return the closest B2DRange with integer coordinates, + which completely contains rRange. + */ + BASEGFX_DLLPUBLIC ::basegfx::B2DRange b2DSurroundingIntegerRangeFromB2DRange( const ::basegfx::B2DRange& rRange ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/common.hxx b/include/basegfx/utils/common.hxx new file mode 100644 index 0000000000..1c11a8bf23 --- /dev/null +++ b/include/basegfx/utils/common.hxx @@ -0,0 +1,33 @@ +/* -*- 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 + +namespace basegfx +{ +// The axis or dimension in a 2D coordinate system +enum class Axis2D +{ + X, + Y +}; + +} // end of namespace basegfx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/gradienttools.hxx b/include/basegfx/utils/gradienttools.hxx new file mode 100644 index 0000000000..d56e73b90d --- /dev/null +++ b/include/basegfx/utils/gradienttools.hxx @@ -0,0 +1,526 @@ +/* -*- 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 <config_options.h> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/color/bcolor.hxx> +#include <utility> +#include <basegfx/basegfxdllapi.h> +#include <basegfx/utils/bgradient.hxx> +#include <osl/endian.h> + +namespace basegfx { class B2DRange; } + +namespace +{ + /* Internal helper to convert ::Color from tools::color.hxx to BColor + without the need to link against tools library. Be on the + safe side by using the same union + */ + struct ColorToBColorConverter + { + union { + sal_uInt32 mValue; + struct { +#ifdef OSL_BIGENDIAN + sal_uInt8 T; + sal_uInt8 R; + sal_uInt8 G; + sal_uInt8 B; +#else + sal_uInt8 B; + sal_uInt8 G; + sal_uInt8 R; + sal_uInt8 T; +#endif + }; + }; + + ColorToBColorConverter GetRGBColor() const + { + return {R, G, B}; + } + + ColorToBColorConverter(sal_uInt32 nColor) + : mValue(nColor) + { T=0; } + + constexpr ColorToBColorConverter(sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue) + : mValue(sal_uInt32(nBlue) | (sal_uInt32(nGreen) << 8) | (sal_uInt32(nRed) << 16)) + {} + + explicit ColorToBColorConverter(const basegfx::BColor& rBColor) + : ColorToBColorConverter( + sal_uInt8(std::lround(rBColor.getRed() * 255.0)), + sal_uInt8(std::lround(rBColor.getGreen() * 255.0)), + sal_uInt8(std::lround(rBColor.getBlue() * 255.0))) + {} + + basegfx::BColor getBColor() const + { + return basegfx::BColor(R / 255.0, G / 255.0, B / 255.0); + } + + constexpr explicit operator sal_Int32() const + { + return sal_Int32(mValue); + } + + constexpr explicit operator sal_uInt32() const + { + return mValue; + } + }; +} + +namespace basegfx +{ + /** Gradient definition as used in ODF 1.2 + + This struct collects all data necessary for rendering ODF + 1.2-compatible gradients. Use the createXXXODFGradientInfo() + methods below for initializing from ODF attributes. + */ + class UNLESS_MERGELIBS(BASEGFX_DLLPUBLIC) ODFGradientInfo + { + private: + /** transformation mapping from [0,1]^2 texture coordinate + space to [0,1]^2 shape coordinate space + */ + B2DHomMatrix maTextureTransform; + + /** transformation mapping from [0,1]^2 shape coordinate space + to [0,1]^2 texture coordinate space. This is the + transformation commonly used to create gradients from a + scanline rasterizer (put shape u/v coordinates into it, get + texture s/t coordinates out of it) + */ + B2DHomMatrix maBackTextureTransform; + + /** Aspect ratio of the gradient. Only used in drawinglayer + for generating nested gradient polygons currently. Already + catered for in the transformations above. + */ + double mfAspectRatio; + + /** Requested gradient steps to render. See the + implementations of the getXXXGradientAlpha() methods below, + the semantic differs slightly for the different gradient + types. + */ + sal_uInt32 mnRequestedSteps; + + public: + ODFGradientInfo() + : mfAspectRatio(1.0), + mnRequestedSteps(0) + { + } + + ODFGradientInfo( + B2DHomMatrix aTextureTransform, + double fAspectRatio, + sal_uInt32 nRequestedSteps) + : maTextureTransform(std::move(aTextureTransform)), + mfAspectRatio(fAspectRatio), + mnRequestedSteps(nRequestedSteps) + { + } + + ODFGradientInfo(const ODFGradientInfo& rODFGradientInfo) + : maTextureTransform(rODFGradientInfo.getTextureTransform()), + maBackTextureTransform(rODFGradientInfo.maBackTextureTransform), + mfAspectRatio(rODFGradientInfo.getAspectRatio()), + mnRequestedSteps(rODFGradientInfo.getRequestedSteps()) + { + } + + ODFGradientInfo& operator=(const ODFGradientInfo& rODFGradientInfo) + { + maTextureTransform = rODFGradientInfo.getTextureTransform(); + maBackTextureTransform = rODFGradientInfo.maBackTextureTransform; + mfAspectRatio = rODFGradientInfo.getAspectRatio(); + mnRequestedSteps = rODFGradientInfo.getRequestedSteps(); + + return *this; + } + + // compare operator + bool operator==(const ODFGradientInfo& rGeoTexSvx) const; + + const B2DHomMatrix& getTextureTransform() const { return maTextureTransform; } + const B2DHomMatrix& getBackTextureTransform() const; + double getAspectRatio() const { return mfAspectRatio; } + sal_uInt32 getRequestedSteps() const { return mnRequestedSteps; } + + void setTextureTransform(const B2DHomMatrix& rNew) + { + maTextureTransform = rNew; + maBackTextureTransform.identity(); + } + }; + + namespace utils + { + /* Tooling method to extract data from given BGradient + to ColorStops, doing some corrections, partially based + on given SingleColor. + This is used for export preparations in case these exports + do neither support Start/EndIntensity nor Border settings, + both will be eliminated if possible (see below). + The BGradient rGradient and BColorStops& rColorStops + are both return parameters and may be changed. + This will do quite some preparations for the gradient + as follows: + - It will check for single color (resetting rSingleColor when + this is the case) and return with empty ColorStops + - It will blend ColorStops to Intensity if StartIntensity/ + EndIntensity != 100 is set in BGradient, so applying + that value(s) to the gradient directly + - It will adapt to Border if Border != 0 is set at the + given BGradient, so applying that value to the gradient + directly + */ + BASEGFX_DLLPUBLIC void prepareColorStops( + const basegfx::BGradient& rGradient, + BColorStops& rColorStops, + BColor& rSingleColor); + + /* Tooling method to synchronize the given ColorStops. + The intention is that a color GradientStops and an + alpha/transparence GradientStops gets synchronized + for export. + For the corrections the single values for color and + alpha may be used, e.g. when ColorStops is given + and not empty, but AlphaStops is empty, it will get + synchronized so that it will have the same number and + offsets in AlphaStops as in ColorStops, but with + the given SingleAlpha as value. + At return it guarantees that both have the same + number of entries with the same StopOffsets, so + that synchronized pair of ColorStops can e.g. be used + to export a Gradient with defined/adapted alpha + being 'coupled' indirectly using the + 'FillTransparenceGradient' method (at import time). + */ + BASEGFX_DLLPUBLIC void synchronizeColorStops( + BColorStops& rColorStops, + BColorStops& rAlphaStops, + const BColor& rSingleColor, + const BColor& rSingleAlpha); + + /* Helper to calculate numberOfSteps needed to represent + gradient for the given two colors: + - to define only based on color distance, give 0 == nRequestedSteps + as wanted value, so color distance will be used + - if a wanted value of nRequestedSteps is given, it gets synched + against the maximum number of steps defined by the color + distance of the two colors + - a minimum result of 1 is returned which means a single + step -> no real gradient + */ + BASEGFX_DLLPUBLIC sal_uInt32 calculateNumberOfSteps( + sal_uInt32 nRequestedSteps, + const BColor& rStart, + const BColor& rEnd); + + /** Create matrix for ODF's linear gradient definition + + Note that odf linear gradients are varying in y direction. + + @param o_rGradientInfo + Receives the calculated texture transformation matrix (for + use with standard [0,1]x[0,1] texture coordinates) + + @param rTargetArea + Output area, needed for aspect ratio calculations and + texture transformation + + @param nRequestedSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo createLinearODFGradientInfo( + const B2DRange& rTargetArea, + sal_uInt32 nRequestedSteps, + double fBorder, + double fAngle); + + + /** Calculate linear gradient blend value + + This method generates you the lerp alpha value for + blending linearly between gradient start and end color, + according to the formula (startCol*(1.0-alpha) + endCol*alpha) + + @param rUV + Current uv coordinate. Values outside [0,1] will be + clamped. Assumes gradient color varies along the y axis. + + @param rGradInfo + Gradient info, for transformation and number of steps + */ + BASEGFX_DLLPUBLIC double getLinearGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo); + + /** Create matrix for ODF's axial gradient definition + + Note that odf axial gradients are varying in y + direction. Note further that you can map the axial + gradient to a linear gradient (in case you want or need to + avoid an extra gradient renderer), by using + createLinearODFGradientInfo() instead, shifting the + resulting texture transformation by 0.5 to the top and + appending the same stop colors again, but mirrored. + + @param o_rGradientInfo + Receives the calculated texture transformation matrix (for + use with standard [0,1]x[0,1] texture coordinates) + + @param rTargetArea + Output area, needed for aspect ratio calculations and + texture transformation + + @param nRequestedSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo createAxialODFGradientInfo( + const B2DRange& rTargetArea, + sal_uInt32 nRequestedSteps, + double fBorder, + double fAngle); + + + /** Calculate axial gradient blend value + + This method generates you the lerp alpha value for + blending linearly between gradient start and end color, + according to the formula (startCol*(1.0-alpha) + endCol*alpha) + + @param rUV + Current uv coordinate. Values outside [0,1] will be + clamped. Assumes gradient color varies along the y axis. + + @param rGradInfo + Gradient info, for transformation and number of steps + */ + BASEGFX_DLLPUBLIC double getAxialGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo); + + /** Create matrix for ODF's radial gradient definition + + @param o_rGradientInfo + Receives the calculated texture transformation matrix (for + use with standard [0,1]x[0,1] texture coordinates) + + @param rTargetArea + Output area, needed for aspect ratio calculations and + texture transformation + + @param rOffset + Gradient offset value (from ODF) + + @param nRequestedSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo createRadialODFGradientInfo( + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nRequestedSteps, + double fBorder); + + + /** Calculate radial gradient blend value + + This method generates you the lerp alpha value for + blending linearly between gradient start and end color, + according to the formula (startCol*(1.0-alpha) + endCol*alpha) + + @param rUV + Current uv coordinate. Values outside [0,1] will be + clamped. + + @param rGradInfo + Gradient info, for transformation and number of steps + */ + BASEGFX_DLLPUBLIC double getRadialGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo); + + /** Create matrix for ODF's elliptical gradient definition + + @param o_rGradientInfo + Receives the calculated texture transformation matrix (for + use with standard [0,1]x[0,1] texture coordinates) + + @param rTargetArea + Output area, needed for aspect ratio calculations and + texture transformation + + @param rOffset + Gradient offset value (from ODF) + + @param nRequestedSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo createEllipticalODFGradientInfo( + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nRequestedSteps, + double fBorder, + double fAngle); + + + /** Calculate elliptical gradient blend value + + This method generates you the lerp alpha value for + blending linearly between gradient start and end color, + according to the formula (startCol*(1.0-alpha) + endCol*alpha) + + @param rUV + Current uv coordinate. Values outside [0,1] will be + clamped. + + @param rGradInfo + Gradient info, for transformation and number of steps + */ + BASEGFX_DLLPUBLIC double getEllipticalGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo); + + /** Create matrix for ODF's square gradient definition + + @param o_rGradientInfo + Receives the calculated texture transformation matrix (for + use with standard [0,1]x[0,1] texture coordinates) + + @param rTargetArea + Output area, needed for aspect ratio calculations and + texture transformation + + @param rOffset + Gradient offset value (from ODF) + + @param nRequestedSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo createSquareODFGradientInfo( + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nRequestedSteps, + double fBorder, + double fAngle); + + + /** Calculate square gradient blend value + + This method generates you the lerp alpha value for + blending linearly between gradient start and end color, + according to the formula (startCol*(1.0-alpha) + endCol*alpha) + + @param rUV + Current uv coordinate. Values outside [0,1] will be + clamped. + + @param rGradInfo + Gradient info, for transformation and number of steps + */ + BASEGFX_DLLPUBLIC double getSquareGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo); + + /** Create matrix for ODF's rectangular gradient definition + + @param o_rGradientInfo + Receives the calculated texture transformation matrix (for + use with standard [0,1]x[0,1] texture coordinates) + + @param rTargetArea + Output area, needed for aspect ratio calculations and + texture transformation + + @param rOffset + Gradient offset value (from ODF) + + @param nRequestedSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo createRectangularODFGradientInfo( + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nRequestedSteps, + double fBorder, + double fAngle); + + + /** Calculate rectangular gradient blend value + + This method generates you the lerp alpha value for + blending linearly between gradient start and end color, + according to the formula (startCol*(1.0-alpha) + endCol*alpha) + + @param rUV + Current uv coordinate. Values outside [0,1] will be + clamped. + + @param rGradInfo + Gradient info, for transformation and number of steps + */ + BASEGFX_DLLPUBLIC double getRectangularGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/keystoplerp.hxx b/include/basegfx/utils/keystoplerp.hxx new file mode 100644 index 0000000000..f8a821e7a5 --- /dev/null +++ b/include/basegfx/utils/keystoplerp.hxx @@ -0,0 +1,85 @@ +/* -*- 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 <vector> +#include <basegfx/basegfxdllapi.h> + +namespace com::sun::star::uno { + template<typename T> class Sequence; +} + +namespace basegfx::utils +{ + /** Lerp in a vector of key stops + + This class holds a key stop vector and provides the + functionality to lerp inside it. Useful e.g. for + multi-stop gradients, or the SMIL key time activity. + + For those, given a global [0,1] lerp alpha, one need to + find the suitable bucket index from key stop vector, and + then calculate the relative alpha between the two buckets + found. + */ + class BASEGFX_DLLPUBLIC KeyStopLerp + { + public: + typedef std::pair<std::ptrdiff_t,double> ResultType; + + /** Create lerper with given vector of stops + + @param rKeyStops + + Vector of stops, must contain at least two elements + (though preferably more, otherwise you probably don't + need key stop lerping in the first place). All + elements must be of monotonically increasing value. + */ + explicit KeyStopLerp( std::vector<double>&& rKeyStops ); + + /** Create lerper with given sequence of stops + + @param rKeyStops + + Sequence of stops, must contain at least two elements + (though preferably more, otherwise you probably don't + need key stop lerping in the first place). All + elements must be of monotonically increasing value. + */ + explicit KeyStopLerp( const css::uno::Sequence<double>& rKeyStops ); + + /** Find two nearest bucket index & interpolate + + @param fAlpha + Find bucket index i, with keyStops[i] < fAlpha <= + keyStops[i+1]. Return new alpha value in [0,1), + proportional to fAlpha's position between keyStops[i] + and keyStops[i+1] + */ + ResultType lerp(double fAlpha) const; + + private: + std::vector<double> maKeyStops; + mutable std::ptrdiff_t mnLastIndex; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/lerp.hxx b/include/basegfx/utils/lerp.hxx new file mode 100644 index 0000000000..e02b3b0fa5 --- /dev/null +++ b/include/basegfx/utils/lerp.hxx @@ -0,0 +1,43 @@ +/* -*- 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 + +namespace basegfx::utils +{ + /** Generic linear interpolator + + @tpl ValueType + Must have operator+ and operator* defined, and should + have value semantics. + + @param t + As usual, t must be in the [0,1] range + */ + template< typename ValueType > ValueType lerp( const ValueType& rFrom, + const ValueType& rTo, + double t ) + { + // This is only to suppress a double->int warning. All other + // types should be okay here. + return static_cast<ValueType>( (1.0-t)*rFrom + t*rTo ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/rectcliptools.hxx b/include/basegfx/utils/rectcliptools.hxx new file mode 100644 index 0000000000..af6be75bfc --- /dev/null +++ b/include/basegfx/utils/rectcliptools.hxx @@ -0,0 +1,72 @@ +/* -*- 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 <sal/types.h> +#include <basegfx/range/b2ibox.hxx> + + +namespace basegfx::utils +{ + namespace RectClipFlags + { + const sal_uInt32 LEFT = sal_Int32(0x01); + const sal_uInt32 RIGHT = sal_Int32(0x02); + const sal_uInt32 TOP = sal_Int32(0x04); + const sal_uInt32 BOTTOM = sal_Int32(0x08); + } + + /** Calc clip mask for Cohen-Sutherland rectangle clip + + This function returns a clip mask used for the + Cohen-Sutherland rectangle clip method, where one or more + of the lower four bits are set, if the given point is + outside one or more of the four half planes defining the + rectangle (see RectClipFlags for possible values) + */ + template< class Point, class Rect > inline + sal_uInt32 getCohenSutherlandClipFlags( const Point& rP, + const Rect& rR ) + { + // maxY | minY | maxX | minX + sal_uInt32 clip; + clip = (rP.getX() < rR.getMinX()) << 0; + clip |= (rP.getX() > rR.getMaxX()) << 1; + clip |= (rP.getY() < rR.getMinY()) << 2; + clip |= (rP.getY() > rR.getMaxY()) << 3; + return clip; + } + + /// Cohen-Sutherland mask calculation - overload for boxes. + template< class Point > inline + sal_uInt32 getCohenSutherlandClipFlags( const Point& rP, + const B2IBox& rB ) + { + // maxY | minY | maxX | minX + sal_uInt32 clip; + clip = (rP.getX() < rB.getMinX()) << 0; + clip |= (rP.getX() >= rB.getMaxX()) << 1; + clip |= (rP.getY() < rB.getMinY()) << 2; + clip |= (rP.getY() >= rB.getMaxY()) << 3; + return clip; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/systemdependentdata.hxx b/include/basegfx/utils/systemdependentdata.hxx new file mode 100644 index 0000000000..9304153c13 --- /dev/null +++ b/include/basegfx/utils/systemdependentdata.hxx @@ -0,0 +1,111 @@ +/* -*- 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/. + */ + +#pragma once + +#include <sal/types.h> +#include <basegfx/basegfxdllapi.h> +#include <memory> +#include <map> + +namespace basegfx +{ + class SystemDependentData; + typedef std::shared_ptr<SystemDependentData> SystemDependentData_SharedPtr; + typedef std::weak_ptr<SystemDependentData> SystemDependentData_WeakPtr; + + class BASEGFX_DLLPUBLIC SystemDependentDataManager + { + private: + // noncopyable + SystemDependentDataManager(const SystemDependentDataManager&) = delete; + SystemDependentDataManager& operator=(const SystemDependentDataManager&) = delete; + + public: + SystemDependentDataManager(); + virtual ~SystemDependentDataManager(); + + // call from (and with) SystemDependentData objects when start/end/touch + // usage is needed + virtual void startUsage(basegfx::SystemDependentData_SharedPtr& rData) = 0; + virtual void endUsage(basegfx::SystemDependentData_SharedPtr& rData) = 0; + virtual void touchUsage(basegfx::SystemDependentData_SharedPtr& rData) = 0; + + // flush all buffered data (e.g. cleanup/shutdown) + virtual void flushAll() = 0; + }; + + class BASEGFX_DLLPUBLIC SystemDependentData + { + private: + // noncopyable + SystemDependentData(const SystemDependentData&) = delete; + SystemDependentData& operator=(const SystemDependentData&) = delete; + + // reference to a SystemDependentDataManager, probably + // a single, globally used one, but not necessarily + SystemDependentDataManager& mrSystemDependentDataManager; + + // Buffered CalculatedCycles, result of estimations using + // getHoldCyclesInSeconds and estimateUsageInBytes, executed + // using getHoldCyclesInSeconds. StartValue is 0 to detect + // not-yet-calculated state + sal_uInt32 mnCalculatedCycles; + + public: + SystemDependentData( + SystemDependentDataManager& rSystemDependentDataManager); + + // CAUTION! It is VERY important to keep this base class + // virtual, else typeid(class).hash_code() from derived classes + // will NOT work what is ESSENTIAL for the SystemDependentData + // mechanism to work properly. So DO NOT REMOVE virtual here, please. + virtual ~SystemDependentData(); + + // allow access to call startUsage/endUsage/touchUsage + // using getSystemDependentDataManager() + SystemDependentDataManager& getSystemDependentDataManager() { return mrSystemDependentDataManager; } + + // Calculate HoldCyclesInSeconds based on using + // getHoldCyclesInSeconds and estimateUsageInBytes, the + // result is created once on-demand and buffered in + // mnCalculatedCycles + sal_uInt32 calculateCombinedHoldCyclesInSeconds() const; + + // Allow read access to the calculated cycles in seconds, this + // can be e.g. used to determine if this instance got added + sal_uInt32 getCombinedHoldCyclesInSeconds() const { return mnCalculatedCycles; } + + // Size estimation of the entry in bytes - does not have to + // be used, but should be. Default returns zero what + // means there is no size estimation available. Override to + // offer useful data if you want to have better caching. + virtual sal_Int64 estimateUsageInBytes() const; + }; + + class BASEGFX_DLLPUBLIC SystemDependentDataHolder + { + private: + // Possibility to hold System-Dependent B2DPolygon-Representations + std::map< size_t, SystemDependentData_WeakPtr > maSystemDependentReferences; + + // noncopyable + SystemDependentDataHolder(const SystemDependentDataHolder&) = delete; + SystemDependentDataHolder& operator=(const SystemDependentDataHolder&) = delete; + + public: + SystemDependentDataHolder(); + virtual ~SystemDependentDataHolder(); + + void addOrReplaceSystemDependentData(SystemDependentData_SharedPtr& rData); + SystemDependentData_SharedPtr getSystemDependentData(size_t hash_code) const; + }; +} // end of namespace basegfx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/tools.hxx b/include/basegfx/utils/tools.hxx new file mode 100644 index 0000000000..f8fc619995 --- /dev/null +++ b/include/basegfx/utils/tools.hxx @@ -0,0 +1,124 @@ +/* -*- 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 <sal/types.h> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B2DPoint; + class B2DRange; + class B2DPolyPolygon; +} + +namespace basegfx::utils +{ + /** Expand given parallelogram, such that it extends beyond + bound rect in a given direction. + + This method is useful when e.g. generating one-dimensional + gradients, such as linear or axial gradients: those + gradients vary only in one direction, the other has + constant color. Most of the time, those gradients extends + infinitely in the direction with the constant color, but + practically, one always has a limiting bound rect into + which the gradient is painted. The method at hand now + extends a given parallelogram (e.g. the transformed + bounding box of a gradient) virtually into infinity to the + top and to the bottom (i.e. normal to the line io_rLeftTop + io_rRightTop), such that the given rectangle is guaranteed + to be covered in that direction. + + @attention There might be some peculiarities with this + method, that might limit its usage to the described + gradients. One of them is the fact that when determining + how far the parallelogram has to be extended to the top or + the bottom, the upper and lower border are assumed to be + infinite lines. + + @param io_rLeftTop + Left, top edge of the parallelogramm. Note that this need + not be the left, top edge geometrically, it's just used + when determining the extension direction. Thus, it's + perfectly legal to affine-transform a rectangle, and given + the transformed point here. On method return, this + parameter will contain the adapted output. + + @param io_rLeftBottom + Left, bottom edge of the parallelogramm. Note that this need + not be the left, bottom edge geometrically, it's just used + when determining the extension direction. Thus, it's + perfectly legal to affine-transform a rectangle, and given + the transformed point here. On method return, this + parameter will contain the adapted output. + + @param io_rRightTop + Right, top edge of the parallelogramm. Note that this need + not be the right, top edge geometrically, it's just used + when determining the extension direction. Thus, it's + perfectly legal to affine-transform a rectangle, and given + the transformed point here. On method return, this + parameter will contain the adapted output. + + @param io_rRightBottom + Right, bottom edge of the parallelogramm. Note that this need + not be the right, bottom edge geometrically, it's just used + when determining the extension direction. Thus, it's + perfectly legal to affine-transform a rectangle, and given + the transformed point here. On method return, this + parameter will contain the adapted output. + + @param rFitTarget + The rectangle to fit the parallelogram into. + */ + BASEGFX_DLLPUBLIC void infiniteLineFromParallelogram( ::basegfx::B2DPoint& io_rLeftTop, + ::basegfx::B2DPoint& io_rLeftBottom, + ::basegfx::B2DPoint& io_rRightTop, + ::basegfx::B2DPoint& io_rRightBottom, + const ::basegfx::B2DRange& rFitTarget ); + + /** Creates polypolygon with the given number as seven-segment + digits + + @param fVal + Value to convert + + @param nTotalDigits + Total number of digits to display. If less is needed for + given number, fill space with blanks. + + @param nDecPlaces + Decimal places to show. When 0, display as integer. When + negative, fill given number of before-the-decimal point + with zero. + + @param bLitSegments + When true, return a polygon containing the segments that + are 'lit' for the given number. Return un-lit segments + otherwise. + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon number2PolyPolygon(double fVal, + sal_Int32 nTotalDigits, + sal_Int32 nDecPlaces, + bool bLitSegments=true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/unopolypolygon.hxx b/include/basegfx/utils/unopolypolygon.hxx new file mode 100644 index 0000000000..48788b074e --- /dev/null +++ b/include/basegfx/utils/unopolypolygon.hxx @@ -0,0 +1,104 @@ +/* -*- 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 <comphelper/compbase.hxx> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/rendering/FillRule.hpp> +#include <com/sun/star/rendering/XLinePolyPolygon2D.hpp> +#include <com/sun/star/rendering/XBezierPolyPolygon2D.hpp> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/basegfxdllapi.h> +#include <o3tl/safeint.hxx> + +namespace basegfx::unotools +{ + typedef comphelper::WeakComponentImplHelper< + css::rendering::XLinePolyPolygon2D, + css::rendering::XBezierPolyPolygon2D, + css::lang::XServiceInfo > UnoPolyPolygonBase; + + class BASEGFX_DLLPUBLIC UnoPolyPolygon + : public UnoPolyPolygonBase + { + public: + explicit UnoPolyPolygon( B2DPolyPolygon ); + + // XPolyPolygon2D + SAL_DLLPRIVATE virtual void SAL_CALL addPolyPolygon( const css::geometry::RealPoint2D& position, const css::uno::Reference< css::rendering::XPolyPolygon2D >& polyPolygon ) override; + SAL_DLLPRIVATE virtual ::sal_Int32 SAL_CALL getNumberOfPolygons( ) override; + SAL_DLLPRIVATE virtual ::sal_Int32 SAL_CALL getNumberOfPolygonPoints( ::sal_Int32 polygon ) override; + SAL_DLLPRIVATE virtual css::rendering::FillRule SAL_CALL getFillRule( ) override; + SAL_DLLPRIVATE virtual void SAL_CALL setFillRule( css::rendering::FillRule fillRule ) override; + SAL_DLLPRIVATE virtual sal_Bool SAL_CALL isClosed( ::sal_Int32 index ) override; + SAL_DLLPRIVATE virtual void SAL_CALL setClosed( ::sal_Int32 index, sal_Bool closedState ) override; + + // XLinePolyPolygon2D + SAL_DLLPRIVATE virtual css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > > SAL_CALL getPoints( ::sal_Int32 nPolygonIndex, ::sal_Int32 nNumberOfPolygons, ::sal_Int32 nPointIndex, ::sal_Int32 nNumberOfPoints ) override; + SAL_DLLPRIVATE virtual void SAL_CALL setPoints( const css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > >& points, ::sal_Int32 nPolygonIndex ) override; + SAL_DLLPRIVATE virtual css::geometry::RealPoint2D SAL_CALL getPoint( ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) override; + SAL_DLLPRIVATE virtual void SAL_CALL setPoint( const css::geometry::RealPoint2D& point, ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) override; + + // XBezierPolyPolygon2D + SAL_DLLPRIVATE virtual css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > > SAL_CALL getBezierSegments( ::sal_Int32 nPolygonIndex, ::sal_Int32 nNumberOfPolygons, ::sal_Int32 nPointIndex, ::sal_Int32 nNumberOfPoints ) override; + SAL_DLLPRIVATE virtual void SAL_CALL setBezierSegments( const css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > >& points, ::sal_Int32 nPolygonIndex ) override; + SAL_DLLPRIVATE virtual css::geometry::RealBezierSegment2D SAL_CALL getBezierSegment( ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) override; + SAL_DLLPRIVATE virtual void SAL_CALL setBezierSegment( const css::geometry::RealBezierSegment2D& point, ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) override; + + // XServiceInfo + SAL_DLLPRIVATE virtual OUString SAL_CALL getImplementationName() override; + SAL_DLLPRIVATE virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + SAL_DLLPRIVATE virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + SAL_DLLPRIVATE B2DPolyPolygon getPolyPolygon() const; + + protected: + /// Check whether index is a valid polygon index + void checkIndex( sal_Int32 nIndex ) const // throw (css::lang::IndexOutOfBoundsException); + { + if( nIndex < 0 || o3tl::make_unsigned(nIndex) >= maPolyPoly.count() ) + throw css::lang::IndexOutOfBoundsException(); + } + + SAL_DLLPRIVATE B2DPolyPolygon getSubsetPolyPolygon( sal_Int32 nPolygonIndex, + sal_Int32 nNumberOfPolygons, + sal_Int32 nPointIndex, + sal_Int32 nNumberOfPoints ) const; + + /// Get cow copy of internal polygon. not thread-safe outside this object. + const B2DPolyPolygon& getPolyPolygonUnsafe() const + { + return maPolyPoly; + } + + /// Called whenever internal polypolygon gets modified + virtual void modifying() const {} + + private: + UnoPolyPolygon(const UnoPolyPolygon&) = delete; + UnoPolyPolygon& operator=(const UnoPolyPolygon&) = delete; + + B2DPolyPolygon maPolyPoly; + css::rendering::FillRule meFillRule; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/utils/zoomtools.hxx b/include/basegfx/utils/zoomtools.hxx new file mode 100644 index 0000000000..16a36448af --- /dev/null +++ b/include/basegfx/utils/zoomtools.hxx @@ -0,0 +1,22 @@ +/* -*- 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/. + */ + +#pragma once + +#include <basegfx/basegfxdllapi.h> + +namespace basegfx::zoomtools +{ +/** This namespace provides functions for optimized geometric zooming +*/ +BASEGFX_DLLPUBLIC sal_uInt16 zoomOut(sal_uInt16 nCurrent); +BASEGFX_DLLPUBLIC sal_uInt16 zoomIn(sal_uInt16 nCurrent); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |