diff options
author | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2013-04-18 18:26:28 +0200 |
---|---|---|
committer | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2013-04-23 22:20:31 +0200 |
commit | b9337e22ce1dbf2eba0e8c8db294ae99f4111f91 (patch) | |
tree | 53ee1bd3dfd213815a21579151983cb997922b05 /include/basegfx | |
parent | f4e1642a1761d5eab6ccdd89928869c2b2f1528a (diff) |
execute move of global headers
see https://gerrit.libreoffice.org/#/c/3367/
and Change-Id: I00c96fa77d04b33a6f8c8cd3490dfcd9bdc9e84a for details
Change-Id: I199a75bc4042af20817265d5ef85b1134a96ff5a
Diffstat (limited to 'include/basegfx')
71 files changed, 11996 insertions, 0 deletions
diff --git a/include/basegfx/basegfxdllapi.h b/include/basegfx/basegfxdllapi.h new file mode 100644 index 000000000000..b71f0755d277 --- /dev/null +++ b/include/basegfx/basegfxdllapi.h @@ -0,0 +1,42 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_BASEGFXDLLAPI_H +#define INCLUDED_BASEGFXDLLAPI_H + +#if defined BASEGFX_STATICLIBRARY + +#define BASEGFX_DLLPUBLIC +#define BASEGFX_DLLPRIVATE + +#else /*BASEGFX_STATICLIBRARY*/ + +#if defined BASEGFX_DLLIMPLEMENTATION +#define BASEGFX_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define BASEGFX_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif +#define BASEGFX_DLLPRIVATE SAL_DLLPRIVATE + +#endif /*BASEGFX_STATICLIBRARY*/ + +#endif + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/color/bcolor.hxx b/include/basegfx/color/bcolor.hxx new file mode 100644 index 000000000000..9b91e212ec89 --- /dev/null +++ b/include/basegfx/color/bcolor.hxx @@ -0,0 +1,229 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_COLOR_BCOLOR_HXX +#define _BGFX_COLOR_BCOLOR_HXX + +#include <basegfx/tuple/b3dtuple.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +namespace com { namespace sun { namespace star { namespace rendering { + class XGraphicDevice; +}}}} + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + /** Base Color class with three double values + + This class derives all operators and common handling for + a 3D data class from B3DTuple. All necessary extensions + which are special for colors will be added here. + + @see B3DTuple + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED BColor : public B3DTuple + { + public: + /** Create a Color with red, green and blue components from [0.0 to 1.0] + + The color is initialized to (0.0, 0.0, 0.0) + */ + BColor() + : B3DTuple() + {} + + /** Create a 3D Color + + @param fRed + @param fGreen + @param fBlue + These parameters are used to initialize the red, green and blue intensities of the color + */ + BColor(double fRed, double fGreen, double fBlue) + : B3DTuple(fRed, fGreen, fBlue) + {} + + /** Create a 3D Color + + @param fLuminosity + The parameter is used to initialize the red, green and blue intensities of the color + */ + explicit BColor(double fLuminosity) + : B3DTuple(fLuminosity, fLuminosity, fLuminosity) + {} + + /** Create a copy of a Color + + @param rVec + The Color which will be copied. + */ + BColor(const BColor& rVec) + : B3DTuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B3DTuple-based classes + */ + BColor(const ::basegfx::B3DTuple& rTuple) + : B3DTuple(rTuple) + {} + + ~BColor() + {} + + // data access read + double getRed() const { return mfX; } + double getGreen() const { return mfY; } + double getBlue() const { return mfZ; } + + // data access write + void setRed(double fNew) { mfX = fNew; } + void setGreen(double fNew) { mfY = fNew; } + void setBlue(double fNew) { mfZ = fNew; } + + /** *=operator to allow usage from BColor, too + */ + BColor& operator*=( const BColor& rPnt ) + { + mfX *= rPnt.mfX; + mfY *= rPnt.mfY; + mfZ *= rPnt.mfZ; + return *this; + } + + /** *=operator to allow usage from BColor, too + */ + BColor& operator*=(double t) + { + mfX *= t; + mfY *= t; + mfZ *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B3DTuple calculations + */ + BColor& operator=( const ::basegfx::B3DTuple& rVec ) + { + mfX = rVec.getX(); + mfY = rVec.getY(); + mfZ = rVec.getZ(); + return *this; + } + + // blend to another color using luminance + void blend(const BColor& rColor) + { + const double fLuminance(luminance()); + mfX = rColor.getRed() * fLuminance; + mfY = rColor.getGreen() * fLuminance; + mfZ = rColor.getBlue() * fLuminance; + } + + // luminance + double luminance() const + { + const double fRedWeight(77.0 / 256.0); // 0.30 + const double fGreenWeight(151.0 / 256.0); // 0.59 + const double fBlueWeight(28.0 / 256.0); // 0.11 + + return (mfX * fRedWeight + mfY * fGreenWeight + mfZ * fBlueWeight); + } + + // distances in color space + double getDistanceRed(const BColor& rColor) const { return (getRed() > rColor.getRed() ? getRed() - rColor.getRed() : rColor.getRed() - getRed()); } + double getDistanceGreen(const BColor& rColor) const { return (getGreen() > rColor.getGreen() ? getGreen() - rColor.getGreen() : rColor.getGreen() - getGreen()); } + double getDistanceBlue(const BColor& rColor) const { return (getBlue() > rColor.getBlue() ? getBlue() - rColor.getBlue() : rColor.getBlue() - getBlue()); } + + double getDistance(const BColor& rColor) const + { + const double fDistR(getDistanceRed(rColor)); + const double fDistG(getDistanceGreen(rColor)); + const double fDistB(getDistanceBlue(rColor)); + + return sqrt(fDistR * fDistR + fDistG * fDistG + fDistB * fDistB); + } + + double getMinimumDistance(const BColor& rColor) const + { + const double fDistR(getDistanceRed(rColor)); + const double fDistG(getDistanceGreen(rColor)); + const double fDistB(getDistanceBlue(rColor)); + + double fRetval(fDistR < fDistG ? fDistR : fDistG); + return (fRetval < fDistB ? fRetval : fDistB); + } + + double getMaximumDistance(const BColor& rColor) const + { + const double fDistR(getDistanceRed(rColor)); + const double fDistG(getDistanceGreen(rColor)); + const double fDistB(getDistanceBlue(rColor)); + + double fRetval(fDistR > fDistG ? fDistR : fDistG); + return (fRetval > fDistB ? fRetval : fDistB); + } + + // clamp color to [0.0..1.0] values in all three intensity components + void clamp() + { + mfX = basegfx::clamp(mfX, 0.0, 1.0); + mfY = basegfx::clamp(mfY, 0.0, 1.0); + mfZ = basegfx::clamp(mfZ, 0.0, 1.0); + } + + void invert() + { + mfX = 1.0 - mfX; + mfY = 1.0 - mfY; + mfZ = 1.0 - mfZ; + } + + static const BColor& getEmptyBColor() + { + return (const BColor&) ::basegfx::B3DTuple::getEmptyTuple(); + } + + com::sun::star::uno::Sequence< double > colorToDoubleSequence(const com::sun::star::uno::Reference< com::sun::star::rendering::XGraphicDevice >& /*xGraphicDevice*/) const + { + com::sun::star::uno::Sequence< double > aRet(4); + double* pRet = aRet.getArray(); + + pRet[0] = mfX; + pRet[1] = mfY; + pRet[2] = mfZ; + pRet[3] = 1.0; + + return aRet; + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_COLOR_BCOLOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/color/bcolormodifier.hxx b/include/basegfx/color/bcolormodifier.hxx new file mode 100644 index 000000000000..4b6f04efc8e9 --- /dev/null +++ b/include/basegfx/color/bcolormodifier.hxx @@ -0,0 +1,137 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_COLOR_BCOLORMODIFIER_HXX +#define _BGFX_COLOR_BCOLORMODIFIER_HXX + +#include <basegfx/color/bcolor.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + /** Descriptor for type of color modification + */ + enum BColorModifyMode + { + BCOLORMODIFYMODE_REPLACE, // replace all color with local color + BCOLORMODIFYMODE_INTERPOLATE, // interpolate color between given and local with local value + BCOLORMODIFYMODE_GRAY, // convert color to gray + BCOLORMODIFYMODE_BLACKANDWHITE, // convert color to B&W, local value is treshhold + BCOLORMODIFYMODE_INVERT, // invert color + BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA // convert color to alpha value (used for Svg Mask) + }; + + /** Class to hold a color, value and mode for a color modification. Color modification is + done calling the getModifiedColor() method + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED BColorModifier + { + protected: + ::basegfx::BColor maBColor; + double mfValue; + BColorModifyMode meMode; + + public: + BColorModifier( + const ::basegfx::BColor& rBColor, + double fValue = 0.5, + BColorModifyMode eMode = BCOLORMODIFYMODE_REPLACE) + : maBColor(rBColor), + mfValue(fValue), + meMode(eMode) + {} + + // compare operator(s) + bool operator==(const BColorModifier& rCompare) const + { + return (maBColor == rCompare.maBColor && mfValue == rCompare.mfValue && meMode == rCompare.meMode); + } + + bool operator!=(const BColorModifier& rCompare) const + { + return !(operator==(rCompare)); + } + + // data access + const ::basegfx::BColor& getBColor() const { return maBColor; } + double getValue() const { return mfValue; } + BColorModifyMode getMode() const { return meMode; } + + // compute modified color + ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const; + }; + + /** Class to hold a stack of BColorModifiers and to get the modified color with + applying all existing entry changes + */ + class BASEGFX_DLLPUBLIC BColorModifierStack + { + protected: + ::std::vector< BColorModifier > maBColorModifiers; + + public: + sal_uInt32 count() const + { + return maBColorModifiers.size(); + } + + const BColorModifier& getBColorModifier(sal_uInt32 nIndex) const + { + OSL_ENSURE(nIndex < count(), "BColorModifierStack: Access out of range (!)"); + return maBColorModifiers[nIndex]; + } + + ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& rSource) const + { + if(count()) + { + ::basegfx::BColor aRetval(rSource); + ::std::vector< BColorModifier >::const_iterator aEnd(maBColorModifiers.end()); + + while(aEnd != maBColorModifiers.begin()) + { + aRetval = (--aEnd)->getModifiedColor(aRetval); + } + + return aRetval; + } + else + { + return rSource; + } + } + + void push(const BColorModifier& rNew) + { + maBColorModifiers.push_back(rNew); + } + + void pop() + { + maBColorModifiers.pop_back(); + } + }; +} // end of namespace basegfx + +#endif // _BGFX_COLOR_BCOLORMODIFIER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/color/bcolortools.hxx b/include/basegfx/color/bcolortools.hxx new file mode 100644 index 000000000000..42ac7aafb3cc --- /dev/null +++ b/include/basegfx/color/bcolortools.hxx @@ -0,0 +1,52 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_COLOR_BCOLORTOOLS_HXX +#define _BGFX_COLOR_BCOLORTOOLS_HXX + +#include <sal/types.h> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BColor; + + namespace tools + { + /// Transform from RGB to HSL + BASEGFX_DLLPUBLIC BColor rgb2hsl(const BColor& rRGBColor); + /// Transform from HSL to RGB + BASEGFX_DLLPUBLIC BColor hsl2rgb(const BColor& rHSLColor); + + /// Transform from RGB to HSV + BASEGFX_DLLPUBLIC BColor rgb2hsv(const BColor& rRGBColor); + /// Transform from HSV to RGB + BASEGFX_DLLPUBLIC BColor hsv2rgb(const BColor& rHSVColor); + + /// Transform from Rec. 709 RGB (D65 white point) into CIE XYZ + BASEGFX_DLLPUBLIC BColor rgb2ciexyz( const BColor& rRGBColor ); + + } +} // end of namespace basegfx + +#endif /* _BGFX_COLOR_BCOLORTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/curve/b2dbeziertools.hxx b/include/basegfx/curve/b2dbeziertools.hxx new file mode 100644 index 000000000000..f52f00a1912f --- /dev/null +++ b/include/basegfx/curve/b2dbeziertools.hxx @@ -0,0 +1,57 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_CURVE_B2DBEZIERTOOLS_HXX +#define _BGFX_CURVE_B2DBEZIERTOOLS_HXX + +#include <sal/types.h> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predefines + +namespace basegfx +{ + class B2DCubicBezier; +} + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC B2DCubicBezierHelper + { + private: + ::std::vector< double > maLengthArray; + sal_uInt32 mnEdgeCount; + + public: + explicit B2DCubicBezierHelper(const B2DCubicBezier& rBase, sal_uInt32 nDivisions = 9); + + double getLength() const { if(!maLengthArray.empty()) return maLengthArray[maLengthArray.size() - 1]; else return 0.0; } + double distanceToRelative(double fDistance) const; + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_CURVE_B2DBEZIERTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/curve/b2dcubicbezier.hxx b/include/basegfx/curve/b2dcubicbezier.hxx new file mode 100644 index 000000000000..003a1970bb0a --- /dev/null +++ b/include/basegfx/curve/b2dcubicbezier.hxx @@ -0,0 +1,200 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_CURVE_B2DCUBICBEZIER_HXX +#define _BGFX_CURVE_B2DCUBICBEZIER_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +namespace basegfx +{ + class B2DPolygon; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC B2DCubicBezier + { + B2DPoint maStartPoint; + B2DPoint maEndPoint; + B2DPoint maControlPointA; + B2DPoint maControlPointB; + + public: + B2DCubicBezier(); + B2DCubicBezier(const B2DCubicBezier& rBezier); + B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rControlPointA, const B2DPoint& rControlPointB, const B2DPoint& rEnd); + ~B2DCubicBezier(); + + // assignment operator + B2DCubicBezier& operator=(const B2DCubicBezier& rBezier); + + // compare operators + bool operator==(const B2DCubicBezier& rBezier) const; + bool operator!=(const B2DCubicBezier& rBezier) const; + bool equal(const B2DCubicBezier& rBezier) const; + + // test if vectors are used + bool isBezier() const; + + // test if contained bezier is trivial and reset vectors accordingly + void testAndSolveTrivialBezier(); + + /** get length of edge + + This method handles beziers and simple edges. For + beziers, the deviation describes the maximum allowed + deviation from the real edge length. The default + allows a deviation of 1% from the correct length. + + For beziers, there is no direct way to get the length, + thus this method may subdivide the bezier edge and may + not be cheap. + + @param fDeviation + The maximal allowed deviation between correct length + and bezier edge length + + @return + The length of the edge + */ + double getLength(double fDeviation = 0.01) const; + + // get distance between start and end point + double getEdgeLength() const; + + // get length of control polygon + double getControlPolygonLength() const; + + // data interface + B2DPoint getStartPoint() const { return maStartPoint; } + void setStartPoint(const B2DPoint& rValue) { maStartPoint = rValue; } + + B2DPoint getEndPoint() const { return maEndPoint; } + void setEndPoint(const B2DPoint& rValue) { maEndPoint = rValue; } + + B2DPoint getControlPointA() const { return maControlPointA; } + void setControlPointA(const B2DPoint& rValue) { maControlPointA = rValue; } + + B2DPoint getControlPointB() const { return maControlPointB; } + void setControlPointB(const B2DPoint& rValue) { maControlPointB = rValue; } + + /** get the tangent in point t + + This method handles all the exceptions, e.g. when control point + A is equal to start point and/or control point B is equal to end + point + + @param t + The bezier index in the range [0.0 .. 1.0]. It will be truncated. + + @return + The tangent vector in point t + */ + B2DVector getTangent(double t) const; + + /** adaptive subdivide by angle criteria + no start point is added, but all necessary created edges + and the end point + #i37443# allow the criteria to get unsharp in recursions + */ + void adaptiveSubdivideByAngle(B2DPolygon& rTarget, double fAngleBound, bool bAllowUnsharpen) const; + + /** #i37443# adaptive subdivide by nCount subdivisions + no start point is added, but all necessary created edges + and the end point + */ + void adaptiveSubdivideByCount(B2DPolygon& rTarget, sal_uInt32 nCount) const; + + /** Subdivide cubic bezier segment. + + This function adaptively subdivides the bezier + segment into as much straight line segments as necessary, + such that the maximal orthogonal distance from any of the + segments to the true curve is less than the given error + value. + No start point is added, but all necessary created edges + and the end point + + @param rPoly + Output polygon. The subdivided bezier segment is added to + this polygon via B2DPolygon::append(). + + @param rCurve + The cubic bezier curve to subdivide + + @param fDistanceBound + Bound on the maximal distance of the approximation to the + true curve. + */ + void adaptiveSubdivideByDistance(B2DPolygon& rTarget, double fDistanceBound) const; + + // get point at given relative position + B2DPoint interpolatePoint(double t) const; + + // calculate the smallest distance from given point to this cubic bezier segment + // and return the value. The relative position on the segment is returned in rCut. + double getSmallestDistancePointToBezierSegment(const B2DPoint& rTestPoint, double& rCut) const; + + // do a split at position t and fill both resulting segments + void split(double t, B2DCubicBezier* pBezierA, B2DCubicBezier* pBezierB) const; + + // extract snippet from fStart to fEnd from this bezier + B2DCubicBezier snippet(double fStart, double fEnd) const; + + // get range including conrol points + B2DRange getRange() const; + + /** Get the minimum extremum position t + + @param rfResult + Will be changed and set to a eventually found split value which should be in the + range [0.0 .. 1.0]. It will be the smallest current extremum; there may be more + + @return + Returns true if there was at least one extremum found + */ + bool getMinimumExtremumPosition(double& rfResult) const; + + /** Get all extremum pos of this segment + + This method will calculate all extremum positions of the segment + and add them to rResults if they are in the range ]0.0 .. 1.0[ + + @param rResults + The vector of doubles where the results will be added. Evtl. + existing contents will be removed since an empty vector is a + necessary result to express that there are no extreme positions + anymore. Since there is an upper maximum of 4 values, it makes + sense to use reserve(4) at the vector as preparation. + */ + void getAllExtremumPositions(::std::vector< double >& rResults) const; + }; +} // end of namespace basegfx + +#endif /* _BGFX_CURVE_B2DCUBICBEZIER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/b2dhommatrix.hxx b/include/basegfx/matrix/b2dhommatrix.hxx new file mode 100644 index 000000000000..30204b91fad5 --- /dev/null +++ b/include/basegfx/matrix/b2dhommatrix.hxx @@ -0,0 +1,139 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX +#define _BGFX_MATRIX_B2DHOMMATRIX_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B2DTuple; + class Impl2DHomMatrix; + + class BASEGFX_DLLPUBLIC B2DHomMatrix + { + public: + typedef o3tl::cow_wrapper< Impl2DHomMatrix > ImplType; + + private: + ImplType mpImpl; + + public: + B2DHomMatrix(); + B2DHomMatrix(const B2DHomMatrix& rMat); + ~B2DHomMatrix(); + + /** constructor to allow setting all needed values for a 3x2 matrix at once. The + parameter f_0x1 e.g. is the same as using set(0, 1, f) + */ + B2DHomMatrix(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2); + + double get(sal_uInt16 nRow, sal_uInt16 nColumn) const; + void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue); + + /** allow setting all needed values for a 3x2 matrix in one call. The + parameter f_0x1 e.g. is the same as using set(0, 1, f) + */ + void set3x2(double f_0x0, double f_0x1, double f_0x2, double f_1x0, double f_1x1, double f_1x2); + + // test if last line is default to see if last line needs to be + // involved in calculations + bool isLastLineDefault() const; + + // reset to a standard matrix + bool isIdentity() const; + void identity(); + + bool isInvertible() const; + bool invert(); + + void rotate(double fRadiant); + + void translate(double fX, double fY); + + void scale(double fX, double fY); + + // Shearing-Matrices + void shearX(double fSx); + void shearY(double fSy); + + B2DHomMatrix& operator+=(const B2DHomMatrix& rMat); + B2DHomMatrix& operator-=(const B2DHomMatrix& rMat); + + bool operator==(const B2DHomMatrix& rMat) const; + bool operator!=(const B2DHomMatrix& rMat) const; + + B2DHomMatrix& operator*=(double fValue); + B2DHomMatrix& operator/=(double fValue); + + // matrix multiplication from the left to the local + B2DHomMatrix& operator*=(const B2DHomMatrix& rMat); + + // assignment operator + B2DHomMatrix& operator=(const B2DHomMatrix& rMat); + + // Help routine to decompose given homogen 3x3 matrix to components. A correction of + // the components is done to avoid inaccuracies. + bool decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const; + }; + + // addition, subtraction + inline B2DHomMatrix operator+(const B2DHomMatrix& rMatA, const B2DHomMatrix& rMatB) + { + B2DHomMatrix aSum(rMatA); + aSum += rMatB; + return aSum; + } + + inline B2DHomMatrix operator-(const B2DHomMatrix& rMatA, const B2DHomMatrix& rMatB) + { + B2DHomMatrix aDiv(rMatA); + aDiv -= rMatB; + return aDiv; + } + + // multiplication, division by a constant + inline B2DHomMatrix operator*(const B2DHomMatrix& rMat, double fValue) + { + B2DHomMatrix aNew(rMat); + aNew *= fValue; + return aNew; + } + + inline B2DHomMatrix operator/(const B2DHomMatrix& rMat, double fValue) + { + B2DHomMatrix aNew(rMat); + aNew *= 1.0 / fValue; + return aNew; + } + + inline B2DHomMatrix operator*(const B2DHomMatrix& rMatA, const B2DHomMatrix& rMatB) + { + B2DHomMatrix aMul(rMatB); + aMul *= rMatA; + return aMul; + } +} // end of namespace basegfx + +#endif /* _BGFX_MATRIX_B2DHOMMATRIX_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/b2dhommatrixtools.hxx b/include/basegfx/matrix/b2dhommatrixtools.hxx new file mode 100644 index 000000000000..ed255360f831 --- /dev/null +++ b/include/basegfx/matrix/b2dhommatrixtools.hxx @@ -0,0 +1,225 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX +#define _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX + +#include <sal/types.h> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/basegfxdllapi.h> + + +/////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + /** If the rotation angle is an approximate multiple of pi/2, + force fSin/fCos to -1/0/1, to maintain orthogonality (which + might also be advantageous for the other cases, but: for + multiples of pi/2, the exact values _can_ be attained. It + would be largely unintuitive, if a 180 degrees rotation + would introduce slight roundoff errors, instead of exactly + mirroring the coordinate system) + */ + BASEGFX_DLLPUBLIC void createSinCosOrthogonal(double& o_rSin, double& rCos, double fRadiant); + + /** Tooling methods for on-the-fly matrix generation e.g. for inline + multiplications + */ + BASEGFX_DLLPUBLIC B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY); + BASEGFX_DLLPUBLIC B2DHomMatrix createShearXB2DHomMatrix(double fShearX); + BASEGFX_DLLPUBLIC B2DHomMatrix createShearYB2DHomMatrix(double fShearY); + BASEGFX_DLLPUBLIC B2DHomMatrix createRotateB2DHomMatrix(double fRadiant); + BASEGFX_DLLPUBLIC B2DHomMatrix createTranslateB2DHomMatrix(double fTranslateX, double fTranslateY); + + /// inline versions for parameters as tuples + inline B2DHomMatrix createScaleB2DHomMatrix(const B2DTuple& rScale) + { + return createScaleB2DHomMatrix(rScale.getX(), rScale.getY()); + } + + inline B2DHomMatrix createTranslateB2DHomMatrix(const B2DTuple& rTranslate) + { + return createTranslateB2DHomMatrix(rTranslate.getX(), rTranslate.getY()); + } + + /** Tooling methods for faster completely combined matrix creation + when scale, shearX, rotation and translation needs to be done in + exactly that order. It's faster since it direcly calculates + each matrix value based on a symbolic calculation of the three + matrix multiplications. + Inline versions for parameters as tuples added, too. + */ + BASEGFX_DLLPUBLIC B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix( + double fScaleX, double fScaleY, + double fShearX, + double fRadiant, + double fTranslateX, double fTranslateY); + inline B2DHomMatrix createScaleShearXRotateTranslateB2DHomMatrix( + const B2DTuple& rScale, + double fShearX, + double fRadiant, + const B2DTuple& rTranslate) + { + return createScaleShearXRotateTranslateB2DHomMatrix( + rScale.getX(), rScale.getY(), + fShearX, + fRadiant, + rTranslate.getX(), rTranslate.getY()); + } + + BASEGFX_DLLPUBLIC B2DHomMatrix createShearXRotateTranslateB2DHomMatrix( + double fShearX, + double fRadiant, + double fTranslateX, double fTranslateY); + inline B2DHomMatrix createShearXRotateTranslateB2DHomMatrix( + double fShearX, + double fRadiant, + const B2DTuple& rTranslate) + { + return createShearXRotateTranslateB2DHomMatrix( + fShearX, + fRadiant, + rTranslate.getX(), rTranslate.getY()); + } + + BASEGFX_DLLPUBLIC B2DHomMatrix createScaleTranslateB2DHomMatrix( + double fScaleX, double fScaleY, + double fTranslateX, double fTranslateY); + inline B2DHomMatrix createScaleTranslateB2DHomMatrix( + const B2DTuple& rScale, + const B2DTuple& rTranslate) + { + return createScaleTranslateB2DHomMatrix( + rScale.getX(), rScale.getY(), + rTranslate.getX(), rTranslate.getY()); + } + + /// special for the often used case of rotation around a point + BASEGFX_DLLPUBLIC B2DHomMatrix createRotateAroundPoint( + double fPointX, double fPointY, + double fRadiant); + inline B2DHomMatrix createRotateAroundPoint( + const B2DTuple& rPoint, + double fRadiant) + { + return createRotateAroundPoint( + rPoint.getX(), rPoint.getY(), + fRadiant); + } + + } // end of namespace tools +} // end of namespace basegfx + +/////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + class BASEGFX_DLLPUBLIC B2DHomMatrixBufferedDecompose + { + private: + B2DVector maScale; + B2DVector maTranslate; + double mfRotate; + double mfShearX; + + public: + B2DHomMatrixBufferedDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix()) + : maScale(), + maTranslate(), + mfRotate(0.0), + mfShearX(0.0) + { + rB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX); + } + + // data access + B2DHomMatrix getB2DHomMatrix() const + { + return createScaleShearXRotateTranslateB2DHomMatrix( + maScale, mfShearX, mfRotate, maTranslate); + } + + const B2DVector& getScale() const { return maScale; } + const B2DVector& getTranslate() const { return maTranslate; } + double getRotate() const { return mfRotate; } + double getShearX() const { return mfShearX; } + }; + } // end of namespace tools +} // end of namespace basegfx + +/////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + class BASEGFX_DLLPUBLIC B2DHomMatrixBufferedOnDemandDecompose + { + private: + B2DHomMatrix maB2DHomMatrix; + B2DVector maScale; + B2DVector maTranslate; + double mfRotate; + double mfShearX; + + // bitfield + unsigned mbDecomposed : 1; + + void impCheckDecompose() + { + if(!mbDecomposed) + { + maB2DHomMatrix.decompose(maScale, maTranslate, mfRotate, mfShearX); + mbDecomposed = true; + } + } + + public: + B2DHomMatrixBufferedOnDemandDecompose(const B2DHomMatrix& rB2DHomMatrix = B2DHomMatrix()) + : maB2DHomMatrix(rB2DHomMatrix), + maScale(), + maTranslate(), + mfRotate(0.0), + mfShearX(0.0), + mbDecomposed(false) + { + } + + // data access + const B2DHomMatrix& getB2DHomMatrix() const { return maB2DHomMatrix; } + const B2DVector& getScale() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maScale; } + const B2DVector& getTranslate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return maTranslate; } + double getRotate() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfRotate; } + double getShearX() const { const_cast< B2DHomMatrixBufferedOnDemandDecompose* >(this)->impCheckDecompose(); return mfShearX; } + }; + } // end of namespace tools + +} // end of namespace basegfx + +/////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_MATRIX_B2DHOMMATRIXTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/matrix/b3dhommatrix.hxx b/include/basegfx/matrix/b3dhommatrix.hxx new file mode 100644 index 000000000000..037d400d674f --- /dev/null +++ b/include/basegfx/matrix/b3dhommatrix.hxx @@ -0,0 +1,155 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX +#define _BGFX_MATRIX_B3DHOMMATRIX_HXX + +#include <sal/types.h> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B3DTuple; + class Impl3DHomMatrix; + + class BASEGFX_DLLPUBLIC B3DHomMatrix + { + public: + typedef o3tl::cow_wrapper< Impl3DHomMatrix > ImplType; + + private: + ImplType mpImpl; + + public: + B3DHomMatrix(); + B3DHomMatrix(const B3DHomMatrix& rMat); + ~B3DHomMatrix(); + + double get(sal_uInt16 nRow, sal_uInt16 nColumn) const; + void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue); + + // test if last line is default to see if last line needs to be + // involved in calculations + bool isLastLineDefault() const; + + bool isIdentity() const; + /// Reset to the identity matrix + void identity(); + + /// Invert the matrix (if possible) + bool invert(); + + /// Calc the matrix determinant + double determinant() const; + + /// Rotation + void rotate(double fAngleX,double fAngleY,double fAngleZ); + + /// Translation + void translate(double fX, double fY, double fZ); + + /// Scaling + void scale(double fX, double fY, double fZ); + + // Shearing-Matrices + void shearXY(double fSx, double fSy); + void shearXZ(double fSx, double fSz); + + // Projection matrices, used for converting between eye and + // clip coordinates + void frustum(double fLeft = -1.0, double fRight = 1.0, + double fBottom = -1.0, double fTop = 1.0, + double fNear = 0.001, double fFar = 1.0); + + void ortho(double fLeft = -1.0, double fRight = 1.0, + double fBottom = -1.0, double fTop = 1.0, + double fNear = 0.0, double fFar = 1.0); + + // build orientation matrix + void orientation( + B3DPoint aVRP = B3DPoint(0.0,0.0,1.0), + B3DVector aVPN = B3DVector(0.0,0.0,1.0), + B3DVector aVUV = B3DVector(0.0,1.0,0.0)); + + // addition, subtraction + B3DHomMatrix& operator+=(const B3DHomMatrix& rMat); + B3DHomMatrix& operator-=(const B3DHomMatrix& rMat); + + // comparison + bool operator==(const B3DHomMatrix& rMat) const; + bool operator!=(const B3DHomMatrix& rMat) const; + + // multiplication, division by constant value + B3DHomMatrix& operator*=(double fValue); + B3DHomMatrix& operator/=(double fValue); + + // matrix multiplication (from the left) + B3DHomMatrix& operator*=(const B3DHomMatrix& rMat); + + // assignment operator + B3DHomMatrix& operator=(const B3DHomMatrix& rMat); + + // decomposition + bool decompose(B3DTuple& rScale, B3DTuple& rTranslate, B3DTuple& rRotate, B3DTuple& rShear) const; + }; + + // addition, subtraction + inline B3DHomMatrix operator+(const B3DHomMatrix& rMatA, const B3DHomMatrix& rMatB) + { + B3DHomMatrix aSum(rMatA); + aSum += rMatB; + return aSum; + } + + inline B3DHomMatrix operator-(const B3DHomMatrix& rMatA, const B3DHomMatrix& rMatB) + { + B3DHomMatrix aDiv(rMatA); + aDiv -= rMatB; + return aDiv; + } + + // multiplication, division by constant value + inline B3DHomMatrix operator*(const B3DHomMatrix& rMat, double fValue) + { + B3DHomMatrix aNew(rMat); + aNew *= fValue; + return aNew; + } + + inline B3DHomMatrix operator/(const B3DHomMatrix& rMat, double fValue) + { + B3DHomMatrix aNew(rMat); + aNew *= 1.0 / fValue; + return aNew; + } + + inline B3DHomMatrix operator*(const B3DHomMatrix& rMatA, const B3DHomMatrix& rMatB) + { + B3DHomMatrix aMul(rMatB); + aMul *= rMatA; + return aMul; + } +} // end of namespace basegfx + +#endif /* _BGFX_MATRIX_B3DHOMMATRIX_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/numeric/ftools.hxx b/include/basegfx/numeric/ftools.hxx new file mode 100644 index 000000000000..70dcabe1a190 --- /dev/null +++ b/include/basegfx/numeric/ftools.hxx @@ -0,0 +1,198 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_NUMERIC_FTOOLS_HXX +#define _BGFX_NUMERIC_FTOOLS_HXX + +#include <rtl/math.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// standard PI defines from solar.h, but we do not want to link against tools + +#ifndef F_PI +#define F_PI M_PI +#endif +#ifndef F_PI2 +#define F_PI2 M_PI_2 +#endif +#ifndef F_PI4 +#define F_PI4 M_PI_4 +#endif +#ifndef F_PI180 +#define F_PI180 (M_PI/180.0) +#endif +#ifndef F_PI1800 +#define F_PI1800 (M_PI/1800.0) +#endif +#ifndef F_PI18000 +#define F_PI18000 (M_PI/18000.0) +#endif +#ifndef F_2PI +#define F_2PI (2.0*M_PI) +#endif + +////////////////////////////////////////////////////////////////////////////// +// fTools defines + +namespace basegfx +{ + /** Round double to nearest integer + + @return the nearest integer + */ + inline sal_Int32 fround( double fVal ) + { + return fVal > 0.0 ? static_cast<sal_Int32>( fVal + .5 ) : -static_cast<sal_Int32>( -fVal + .5 ); + } + + /** Round double to nearest integer + + @return the nearest 64 bit integer + */ + inline sal_Int64 fround64( double fVal ) + { + return fVal > 0.0 ? static_cast<sal_Int64>( fVal + .5 ) : -static_cast<sal_Int64>( -fVal + .5 ); + } + + /** Prune a small epsilon range around zero. + + Use this method e.g. for calculating scale values. There, it + is usually advisable not to set a scaling to 0.0, because that + yields singular transformation matrices. + + @param fVal + An arbitrary, but finite and valid number + + @return either fVal, or a small value slightly above (when + fVal>0) or below (when fVal<0) zero. + */ + inline double pruneScaleValue( double fVal ) + { + // old version used ::std::min/max, but this collides if min is defined as preprocessor + // macro which is the case e.g with windows.h headers. The simplest way to avoid this is to + // just use the full comparison. I keep the original here, maybe there will be a better + // solution some day. + // + //return fVal < 0.0 ? + // (::std::min(fVal,-0.00001)) : + // (::std::max(fVal,0.00001)); + + if(fVal < 0.0) + return (fVal < -0.00001 ? fVal : -0.00001); + else + return (fVal > 0.00001 ? fVal : 0.00001); + } + + /** clamp given value against given minimum and maximum values + */ + template <class T> inline const T& clamp(const T& value, const T& minimum, const T& maximum) + { + if(value < minimum) + { + return minimum; + } + else if(value > maximum) + { + return maximum; + } + else + { + return value; + } + } + + /** Convert value from degrees to radians + */ + inline double deg2rad( double v ) + { + // divide first, to get exact values for v being a multiple of + // 90 degrees + return v / 90.0 * M_PI_2; + } + + /** Convert value radians to degrees + */ + inline double rad2deg( double v ) + { + // divide first, to get exact values for v being a multiple of + // pi/2 + return v / M_PI_2 * 90.0; + } + + + class BASEGFX_DLLPUBLIC fTools + { + /// Threshold value for equalZero() + static double mfSmallValue; + + public: + /// Get threshold value for equalZero and friends + static double getSmallValue() { return mfSmallValue; } + /// Set threshold value for equalZero and friends + static void setSmallValue(const double& rfNew) { mfSmallValue = rfNew; } + + /// Compare against small value + static bool equalZero(const double& rfVal) + { + return (fabs(rfVal) <= getSmallValue()); + } + + /// Compare against given small value + static bool equalZero(const double& rfVal, const double& rfSmallValue) + { + return (fabs(rfVal) <= rfSmallValue); + } + + static bool equal(const double& rfValA, const double& rfValB) + { + // changed to approxEqual usage for better numerical correctness + return rtl::math::approxEqual(rfValA, rfValB); + } + + static bool equal(const double& rfValA, const double& rfValB, const double& rfSmallValue) + { + return (fabs(rfValA - rfValB) <= rfSmallValue); + } + + static bool less(const double& rfValA, const double& rfValB) + { + return (rfValA < rfValB && !equal(rfValA, rfValB)); + } + + static bool lessOrEqual(const double& rfValA, const double& rfValB) + { + return (rfValA < rfValB || equal(rfValA, rfValB)); + } + + static bool more(const double& rfValA, const double& rfValB) + { + return (rfValA > rfValB && !equal(rfValA, rfValB)); + } + + static bool moreOrEqual(const double& rfValA, const double& rfValB) + { + return (rfValA > rfValB || equal(rfValA, rfValB)); + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_NUMERIC_FTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/pixel/bpixel.hxx b/include/basegfx/pixel/bpixel.hxx new file mode 100644 index 000000000000..a2c59101fa78 --- /dev/null +++ b/include/basegfx/pixel/bpixel.hxx @@ -0,0 +1,217 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_PIXEL_BPIXEL_HXX +#define _BGFX_PIXEL_BPIXEL_HXX + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC BPixel + { + protected: + union + { + struct + { + // bitfield + unsigned mnR : 8; // red intensity + unsigned mnG : 8; // green intensity + unsigned mnB : 8; // blue intensity + unsigned mnO : 8; // opacity, 0 == full transparence + } maRGBO; + + struct + { + // bitfield + unsigned mnValue : 32; // all values + } maCombinedRGBO; + } maPixelUnion; + + public: + BPixel() + { + maPixelUnion.maCombinedRGBO.mnValue = 0L; + } + + // use explicit here to make sure everyone knows what he is doing. Values range from + // 0..255 integer here. + explicit BPixel(sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue, sal_uInt8 nOpacity) + { + maPixelUnion.maRGBO.mnR = nRed; + maPixelUnion.maRGBO.mnG = nGreen; + maPixelUnion.maRGBO.mnB = nBlue; + maPixelUnion.maRGBO.mnO = nOpacity; + } + + // constructor from BColor which uses double precision color, so change it + // to local integer format. It will also be clamped here. + BPixel(const BColor& rColor, sal_uInt8 nOpacity) + { + maPixelUnion.maRGBO.mnR = sal_uInt8((rColor.getRed() * 255.0) + 0.5); + maPixelUnion.maRGBO.mnG = sal_uInt8((rColor.getGreen() * 255.0) + 0.5); + maPixelUnion.maRGBO.mnB = sal_uInt8((rColor.getBlue() * 255.0) + 0.5); + maPixelUnion.maRGBO.mnO = nOpacity; + } + + // copy constructor + BPixel(const BPixel& rPixel) + { + maPixelUnion.maCombinedRGBO.mnValue = rPixel.maPixelUnion.maCombinedRGBO.mnValue; + } + + ~BPixel() + {} + + // assignment operator + BPixel& operator=( const BPixel& rPixel ) + { + maPixelUnion.maCombinedRGBO.mnValue = rPixel.maPixelUnion.maCombinedRGBO.mnValue; + return *this; + } + + // data access read + sal_uInt8 getRed() const { return maPixelUnion.maRGBO.mnR; } + sal_uInt8 getGreen() const { return maPixelUnion.maRGBO.mnG; } + sal_uInt8 getBlue() const { return maPixelUnion.maRGBO.mnB; } + sal_uInt8 getOpacity() const { return maPixelUnion.maRGBO.mnO; } + sal_uInt32 getRedGreenBlueOpacity() const { return maPixelUnion.maCombinedRGBO.mnValue; } + + // data access write + void setRed(sal_uInt8 nNew) { maPixelUnion.maRGBO.mnR = nNew; } + void setGreen(sal_uInt8 nNew) { maPixelUnion.maRGBO.mnG = nNew; } + void setBlue(sal_uInt8 nNew) { maPixelUnion.maRGBO.mnB = nNew; } + void setOpacity(sal_uInt8 nNew) { maPixelUnion.maRGBO.mnO = nNew; } + void setRedGreenBlueOpacity(sal_uInt32 nRedGreenBlueOpacity) { maPixelUnion.maCombinedRGBO.mnValue = nRedGreenBlueOpacity; } + void setRedGreenBlue(sal_uInt8 nR, sal_uInt8 nG, sal_uInt8 nB) { maPixelUnion.maRGBO.mnR = nR; maPixelUnion.maRGBO.mnG = nG; maPixelUnion.maRGBO.mnB = nB; } + + // comparators + bool isInvisible() const { return (0 == maPixelUnion.maRGBO.mnO); } + bool isVisible() const { return (0 != maPixelUnion.maRGBO.mnO); } + bool isEmpty() const { return isInvisible(); } + bool isUsed() const { return isVisible(); } + + bool operator==( const BPixel& rPixel ) const + { + return (rPixel.maPixelUnion.maCombinedRGBO.mnValue == maPixelUnion.maCombinedRGBO.mnValue); + } + + bool operator!=( const BPixel& rPixel ) const + { + return (rPixel.maPixelUnion.maCombinedRGBO.mnValue != maPixelUnion.maCombinedRGBO.mnValue); + } + + // empty element + static const BPixel& getEmptyBPixel(); + }; + + ////////////////////////////////////////////////////////////////////////// + // external operators + + inline BPixel minimum(const BPixel& rTupA, const BPixel& rTupB) + { + BPixel aMin( + (rTupB.getRed() < rTupA.getRed()) ? rTupB.getRed() : rTupA.getRed(), + (rTupB.getGreen() < rTupA.getGreen()) ? rTupB.getGreen() : rTupA.getGreen(), + (rTupB.getBlue() < rTupA.getBlue()) ? rTupB.getBlue() : rTupA.getBlue(), + (rTupB.getOpacity() < rTupA.getOpacity()) ? rTupB.getOpacity() : rTupA.getOpacity()); + return aMin; + } + + inline BPixel maximum(const BPixel& rTupA, const BPixel& rTupB) + { + BPixel aMax( + (rTupB.getRed() > rTupA.getRed()) ? rTupB.getRed() : rTupA.getRed(), + (rTupB.getGreen() > rTupA.getGreen()) ? rTupB.getGreen() : rTupA.getGreen(), + (rTupB.getBlue() > rTupA.getBlue()) ? rTupB.getBlue() : rTupA.getBlue(), + (rTupB.getOpacity() > rTupA.getOpacity()) ? rTupB.getOpacity() : rTupA.getOpacity()); + return aMax; + } + + inline BPixel interpolate(const BPixel& rOld1, const BPixel& rOld2, double t) + { + if(rOld1 == rOld2) + { + return rOld1; + } + else if(0.0 >= t) + { + return rOld1; + } + else if(1.0 <= t) + { + return rOld2; + } + else + { + const sal_uInt32 nFactor(fround(256.0 * t)); + const sal_uInt32 nNegFac(256L - nFactor); + return BPixel( + (sal_uInt8)(((sal_uInt32)rOld1.getRed() * nNegFac + (sal_uInt32)rOld2.getRed() * nFactor) >> 8L), + (sal_uInt8)(((sal_uInt32)rOld1.getGreen() * nNegFac + (sal_uInt32)rOld2.getGreen() * nFactor) >> 8L), + (sal_uInt8)(((sal_uInt32)rOld1.getBlue() * nNegFac + (sal_uInt32)rOld2.getBlue() * nFactor) >> 8L), + (sal_uInt8)(((sal_uInt32)rOld1.getOpacity() * nNegFac + (sal_uInt32)rOld2.getOpacity() * nFactor) >> 8L)); + } + } + + inline BPixel average(const BPixel& rOld1, const BPixel& rOld2) + { + if(rOld1 == rOld2) + { + return rOld1; + } + else + { + return BPixel( + (sal_uInt8)(((sal_uInt32)rOld1.getRed() + (sal_uInt32)rOld2.getRed()) >> 1L), + (sal_uInt8)(((sal_uInt32)rOld1.getGreen() + (sal_uInt32)rOld2.getGreen()) >> 1L), + (sal_uInt8)(((sal_uInt32)rOld1.getBlue() + (sal_uInt32)rOld2.getBlue()) >> 1L), + (sal_uInt8)(((sal_uInt32)rOld1.getOpacity() + (sal_uInt32)rOld2.getOpacity()) >> 1L)); + } + } + + inline BPixel average(const BPixel& rOld1, const BPixel& rOld2, const BPixel& rOld3) + { + if(rOld1 == rOld2 && rOld2 == rOld3) + { + return rOld1; + } + else + { + return BPixel( + (sal_uInt8)(((sal_uInt32)rOld1.getRed() + (sal_uInt32)rOld2.getRed() + (sal_uInt32)rOld3.getRed()) / 3L), + (sal_uInt8)(((sal_uInt32)rOld1.getGreen() + (sal_uInt32)rOld2.getGreen() + (sal_uInt32)rOld3.getGreen()) / 3L), + (sal_uInt8)(((sal_uInt32)rOld1.getBlue() + (sal_uInt32)rOld2.getBlue() + (sal_uInt32)rOld3.getBlue()) / 3L), + (sal_uInt8)(((sal_uInt32)rOld1.getOpacity() + (sal_uInt32)rOld2.getOpacity() + (sal_uInt32)rOld3.getOpacity()) / 3L)); + } + } +} // end of namespace basegfx + +#endif /* _BGFX_PIXEL_BPIXEL_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/point/b2dpoint.hxx b/include/basegfx/point/b2dpoint.hxx new file mode 100644 index 000000000000..ef73c8ab46c9 --- /dev/null +++ b/include/basegfx/point/b2dpoint.hxx @@ -0,0 +1,146 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POINT_B2DPOINT_HXX +#define _BGFX_POINT_B2DPOINT_HXX + +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predeclaration + class B2DHomMatrix; + + /** Base Point class with two double values + + This class derives all operators and common handling for + a 2D data class from B2DTuple. All necessary extensions + which are special for points will be added here. + + @see B2DTuple + */ + class SAL_WARN_UNUSED B2DPoint : public ::basegfx::B2DTuple + { + public: + /** Create a 2D Point + + The point is initialized to (0.0, 0.0) + */ + B2DPoint() + : B2DTuple() + {} + + /** Create a 2D Point + + @param fX + This parameter is used to initialize the X-coordinate + of the 2D Point. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 2D Point. + */ + B2DPoint(double fX, double fY) + : B2DTuple(fX, fY) + {} + + /** Create a copy of a 2D Point + + @param rPoint + The 2D Point which will be copied. + */ + B2DPoint(const B2DPoint& rPoint) + : B2DTuple(rPoint) + {} + + /** Create a copy of a 2D Point + + @param rPoint + The 2D Point which will be copied. + */ + explicit B2DPoint(const ::basegfx::B2IPoint& rPoint) + : B2DTuple(rPoint) + {} + + /** constructor with tuple to allow copy-constructing + from B2DTuple-based classes + */ + B2DPoint(const ::basegfx::B2DTuple& rTuple) + : B2DTuple(rTuple) + {} + + ~B2DPoint() + {} + + /** *=operator to allow usage from B2DPoint, too + */ + B2DPoint& operator*=( const B2DPoint& rPnt ) + { + mfX *= rPnt.mfX; + mfY *= rPnt.mfY; + return *this; + } + + /** *=operator to allow usage from B2DPoint, too + */ + B2DPoint& operator*=(double t) + { + mfX *= t; + mfY *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B2DTuple calculations + */ + BASEGFX_DLLPUBLIC B2DPoint& operator=( const ::basegfx::B2DTuple& rPoint ); + + /** Transform point by given transformation matrix. + + The translational components of the matrix are, in + contrast to B2DVector, applied. + */ + BASEGFX_DLLPUBLIC B2DPoint& operator*=( const ::basegfx::B2DHomMatrix& rMat ); + + static const B2DPoint& getEmptyPoint() + { + return (const B2DPoint&) ::basegfx::B2DTuple::getEmptyTuple(); + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + /** Transform B2DPoint by given transformation matrix. + + Since this is a Point, translational components of the + matrix are used. + */ + BASEGFX_DLLPUBLIC B2DPoint operator*( const B2DHomMatrix& rMat, const B2DPoint& rPoint ); +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POINT_B2DPOINT_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/point/b2ipoint.hxx b/include/basegfx/point/b2ipoint.hxx new file mode 100644 index 000000000000..33b225a2a36d --- /dev/null +++ b/include/basegfx/point/b2ipoint.hxx @@ -0,0 +1,117 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POINT_B2IPOINT_HXX +#define _BGFX_POINT_B2IPOINT_HXX + +#include <basegfx/tuple/b2ituple.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclaration + class B2DHomMatrix; + + /** Base Point class with two sal_Int32 values + + This class derives all operators and common handling for + a 2D data class from B2ITuple. All necessary extensions + which are special for points will be added here. + + @see B2ITuple + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B2IPoint : public ::basegfx::B2ITuple + { + public: + /** Create a 2D Point + + The point is initialized to (0, 0) + */ + B2IPoint() + : B2ITuple() + {} + + /** Create a 2D Point + + @param nX + This parameter is used to initialize the X-coordinate + of the 2D Point. + + @param nY + This parameter is used to initialize the Y-coordinate + of the 2D Point. + */ + B2IPoint(sal_Int32 nX, sal_Int32 nY) + : B2ITuple(nX, nY) + {} + + /** Create a copy of a 2D Point + + @param rPoint + The 2D Point which will be copied. + */ + B2IPoint(const B2IPoint& rPoint) + : B2ITuple(rPoint) + {} + + /** constructor with tuple to allow copy-constructing + from B2ITuple-based classes + */ + B2IPoint(const ::basegfx::B2ITuple& rTuple) + : B2ITuple(rTuple) + {} + + ~B2IPoint() + {} + + /** *=operator to allow usage from B2IPoint, too + */ + B2IPoint& operator*=( const B2IPoint& rPnt ) + { + mnX *= rPnt.mnX; + mnY *= rPnt.mnY; + return *this; + } + + /** *=operator to allow usage from B2IPoint, too + */ + B2IPoint& operator*=(sal_Int32 t) + { + mnX *= t; + mnY *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B2ITuple calculations + */ + B2IPoint& operator=( const ::basegfx::B2ITuple& rPoint ); + + /** Transform point by given transformation matrix. + + The translational components of the matrix are, in + contrast to B2DVector, applied. + */ + B2IPoint& operator*=( const ::basegfx::B2DHomMatrix& rMat ); + }; +} // end of namespace basegfx + +#endif /* _BGFX_POINT_B2IPOINT_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/point/b3dpoint.hxx b/include/basegfx/point/b3dpoint.hxx new file mode 100644 index 000000000000..391bc128b9fb --- /dev/null +++ b/include/basegfx/point/b3dpoint.hxx @@ -0,0 +1,145 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POINT_B3DPOINT_HXX +#define _BGFX_POINT_B3DPOINT_HXX + +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclaration + class B3DHomMatrix; + + /** Base Point class with three double values + + This class derives all operators and common handling for + a 3D data class from B3DTuple. All necessary extensions + which are special for points will be added here. + + @see B3DTuple + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B3DPoint : public ::basegfx::B3DTuple + { + public: + /** Create a 3D Point + + The point is initialized to (0.0, 0.0, 0.0) + */ + B3DPoint() + : B3DTuple() + {} + + /** Create a 3D Point + + @param fX + This parameter is used to initialize the X-coordinate + of the 3D Point. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 3D Point. + + @param fZ + This parameter is used to initialize the Z-coordinate + of the 3D Point. + */ + B3DPoint(double fX, double fY, double fZ) + : B3DTuple(fX, fY, fZ) + {} + + /** Create a copy of a 3D Point + + @param rVec + The 3D Point which will be copied. + */ + B3DPoint(const B3DPoint& rVec) + : B3DTuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B3DTuple-based classes + */ + B3DPoint(const ::basegfx::B3DTuple& rTuple) + : B3DTuple(rTuple) + {} + + ~B3DPoint() + {} + + /** *=operator to allow usage from B3DPoint, too + */ + B3DPoint& operator*=( const B3DPoint& rPnt ) + { + mfX *= rPnt.mfX; + mfY *= rPnt.mfY; + mfZ *= rPnt.mfZ; + return *this; + } + + /** *=operator to allow usage from B3DPoint, too + */ + B3DPoint& operator*=(double t) + { + mfX *= t; + mfY *= t; + mfZ *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B3DTuple calculations + */ + B3DPoint& operator=( const ::basegfx::B3DTuple& rVec ) + { + mfX = rVec.getX(); + mfY = rVec.getY(); + mfZ = rVec.getZ(); + return *this; + } + + /** Transform point by given transformation matrix. + + The translational components of the matrix are, in + contrast to B3DVector, applied. + */ + B3DPoint& operator*=( const ::basegfx::B3DHomMatrix& rMat ); + + static const B3DPoint& getEmptyPoint() + { + return (const B3DPoint&) ::basegfx::B3DTuple::getEmptyTuple(); + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + /** Transform B3DPoint by given transformation matrix. + + Since this is a Point, translational components of the + matrix are used. + */ + BASEGFX_DLLPUBLIC B3DPoint operator*( const B3DHomMatrix& rMat, const B3DPoint& rPoint ); + +} // end of namespace basegfx + +#endif /* _BGFX_POINT_B3DPOINT_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/point/b3ipoint.hxx b/include/basegfx/point/b3ipoint.hxx new file mode 100644 index 000000000000..e80514c13de2 --- /dev/null +++ b/include/basegfx/point/b3ipoint.hxx @@ -0,0 +1,129 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POINT_B3IPOINT_HXX +#define _BGFX_POINT_B3IPOINT_HXX + +#include <basegfx/tuple/b3ituple.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclaration + class B3DHomMatrix; + + /** Base Point class with three sal_Int32 values + + This class derives all operators and common handling for + a 3D data class from B3ITuple. All necessary extensions + which are special for points will be added here. + + @see B3ITuple + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B3IPoint : public ::basegfx::B3ITuple + { + public: + /** Create a 3D Point + + The point is initialized to (0, 0, 0) + */ + B3IPoint() + : B3ITuple() + {} + + /** Create a 3D Point + + @param nX + This parameter is used to initialize the X-coordinate + of the 3D Point. + + @param nY + This parameter is used to initialize the Y-coordinate + of the 3D Point. + + @param nZ + This parameter is used to initialize the Z-coordinate + of the 3D Point. + */ + B3IPoint(sal_Int32 nX, sal_Int32 nY, sal_Int32 nZ) + : B3ITuple(nX, nY, nZ) + {} + + /** Create a copy of a 3D Point + + @param rVec + The 3D Point which will be copied. + */ + B3IPoint(const B3IPoint& rVec) + : B3ITuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B3ITuple-based classes + */ + B3IPoint(const ::basegfx::B3ITuple& rTuple) + : B3ITuple(rTuple) + {} + + ~B3IPoint() + {} + + /** *=operator to allow usage from B3IPoint, too + */ + B3IPoint& operator*=( const B3IPoint& rPnt ) + { + mnX *= rPnt.mnX; + mnY *= rPnt.mnY; + mnZ *= rPnt.mnZ; + return *this; + } + + /** *=operator to allow usage from B3IPoint, too + */ + B3IPoint& operator*=(sal_Int32 t) + { + mnX *= t; + mnY *= t; + mnZ *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B3ITuple calculations + */ + B3IPoint& operator=( const ::basegfx::B3ITuple& rVec ) + { + mnX = rVec.getX(); + mnY = rVec.getY(); + mnZ = rVec.getZ(); + return *this; + } + + /** Transform point by given transformation matrix. + + The translational components of the matrix are, in + contrast to B3DVector, applied. + */ + B3IPoint& operator*=( const ::basegfx::B3DHomMatrix& rMat ); + }; +} // end of namespace basegfx + +#endif /* _BGFX_POINT_B3IPOINT_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dlinegeometry.hxx b/include/basegfx/polygon/b2dlinegeometry.hxx new file mode 100644 index 000000000000..934158f88a2f --- /dev/null +++ b/include/basegfx/polygon/b2dlinegeometry.hxx @@ -0,0 +1,141 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B2DLINEGEOMETRY_HXX +#define _BGFX_POLYGON_B2DLINEGEOMETRY_HXX + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <com/sun/star/drawing/LineCap.hpp> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + /** Create line start/end geometry element, mostly arrows and things like that. + + @param rCandidate + The polygon which needs to get that line ends and needs to have two points + at least. + + @param rArrow + The line start/end geometry. It is assumed that the tip is pointing + upwards. Result will be rotated and scaled to fit. + + @param bStart + describes if creation is for start or end of candidate. + + @param fWidth + defines the size of the element, it's describing the target width in X + of the arrow. + + @param fDockingPosition needs to be in [0.0 ..1.0] range, where 0.0 means + that the tip of the arrow will be aligned with the polygon start, 1.0 means + the bottom. The default of 0.5 describes a centered arrow. + + @param pConsumedLength + Using this parameter it is possible to get back how much from the candidate + geometry is overlapped by the created element (consumed). + + @param fCandidateLength + This should contain the length of rCandidate to allow work without + again calculating the length (which may be expensive with beziers). If 0.0 is + given, the length is calculated on demand. + + @return + The Line start and end polygon, correctly rotated and scaled + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon createAreaGeometryForLineStartEnd( + const B2DPolygon& rCandidate, + const B2DPolyPolygon& rArrow, + bool bStart, + double fWidth, + double fCandidateLength = 0.0, // 0.0 -> calculate self + double fDockingPosition = 0.5, // 0->top, 1->bottom + double* pConsumedLength = 0L); + + /** create filled polygon geometry for lines with a line width + + This method will create bezier based, fillable polygons which + will resample the curve if it was extended for the given half + line width. It will remove extrema positions from contained + bezier segments and get as close as possible and defined by + the given parameters to the ideal result. + + It will check edges for trivial bezier to avoid unnecessary + bezier polygons. Care is taken to produce the in-between + polygon points (the ones original on the source poygon) since + it has showed that without those, the raster converters leave + non-filled gaps. + + @param rCandidate + The source polygon defining the hairline polygon path + + @param fHalfLineWidth + The width of the line to one side + + @param eJoin + The LineJoin if the edges meeting in a point do not have a C1 + or C2 continuity + + @param eCap + The kind of cap, which is added to the line. + + @param fMaxAllowedAngle + Allows to hand over the maximum allowed angle between an edge and + it's control vectors. The smaller, the more subdivisions will be + needed to create the filled geometry. Allowed range is cropped to + [F_PI2 .. 0.01 * F_PI2]. + + @param fMaxPartOfEdge + Allows to influence from with relative length of a control vector + compared to it's edge a split is forced. The smaller, the more + subdivisions will be needed to create the filled geometry. Allowed + range is cropped to [1.0 .. 0.01] + + @praram fMiterMinimumAngle + The minimum wanted angle between two edges when edge rounding + is using miter. When an edge is smaller than this (tighter) + the usual fallback to bevel is used. Allowed range is cropped + to [F_PI .. 0.01 * F_PI]. + + @return + The PolyPolygon containing the geometry of the extended line by + it's line width. Contains bezier segments and edge roundings as + needed and defined. + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon createAreaGeometry( + const B2DPolygon& rCandidate, + double fHalfLineWidth, + B2DLineJoin eJoin = B2DLINEJOIN_ROUND, + com::sun::star::drawing::LineCap eCap = com::sun::star::drawing::LineCap_BUTT, + double fMaxAllowedAngle = (12.5 * F_PI180), + double fMaxPartOfEdge = 0.4, + double fMiterMinimumAngle = (15.0 * F_PI180)); + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DLINEGEOMETRY_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolygon.hxx b/include/basegfx/polygon/b2dpolygon.hxx new file mode 100644 index 000000000000..7c854fdc8a0e --- /dev/null +++ b/include/basegfx/polygon/b2dpolygon.hxx @@ -0,0 +1,230 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX +#define _BGFX_POLYGON_B2DPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations +class ImplB2DPolygon; + +namespace basegfx +{ + class B2DPolygon; + class B2DPoint; + class B2DVector; + class B2DHomMatrix; + class B2DCubicBezier; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC B2DPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB2DPolygon > ImplType; + + private: + // internal data. + ImplType mpPolygon; + + public: + /// diverse constructors + B2DPolygon(); + B2DPolygon(const B2DPolygon& rPolygon); + B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount); + ~B2DPolygon(); + + /// assignment operator + B2DPolygon& operator=(const B2DPolygon& rPolygon); + + /// unshare this polygon with all internally shared instances + void makeUnique(); + + /// compare operators + bool operator==(const B2DPolygon& rPolygon) const; + bool operator!=(const B2DPolygon& rPolygon) const; + + /// member count + sal_uInt32 count() const; + + /// Coordinate interface + basegfx::B2DPoint getB2DPoint(sal_uInt32 nIndex) const; + void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); + + /// Coordinate insert/append + void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount = 1); + void append(const basegfx::B2DPoint& rPoint, sal_uInt32 nCount); + void append(const basegfx::B2DPoint& rPoint); + void reserve(sal_uInt32 nCount); + + /// Basic ControlPoint interface + basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const; + basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const; + void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); + void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); + void setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext); + + /// ControlPoint resets + void resetPrevControlPoint(sal_uInt32 nIndex); + void resetNextControlPoint(sal_uInt32 nIndex); + void resetControlPoints(); + + /// Bezier segment append with control points. The current last polygon point is implicitly taken as start point. + void appendBezierSegment(const basegfx::B2DPoint& rNextControlPoint, const basegfx::B2DPoint& rPrevControlPoint, const basegfx::B2DPoint& rPoint); + + /// ControlPoint checks + bool areControlPointsUsed() const; + bool isPrevControlPointUsed(sal_uInt32 nIndex) const; + bool isNextControlPointUsed(sal_uInt32 nIndex) const; + B2VectorContinuity getContinuityInPoint(sal_uInt32 nIndex) const; + + /** bezier segment access + + This method also works when it is no bezier segment at all and will fill + the given B2DCubicBezier as needed. + In any case, the given B2DCubicBezier will be filled, if necessary with + the single start point (if no valid edge exists). + + @param nIndex + Index of the addressed edge's start point + + @param rTarget + The B2DCubicBezier to be filled. It's data WILL be changed. + */ + void getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const; + + /** Default adaptive subdivision access + + This method will return a default adapive subdivision of the polygon. + If the polygon does not contain any bezier curve segments, it will + just return itself. + + The subdivision is created on first request and buffered, so when using + this subdivision You have the guarantee for fast accesses for multiple + usages. It is intended for tooling usage for tasks which would be hard + to accomplish on bezier segments (e.g. isInEpsilonRange). + + The current default subdivision uses adaptiveSubdivideByCount with 9 + subdivisions which gives 10 edges and 11 points per segment and is + usually pretty usable for processing purposes. There is no parameter + passing here ATM but it may be changed on demand. If needed, a TYPE + and PARAMETER (both defaulted) may be added to allow for switching + between the different kinds of subdivisiond and passing them one + parameter. + + The lifetime of the buffered subdivision is based on polygon changes. + When changing the polygon, it will be flushed. It is buffered at the + refcounted implementation class, so it will survive copy by value and + combinations in PolyPolygons. + + @return + The default (and buffered) subdivision of this polygon. It may + be this polygon itself when it has no bezier segments. It is guaranteed + to have no more bezier segments + */ + B2DPolygon getDefaultAdaptiveSubdivision() const; + + /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon + + A polygon may have up to three ranges: + + (a) the range of the polygon points + (b) the range of the polygon points and control points + (c) the outer range of the subdivided bezier curve + + Ranges (a) and (c) are produced by tools::getRange(); resp. this + getB2DRange(). tools::getRangeWithControlPoints handles case (b). + + To get range (c) a simple solution would be to subdivide the polygon + and use getRange() on it. Since subdivision is expensive and decreases + the polygon quality, i added this new method. It will use a + methodology suggested by HDU. First, it gets the range (a). + Then it iterates over the bezier segments and for each it + first tests if the outer range of the bezier segment is already + contained in the result range. + + The subdivision itself uses getAllExtremumPositions() to only + calculate extremum points and to expand the result accordingly. + Thus it calculates maximal four extremum points on the bezier + segment, no split is used at all. + + @return + The outer range of the bezier curve/polygon + */ + B2DRange getB2DRange() const; + + /** append other 2D polygons + + The default (nIndex ==0 && nCount == 0) will append + the whole rPoly + + @param rPoly + The source polygon + + @param nIndex + The index to the first point of rPoly to append + + @param nCount + The number of points to append from rPoly, starting + from nIndex. If zero, as much as possibel is appended + */ + void append(const B2DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0); + + /// remove points + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + /// clear all points + void clear(); + + /// closed state interface + bool isClosed() const; + void setClosed(bool bNew); + + /// flip polygon direction + void flip(); + + /// test if Polygon has double points + bool hasDoublePoints() const; + + /// remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + /// apply transformation given in matrix form + void transform(const basegfx::B2DHomMatrix& rMatrix); + }; + + // typedef for a vector of B2DPolygons + typedef ::std::vector< B2DPolygon > B2DPolygonVector; + +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POLYGON_B2DPOLYGON_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolygonclipper.hxx b/include/basegfx/polygon/b2dpolygonclipper.hxx new file mode 100644 index 000000000000..197958e45a00 --- /dev/null +++ b/include/basegfx/polygon/b2dpolygonclipper.hxx @@ -0,0 +1,70 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONCLIPPER_HXX +#define _BGFX_POLYPOLYGON_B2DPOLYGONCLIPPER_HXX + +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B2DRange; + + namespace tools + { + // This method clips the given PolyPolygon against a horizontal or vertical axis (parallell to X or Y axis). The axis is + // defined by bParallelToXAxis (true -> it's parallel to the X-Axis of the coordinate system, else to the Y-Axis) and the + // fValueOnOtherAxis (gives the translation to the coordinate system axis). For example, when You want to define + // a clip axis parallel to X.Axis and 100 above it, use bParallelToXAxis = true and fValueOnOtherAxis = 100. + // The value bAboveAxis defines on which side the return value will be (true -> above X, right of Y). + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + BASEGFX_DLLPUBLIC B2DPolyPolygon clipPolyPolygonOnParallelAxis(const B2DPolyPolygon& rCandidate, bool bParallelToXAxis, bool bAboveAxis, double fValueOnOtherAxis, bool bStroke); + BASEGFX_DLLPUBLIC B2DPolyPolygon clipPolygonOnParallelAxis(const B2DPolygon& rCandidate, bool bParallelToXAxis, bool bAboveAxis, double fValueOnOtherAxis, bool bStroke); + + // Clip the given PolyPolygon against the given range. bInside defines if the result will contain the + // parts which are contained in the range or vice versa. + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + BASEGFX_DLLPUBLIC B2DPolyPolygon clipPolyPolygonOnRange(const B2DPolyPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke); + BASEGFX_DLLPUBLIC B2DPolyPolygon clipPolygonOnRange(const B2DPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke); + + // Clip given PolyPolygon against given clipping polygon. + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + // With stroke polygons, You get all line snippets inside rCip. + // With filled polygons, You get all PolyPolygon parts which were inside rClip. + // The switch bInside decides if the parts inside the clip polygon or outside shall be created. + // The clip polygon is always assumed closed, even when it's isClosed() is false. + BASEGFX_DLLPUBLIC B2DPolyPolygon clipPolyPolygonOnPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPolyPolygon& rClip, bool bInside, bool bStroke); + BASEGFX_DLLPUBLIC B2DPolyPolygon clipPolygonOnPolyPolygon(const B2DPolygon& rCandidate, const B2DPolyPolygon& rClip, bool bInside, bool bStroke); + + // clip the given polygon against the given range. the resulting polygon will always contain + // the inside parts which will always be interpreted as areas. the incoming polygon is expected + // to be a simple triangle list. the result is also a simple triangle list. + BASEGFX_DLLPUBLIC B2DPolygon clipTriangleListOnRange( const B2DPolygon& rCandidate, const B2DRange& rRange ); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B2DPOLYGONCLIPPER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolygoncutandtouch.hxx b/include/basegfx/polygon/b2dpolygoncutandtouch.hxx new file mode 100644 index 000000000000..05f8e0e0cb3a --- /dev/null +++ b/include/basegfx/polygon/b2dpolygoncutandtouch.hxx @@ -0,0 +1,58 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_CUTANDTOUCH_HXX +#define _BGFX_POLYGON_CUTANDTOUCH_HXX + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + // look for self-intersections and self-touches (points on an edge) in given polygon and add + // extra points there. Result will have no touches or intersections on an edge, only on points + BASEGFX_DLLPUBLIC B2DPolygon addPointsAtCutsAndTouches(const B2DPolygon& rCandidate); + + // look for polypolygon-intersections and polypolygon-touches (point of poly A on an edge of poly B) in given PolyPolygon and add + // extra points there. Result will have no touches or intersections between contained polygons on an edge, only on points. For + // convenience, the correction for self-intersections for each member polygon will be used, too. + // Changed: Self intersections are searched by default, but may be switched off by 2nd parameter. + BASEGFX_DLLPUBLIC B2DPolyPolygon addPointsAtCutsAndTouches(const B2DPolyPolygon& rCandidate, bool bSelfIntersections = true); + + // look for intersections of rCandidate with the edge from rStart to rEnd and add extra points there. + // Points are only added in the range of the edge, not on the endless vector. + BASEGFX_DLLPUBLIC B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPoint& rStart, const B2DPoint& rEnd); + + // look for intersections of rCandidate with the mask Polygon and add extra points there. + // The mask polygon is assumed to be closed, even when it's not explicitly. + BASEGFX_DLLPUBLIC B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPolyPolygon& rMask); + + } // end of namespace tools +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POLYGON_CUTANDTOUCH_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolygontools.hxx b/include/basegfx/polygon/b2dpolygontools.hxx new file mode 100644 index 000000000000..dce479847d65 --- /dev/null +++ b/include/basegfx/polygon/b2dpolygontools.hxx @@ -0,0 +1,442 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#define _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b3dpolygon.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B2DPolygon; + class B2DRange; + + namespace tools + { + // B2DPolygon tools + + // open/close with point add/remove and control point corrections + BASEGFX_DLLPUBLIC void openWithGeometryChange(B2DPolygon& rCandidate); + BASEGFX_DLLPUBLIC void closeWithGeometryChange(B2DPolygon& rCandidate); + + /** Check if given polygon is closed. + + This is kind of a 'classic' method to support old polygon + definitions. Those old polygon definitions define the + closed state of the polygon using identical start and + endpoints. This method corrects this (removes double + start/end points) and sets the Closed()-state of the + polygon correctly. + */ + BASEGFX_DLLPUBLIC void checkClosed(B2DPolygon& rCandidate); + + // Get successor and predecessor indices. Returning the same index means there + // is none. Same for successor. + BASEGFX_DLLPUBLIC sal_uInt32 getIndexOfPredecessor(sal_uInt32 nIndex, const B2DPolygon& rCandidate); + BASEGFX_DLLPUBLIC sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const B2DPolygon& rCandidate); + + // Get orientation of Polygon + BASEGFX_DLLPUBLIC B2VectorOrientation getOrientation(const B2DPolygon& rCandidate); + + // isInside tests for B2dPoint and other B2dPolygon. On border is not inside as long as + // not true is given in bWithBorder flag. + BASEGFX_DLLPUBLIC bool isInside(const B2DPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false); + BASEGFX_DLLPUBLIC bool isInside(const B2DPolygon& rCandidate, const B2DPolygon& rPolygon, bool bWithBorder = false); + + /** Get the range of a polygon + + This method creates the outer range of the subdivided bezier curve. + For detailed discussion see B2DPolygon::getB2DRange() + + @param rCandidate + The B2DPolygon eventually containing bezier segments + + @return + The outer range of the bezier curve + */ + BASEGFX_DLLPUBLIC B2DRange getRange(const B2DPolygon& rCandidate); + + // get signed area of polygon + BASEGFX_DLLPUBLIC double getSignedArea(const B2DPolygon& rCandidate); + + // get area of polygon + BASEGFX_DLLPUBLIC double getArea(const B2DPolygon& rCandidate); + + /** get length of polygon edge from point nIndex to nIndex + 1 */ + BASEGFX_DLLPUBLIC double getEdgeLength(const B2DPolygon& rCandidate, sal_uInt32 nIndex); + + /** get length of polygon */ + BASEGFX_DLLPUBLIC double getLength(const B2DPolygon& rCandidate); + + // get position on polygon for absolute given distance. If + // length is given, it is assumed the correct polygon length, if 0.0 it is calculated + // using getLength(...) + BASEGFX_DLLPUBLIC B2DPoint getPositionAbsolute(const B2DPolygon& rCandidate, double fDistance, double fLength = 0.0); + + // get position on polygon for relative given distance in range [0.0 .. 1.0]. If + // length is given, it is assumed the correct polygon length, if 0.0 it is calculated + // using getLength(...) + BASEGFX_DLLPUBLIC B2DPoint getPositionRelative(const B2DPolygon& rCandidate, double fDistance, double fLength = 0.0); + + // get a snippet from given polygon for absolute distances. The polygon is assumed + // to be opened (not closed). fFrom and fTo need to be in range [0.0 .. fLength], where + // fTo >= fFrom. If length is given, it is assumed the correct polygon length, + // if 0.0 it is calculated using getLength(...) + BASEGFX_DLLPUBLIC B2DPolygon getSnippetAbsolute(const B2DPolygon& rCandidate, double fFrom, double fTo, double fLength = 0.0); + + // Continuity check for point with given index + BASEGFX_DLLPUBLIC B2VectorContinuity getContinuityInPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex); + + // Subdivide all contained curves. Use distanceBound value if given. + BASEGFX_DLLPUBLIC B2DPolygon adaptiveSubdivideByDistance(const B2DPolygon& rCandidate, double fDistanceBound = 0.0); + + // Subdivide all contained curves. Use angleBound value if given. + BASEGFX_DLLPUBLIC B2DPolygon adaptiveSubdivideByAngle(const B2DPolygon& rCandidate, double fAngleBound = 0.0); + + // #i37443# Subdivide all contained curves. + BASEGFX_DLLPUBLIC B2DPolygon adaptiveSubdivideByCount(const B2DPolygon& rCandidate, sal_uInt32 nCount = 0L); + + // Definitions for the cut flags used from the findCut methods + typedef sal_uInt16 CutFlagValue; + + #define CUTFLAG_NONE (0x0000) + #define CUTFLAG_LINE (0x0001) + #define CUTFLAG_START1 (0x0002) + #define CUTFLAG_START2 (0x0004) + #define CUTFLAG_END1 (0x0008) + #define CUTFLAG_END2 (0x0010) + #define CUTFLAG_ALL (CUTFLAG_LINE|CUTFLAG_START1|CUTFLAG_START2|CUTFLAG_END1|CUTFLAG_END2) + #define CUTFLAG_DEFAULT (CUTFLAG_LINE|CUTFLAG_START2|CUTFLAG_END2) + + // This version works with two points and vectors to define the + // edges for the cut test. + BASEGFX_DLLPUBLIC CutFlagValue findCut( + const B2DPoint& rEdge1Start, const B2DVector& rEdge1Delta, + const B2DPoint& rEdge2Start, const B2DVector& rEdge2Delta, + CutFlagValue aCutFlags = CUTFLAG_DEFAULT, + double* pCut1 = 0L, double* pCut2 = 0L); + + // test if point is on the given edge in range ]0.0..1.0[ without + // the start/end points. If so, return true and put the parameter + // value in pCut (if provided) + BASEGFX_DLLPUBLIC bool isPointOnEdge( + const B2DPoint& rPoint, + const B2DPoint& rEdgeStart, + const B2DVector& rEdgeDelta, + double* pCut = 0L); + + /** Apply given LineDashing to given polygon + + This method is used to cut down line polygons to the needed + pieces when a dashing needs to be applied. + It is now capable of keeping contained bezier segments. + It is also capable of delivering line and non-line portions + depending on what target polygons You provide. This is useful + e.g. for dashed lines with two colors. + If the last and the first snippet in one of the results have + a common start/end ppoint, they will be merged to achieve as + view as needed result line snippets. This is also relevant for + further processing the results. + + @param rCandidate + The polygon based on which the snippets will be created. + + @param rDotDashArray + The line pattern given as array of length values + + @param pLineTarget + The target for line snippets, e.g. the first entry will be + a line segment with length rDotDashArray[0]. The given + polygon will be emptied as preparation. + + @param pGapTarget + The target for gap snippets, e.g. the first entry will be + a line segment with length rDotDashArray[1]. The given + polygon will be emptied as preparation. + + @param fFullDashDotLen + The sumed-up length of the rDotDashArray. If zero, it will + be calculated internally. + */ + BASEGFX_DLLPUBLIC void applyLineDashing( + const B2DPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B2DPolyPolygon* pLineTarget, + B2DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + // test if point is inside epsilon-range around an edge defined + // by the two given points. Can be used for HitTesting. The epsilon-range + // is defined to be the rectangle centered to the given edge, using height + // 2 x fDistance, and the circle around both points with radius fDistance. + BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPoint& rEdgeStart, const B2DPoint& rEdgeEnd, const B2DPoint& rTestPosition, double fDistance); + + // test if point is inside epsilon-range around the given Polygon. Can be used + // for HitTesting. The epsilon-range is defined to be the rectangle centered + // to the given edge, using height 2 x fDistance, and the circle around both points + // with radius fDistance. + BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance); + + /** Create a polygon from a rectangle. + + @param rRect + The rectangle which describes the polygon size + + @param fRadiusX + @param fRadiusY + Radius of the edge rounding, relative to the rectangle size. 0.0 means no + rounding, 1.0 will lead to an ellipse + */ + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromRect( const B2DRectangle& rRect, double fRadiusX, double fRadiusY ); + + /** Create a polygon from a rectangle. + */ + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromRect( const B2DRectangle& rRect ); + + /** Create the unit polygon + */ + BASEGFX_DLLPUBLIC B2DPolygon createUnitPolygon(); + + /** Create a circle polygon with given radius. + + This method creates a circle approximation consisting of + four cubic bezier segments, which approximate the given + circle with an error of less than 0.5 percent. + + @param rCenter + Center point of the circle + + @param fRadius + Radius of the circle + */ + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromCircle( const B2DPoint& rCenter, double fRadius ); + + /// create half circle centered on (0,0) from [0 .. F_PI] + B2DPolygon createHalfUnitCircle(); + + /** create a polygon which describes the unit circle and close it + + @param nStartQuadrant + To be able to rebuild the old behaviour where the circles started at bottom, + this parameter is used. Default is 0 which is the first quadrant and the + polygon's start point will be the rightmost one. When using e.g. 1, the + first created quadrant will start at the YMax-position (with Y down on screens, + this is the lowest one). This is needed since when lines are dashed, toe old + geometry started at bottom point, else it would look different. + */ + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromUnitCircle(sal_uInt32 nStartQuadrant = 0); + + /** Create an ellipse polygon with given radii. + + This method creates an ellipse approximation consisting of + four cubic bezier segments, which approximate the given + ellipse with an error of less than 0.5 percent. + + @param rCenter + Center point of the circle + + @param fRadiusX + Radius of the ellipse in X direction + + @param fRadiusY + Radius of the ellipse in Y direction + */ + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY ); + + /** Create an unit ellipse polygon with the given angles, from start to end + */ + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromEllipseSegment( const B2DPoint& rCenter, double fRadiusX, double fRadiusY, double fStart, double fEnd ); + + BASEGFX_DLLPUBLIC B2DPolygon createPolygonFromUnitEllipseSegment( double fStart, double fEnd ); + + /** Predicate whether a given polygon is a rectangle. + + @param rPoly + Polygon to check + + @return true, if the polygon describes a rectangle + (polygon is closed, and the points are either cw or ccw + enumerations of a rectangle's vertices). Note that + intermediate points and duplicate points are ignored. + */ + BASEGFX_DLLPUBLIC bool isRectangle( const B2DPolygon& rPoly ); + + // create 3d polygon from given 2d polygon. The given fZCoordinate is used to expand the + // third coordinate. + BASEGFX_DLLPUBLIC B3DPolygon createB3DPolygonFromB2DPolygon(const B2DPolygon& rCandidate, double fZCoordinate = 0.0); + + // create 2d PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given + // matrix and the resulting x,y is used to form the new polygon. + BASEGFX_DLLPUBLIC B2DPolygon createB2DPolygonFromB3DPolygon(const B3DPolygon& rCandidate, const B3DHomMatrix& rMat); + + // calculate the smallest distance to given edge and return. The relative position on the edge is returned in Cut. + // That position is in the range [0.0 .. 1.0] and the returned distance is adapted accordingly to the start or end + // point of the edge + BASEGFX_DLLPUBLIC double getSmallestDistancePointToEdge(const B2DPoint& rPointA, const B2DPoint& rPointB, const B2DPoint& rTestPoint, double& rCut); + + // for each contained edge calculate the smallest distance. Return the index to the smallest + // edge in rEdgeIndex. The relative position on the edge is returned in rCut. + // If nothing was found (e.g. empty input plygon), DBL_MAX is returned. + BASEGFX_DLLPUBLIC double getSmallestDistancePointToPolygon(const B2DPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rEdgeIndex, double& rCut); + + // distort single point. rOriginal describes the original range, where the given points describe the distorted corresponding points. + BASEGFX_DLLPUBLIC B2DPoint distort(const B2DPoint& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); + + // distort polygon. rOriginal describes the original range, where the given points describe the distorted corresponding points. + BASEGFX_DLLPUBLIC B2DPolygon distort(const B2DPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); + + // expand all segments (which are not yet) to curve segments. This is done with setting the control + // vectors on the 1/3 resp. 2/3 distances on each segment. + BASEGFX_DLLPUBLIC B2DPolygon expandToCurve(const B2DPolygon& rCandidate); + + // expand given segment to curve segment. This is done with setting the control + // vectors on the 1/3 resp. 2/3 distances. The return value describes if a change took place. + BASEGFX_DLLPUBLIC bool expandToCurveInPoint(B2DPolygon& rCandidate, sal_uInt32 nIndex); + + // set continuity for given index. If not a curve, nothing will change. Non-curve points are not changed, too. + // The return value describes if a change took place. + BASEGFX_DLLPUBLIC bool setContinuityInPoint(B2DPolygon& rCandidate, sal_uInt32 nIndex, B2VectorContinuity eContinuity); + + // test if polygon contains neutral points. A neutral point is one whos orientation is neutral + // e.g. positioned on the edge of it's predecessor and successor + BASEGFX_DLLPUBLIC bool hasNeutralPoints(const B2DPolygon& rCandidate); + + // remove neutral points. A neutral point is one whos orientation is neutral + // e.g. positioned on the edge of it's predecessor and successor + BASEGFX_DLLPUBLIC B2DPolygon removeNeutralPoints(const B2DPolygon& rCandidate); + + // tests if polygon is convex + BASEGFX_DLLPUBLIC bool isConvex(const B2DPolygon& rCandidate); + + // calculates the orientation at edge nIndex + BASEGFX_DLLPUBLIC B2VectorOrientation getOrientationForIndex(const B2DPolygon& rCandidate, sal_uInt32 nIndex); + + // calculates if given point is on given line, taking care of the numerical epsilon + BASEGFX_DLLPUBLIC bool isPointOnLine(const B2DPoint& rStart, const B2DPoint& rEnd, const B2DPoint& rCandidate, bool bWithPoints = false); + + // calculates if given point is on given polygon, taking care of the numerical epsilon. Uses + // isPointOnLine internally + BASEGFX_DLLPUBLIC bool isPointOnPolygon(const B2DPolygon& rCandidate, const B2DPoint& rPoint, bool bWithPoints = true); + + // test if candidate is inside triangle + BASEGFX_DLLPUBLIC bool isPointInTriangle(const B2DPoint& rA, const B2DPoint& rB, const B2DPoint& rC, const B2DPoint& rCandidate, bool bWithBorder = false); + + // test if candidateA and candidateB are on the same side of the given line + BASEGFX_DLLPUBLIC bool arePointsOnSameSideOfLine(const B2DPoint& rStart, const B2DPoint& rEnd, const B2DPoint& rCandidateA, const B2DPoint& rCandidateB, bool bWithLine = false); + + // add triangles for given rCandidate to rTarget. For each triangle, 3 points will be added to rCandidate. + // All triangles will go from the start point of rCandidate to two consecutive points, building (rCandidate.count() - 2) + // triangles. + BASEGFX_DLLPUBLIC void addTriangleFan(const B2DPolygon& rCandidate, B2DPolygon& rTarget); + + // grow for polygon. Move all geometry in each point in the direction of the normal in that point + // with the given amount. Value may be negative. + BASEGFX_DLLPUBLIC B2DPolygon growInNormalDirection(const B2DPolygon& rCandidate, double fValue); + + // force all sub-polygons to a point count of nSegments + BASEGFX_DLLPUBLIC B2DPolygon reSegmentPolygon(const B2DPolygon& rCandidate, sal_uInt32 nSegments); + + // create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same + // organisation, e.g. same amount of points + BASEGFX_DLLPUBLIC B2DPolygon interpolate(const B2DPolygon& rOld1, const B2DPolygon& rOld2, double t); + + // #i76891# Try to remove existing curve segments if they are simply edges + BASEGFX_DLLPUBLIC B2DPolygon simplifyCurveSegments(const B2DPolygon& rCandidate); + + // makes the given indexed point the new polygon start point. To do that, the points in the + // polygon will be rotated. This is only valid for closed polygons, for non-closed ones + // an assertion will be triggered + BASEGFX_DLLPUBLIC B2DPolygon makeStartPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndexOfNewStatPoint); + + /** create edges of given length along given B2DPolygon + + @param rCandidate + The polygon to move along. Points at the given polygon are created, starting + at position fStart and stopping at less or equal to fEnd. The closed state is + preserved. + The polygon is subdivided if curve segments are included. That subdivision is the base + for the newly created points. + If the source is closed, the indirectly existing last edge may NOT have the + given length. + If the source is open, all edges will have the given length. You may use the last + point of the original when You want to add the last edge Yourself. + + @param fLength + The length of the created edges. If less or equal zero, an empty polygon is returned. + + @param fStart + The start distance for the first to be generated point. Use 0.0 to get the + original start point. Negative values are truncated to 0.0. + + @param fEnd + The maximum distance for the last point. No more points behind this distance will be created. + Use 0.0 to proccess the whole polygon. Negative values are truncated to 0.0. It also + needs to be more or equal to fStart, else it is truncated to fStart. + + @return + The newly created polygon + */ + BASEGFX_DLLPUBLIC B2DPolygon createEdgesOfGivenLength(const B2DPolygon& rCandidate, double fLength, double fStart = 0.0, double fEnd = 0.0); + + /** Create Waveline along given polygon + The implementation is based on createEdgesOfGivenLength and creates a curve + segment with the given dimensions for each created line segment. The polygon + is treated as if opened (closed state will be ignored) and only for whole + edges a curve segment will be created (no rest handling) + + @param rCandidate + The polygon along which the waveline will be created + + @param fWaveWidth + The length of a single waveline curve segment + + @param fgWaveHeight + The height of the waveline (amplitude) + */ + BASEGFX_DLLPUBLIC B2DPolygon createWaveline(const B2DPolygon& rCandidate, double fWaveWidth, double fWaveHeight); + + /** snap some polygon coordinates to discrete coordinates + + This method allows to snap some polygon points to discrete (integer) values + which equals e.g. a snap to discrete coordinates. It will snap points of + horizontal and vertical edges + + @param rCandidate + The source polygon + + @return + The modified version of the source polygon + */ + BASEGFX_DLLPUBLIC B2DPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolygon& rCandidate); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolygontriangulator.hxx b/include/basegfx/polygon/b2dpolygontriangulator.hxx new file mode 100644 index 000000000000..5af34ae1ecd2 --- /dev/null +++ b/include/basegfx/polygon/b2dpolygontriangulator.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 . + */ + +#ifndef _BGFX_POLYGON_B2DPOLYGONTRIANGULATOR_HXX +#define _BGFX_POLYGON_B2DPOLYGONTRIANGULATOR_HXX + +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace triangulator + { + // triangulate given polygon + BASEGFX_DLLPUBLIC ::basegfx::B2DPolygon triangulate(const ::basegfx::B2DPolygon& rCandidate); + + // triangulate given PolyPolygon + BASEGFX_DLLPUBLIC ::basegfx::B2DPolygon triangulate(const ::basegfx::B2DPolyPolygon& rCandidate); + + } // end of namespace triangulator +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DPOLYGONTRIANGULATOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolypolygon.hxx b/include/basegfx/polygon/b2dpolypolygon.hxx new file mode 100644 index 000000000000..cd22644ab8ce --- /dev/null +++ b/include/basegfx/polygon/b2dpolypolygon.hxx @@ -0,0 +1,137 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/basegfxdllapi.h> +#include <vector> + +// predeclarations +class ImplB2DPolyPolygon; + +namespace basegfx +{ + class B2DPolygon; + class B2DHomMatrix; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC B2DPolyPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB2DPolyPolygon > ImplType; + + private: + ImplType mpPolyPolygon; + + public: + B2DPolyPolygon(); + B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon); + explicit B2DPolyPolygon(const B2DPolygon& rPolygon); + ~B2DPolyPolygon(); + + // assignment operator + B2DPolyPolygon& operator=(const B2DPolyPolygon& rPolyPolygon); + + /// unshare this poly-polygon (and all included polygons) with all internally shared instances + void makeUnique(); + + // compare operators + bool operator==(const B2DPolyPolygon& rPolyPolygon) const; + bool operator!=(const B2DPolyPolygon& rPolyPolygon) const; + + // polygon interface + sal_uInt32 count() const; + + B2DPolygon getB2DPolygon(sal_uInt32 nIndex) const; + void setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon); + + // test for curve + bool areControlPointsUsed() const; + + // insert/append single polygon + void insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount = 1); + void append(const B2DPolygon& rPolygon, sal_uInt32 nCount = 1); + + /** Default adaptive subdivision access + + For details refer to B2DPolygon::getDefaultAdaptiveSubdivision() + + @return + The default subdivision of this polygon + */ + B2DPolyPolygon getDefaultAdaptiveSubdivision() const; + + /** Get the B2DRange (Rectangle dimensions) of this B2DPolyPolygon + + For details refer to B2DPolygon::getB2DRange() + + @return + The outer range of the bezier curve/polygon + */ + B2DRange getB2DRange() const; + + // insert/append multiple polygons + void insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon); + void append(const B2DPolyPolygon& rPolyPolygon); + + // remove + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + // reset to empty state + void clear(); + + // closed state + bool isClosed() const; + void setClosed(bool bNew); + + // flip polygon direction + void flip(); + + // test if PolyPolygon has double points + bool hasDoublePoints() const; + + // remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + // apply transformation given in matrix form to the polygon + void transform(const basegfx::B2DHomMatrix& rMatrix); + + // polygon iterators (same iterator validity conditions as for vector) + const B2DPolygon* begin() const; + const B2DPolygon* end() const; + B2DPolygon* begin(); + B2DPolygon* end(); + }; + + // typedef for a vector of B2DPolyPolygons + typedef ::std::vector< B2DPolyPolygon > B2DPolyPolygonVector; + +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGON_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolypolygoncutter.hxx b/include/basegfx/polygon/b2dpolypolygoncutter.hxx new file mode 100644 index 000000000000..31bd8b6279f9 --- /dev/null +++ b/include/basegfx/polygon/b2dpolypolygoncutter.hxx @@ -0,0 +1,153 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGONCUTTER_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGONCUTTER_HXX + +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + /** Solve all crossovers (aka self-intersections) in a polyPolygon. + + This re-layouts all contained polygons so that the result + will contain only non-cutting polygons. For that reason, + points will be added at crossover and touch points and the + single Polygons may be re-combined. The orientations of + the contained polygons in not changed but used as + topological information. Self crossovers of the contained + sub-polygons are implicitely handled, but to not lose the + topological information, it may be necessary to remove + self-intersections of the contained sub-polygons in a + preparing step and to explicitly correct their + orientations. + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon solveCrossovers(const B2DPolyPolygon& rCandidate); + + /** Solve all crossovers (aka self-intersections) in a Polygon + + Same as above, but for single polygons. Result will be + free of self-intersections. When result contains multiple + polygons, it may be necessary to rearrange their + orientations since holes may have been created (use + correctOrientations eventually). + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon solveCrossovers(const B2DPolygon& rCandidate); + + /** Strip neutral polygons from PolyPolygon. + + Neutral polygons are ones who's orientation is neutral, so + normally they have no volume -> just closed paths. A + polygon with the same positive and negative oriented + volume is also neutral, so this may not be wanted. It is + safe to call with self-intersection-free polygons, though + (that's where it's mostly used). + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon stripNeutralPolygons(const B2DPolyPolygon& rCandidate); + + /** Remove unnecessary/non-displayed polygons. + + Works only correct with self-intersection-free + polygons. For each polygon, the depth for the PolyPolygon + is calculated. The orientation is used to identify holes. + Start value for holes is -1, for polygons it's zero. Ech + time a polygon is contained in another one, it's depth is + increased when inside a polygon, decreased when inside a + hole. The result is a depth which e.g. is -1 for holes + outside everything, 1 for a polygon covered by another + polygon and zero for e.g. holes in a polygon or polygons + outside everythig else. In the 2nd step, all polygons + with depth other than zero are removed. If bKeepAboveZero + is used, all polygons < 1 are removed. The bKeepAboveZero + mode is useful for clipping, e.g. just append one polygon + to another and use this mode -> only parts where two + polygons overlapped will be kept. In combination with + correct orientation of the input orientations and the + SolveCrossover calls this can be combined for logical + polygon operations or polygon clipping. + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon& rCandidate, bool bKeepAboveZero = false); + + /** Emulate nonzero winding rule filling. + + Geometrically convert PolyPolygons which are proposed to + use nonzero fill rule to a representation where evenodd + paint will give the same result. To do this all + intersections and self-intersections get solved (the + polygons will be rearranged if needed). Then all polygons + which are inside another one with the same orientation get + deleted + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon createNonzeroConform(const B2DPolyPolygon& rCandidate); + + // For convenience: The four basic operations OR, XOR, AND and DIFF for + // two PolyPolygons. These are combinations of the above methods. To not be forced + // to do evtl. already done preparations twice, You have to do the operations Yourself. + // + // A source preparation consists of preparing it to be seen as XOR-Rule PolyPolygon, + // so it is freed of intersections, self-intersections and the orientations are corrected. + // Important is that it will define the same areas as before, but is intersection-free. + // As an example think about a single polygon looping in itself and having holes. To + // topologically correctly handle this, it is necessary to remove all intersections and + // to correct the orientations. The orientation of the isolated holes e.g. will be negative. + // Topologically it is necessary to prepare each polygon which is seen as entity. It is + // not sufficient just to concatenate them and prepare the result, this may be topologically + // different since the simple concatenation will be seen as XOR. To work correctly, You + // may need to OR those polygons. + + /// prep for ops - solve self-intersections and intersections, remove neutral parts and check orientations. + BASEGFX_DLLPUBLIC B2DPolyPolygon prepareForPolygonOperation(const B2DPolygon& rCandidate); + /// prep for ops - solve self-intersections and intersections, remove neutral parts and check orientations. + BASEGFX_DLLPUBLIC B2DPolyPolygon prepareForPolygonOperation(const B2DPolyPolygon& rCandidate); + + /// OR: Return all areas where CandidateA or CandidateB exist + BASEGFX_DLLPUBLIC B2DPolyPolygon solvePolygonOperationOr(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + /// XOR: Return all areas where CandidateA or CandidateB exist, but not both + BASEGFX_DLLPUBLIC B2DPolyPolygon solvePolygonOperationXor(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + /// AND: Return all areas where CandidateA and CandidateB exist + BASEGFX_DLLPUBLIC B2DPolyPolygon solvePolygonOperationAnd(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + /// DIFF: Return all areas where CandidateA is not covered by CandidateB (cut B out of A) + BASEGFX_DLLPUBLIC B2DPolyPolygon solvePolygonOperationDiff(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + /** merge all single PolyPolygons to a single, OR-ed PolyPolygon + + @param rInput + The source PolyPolygons + + @return A single PolyPolygon containing the Or-merged result + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon mergeToSinglePolyPolygon(const B2DPolyPolygonVector& rInput); + + } // end of namespace tools +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGONCUTTER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolypolygonfillrule.hxx b/include/basegfx/polygon/b2dpolypolygonfillrule.hxx new file mode 100644 index 000000000000..390dd9bac9f0 --- /dev/null +++ b/include/basegfx/polygon/b2dpolypolygonfillrule.hxx @@ -0,0 +1,54 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGONFILLRULE_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGONFILLRULE_HXX + +#include <sal/types.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + /** Fill rule to use for poly-polygon filling. + + The fill rule determines which areas are inside, and which are + outside the poly-polygon. + */ + enum FillRule + { + /** Areas, for which a scanline has crossed an odd number of + vertices, are regarded 'inside', the remainder 'outside' + of the poly-polygon. + */ + FillRule_EVEN_ODD, + + /** For each edge a scanline crosses, a current winding number + is updated. Downward edges count +1, upward edges count + -1. If the total accumulated winding number for one area + is not zero, this area is regarded 'inside', otherwise, + 'outside'. + */ + FillRule_NONZERO_WINDING_NUMBER + }; +} + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGONFILLRULE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dpolypolygontools.hxx b/include/basegfx/polygon/b2dpolypolygontools.hxx new file mode 100644 index 000000000000..29ae3e042133 --- /dev/null +++ b/include/basegfx/polygon/b2dpolypolygontools.hxx @@ -0,0 +1,236 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX +#define _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b3dpolypolygon.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B2DPolyPolygon; + class B2DRange; + + namespace tools + { + // B2DPolyPolygon tools + + // Check and evtl. correct orientations of all contained Polygons so that + // the orientations of contained polygons will variate to express areas and + // holes + BASEGFX_DLLPUBLIC B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate); + + // make sure polygon with index 0L is not a hole. This may evtl. change the + // sequence of polygons, but allows to use polygon with index 0L to + // get the correct normal for the whole polyPolygon + BASEGFX_DLLPUBLIC B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate); + + // Subdivide all contained curves. Use distanceBound value if given. + BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound = 0.0); + + // Subdivide all contained curves. Use distanceBound value if given. Else, a convenient one + // is created. + BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound = 0.0); + + // Subdivide all contained curves. Use nCount divisions if given. Else, a convenient one + // is created. + BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount = 0L); + + // isInside test for B2dPoint. On border is not inside as long as not true is given + // in bWithBorder flag. It is assumed that the orientations of the given polygon are correct. + BASEGFX_DLLPUBLIC bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false); + + /** Get the range of a polyPolygon + + For detailed description look at getRange(const B2DPolygon&). + This method just expands by the range of every sub-Polygon. + + @param rCandidate + The B2DPolyPolygon eventually containing bezier segments + + @return + The outer range of the polygon + */ + BASEGFX_DLLPUBLIC B2DRange getRange(const B2DPolyPolygon& rCandidate); + + /** Apply given LineDashing to given polyPolygon + + For a description see applyLineDashing in b2dpolygontoos.hxx + */ + BASEGFX_DLLPUBLIC void applyLineDashing( + const B2DPolyPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B2DPolyPolygon* pLineTarget, + B2DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + // test if point is inside epsilon-range around the given PolyPolygon. Can be used + // for HitTesting. The epsilon-range is defined to be the tube around the PolyPolygon + // with distance fDistance and rounded edges (start and end point). + BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance); + + /** Read poly-polygon from SVG. + + This function imports a poly-polygon from an SVG-D + attribute. + + @param o_rPolyPoly + The output poly-polygon + + @param rSvgDAttribute + A valid SVG-D attribute string + + @param rWrongPositionAfterZ + Indicates wheter the generator interprets wrongly + the position in the path after Z or z elements + https://bugs.freedesktop.org/show_bug.cgi?id=47406 + + @return true, if the string was successfully parsed + */ + BASEGFX_DLLPUBLIC bool importFromSvgD( B2DPolyPolygon& o_rPolyPoly, + const OUString& rSvgDAttribute, bool bWrongPositionAfterZ = false ); + + /** Read poly-polygon from SVG. + + This function imports a poly-polygon from an SVG points + attribute (a plain list of coordinate pairs). + + @param o_rPoly + The output polygon. Note that svg:points can only define a + single polygon + + @param rSvgPointsAttribute + A valid SVG points attribute string + + @return true, if the string was successfully parsed + */ + BASEGFX_DLLPUBLIC bool importFromSvgPoints( B2DPolygon& o_rPoly, + const OUString& rSvgPointsAttribute ); + + + // grow for polyPolygon. Move all geometry in each point in the direction of the normal in that point + // with the given amount. Value may be negative. + BASEGFX_DLLPUBLIC B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue); + + // This method will correct a pair of polyPolygons where the goal is to keep same point count + // to allow direct point association and also to remove self-intersections produced by shrinks. + // This method will eventually change both polyPolygons to reach that goal because there are cases + // where it is necessary to add new cut points to the original + BASEGFX_DLLPUBLIC void correctGrowShrinkPolygonPair(B2DPolyPolygon& rOriginal, B2DPolyPolygon& rGrown); + + // force all sub-polygons to a point count of nSegments + BASEGFX_DLLPUBLIC B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments); + + // create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same + // organisation, e.g. same amount of polygons + BASEGFX_DLLPUBLIC B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t); + + // create 3d PolyPolygon from given 2d PolyPolygon. The given fZCoordinate is used to expand the + // third coordinate. + BASEGFX_DLLPUBLIC B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate = 0.0); + + // create 2d PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given + // matrix and the resulting x,y is used to form the new polygon. + BASEGFX_DLLPUBLIC B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat); + + // for each contained edge in each contained polygon calculate the smallest distance. Return the index to the smallest + // edge in rEdgeIndex and the index to the polygon in rPolygonIndex. The relative position on the edge is returned in rCut. + // If nothing was found (e.g. empty input plygon), DBL_MAX is returned. + BASEGFX_DLLPUBLIC double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut); + + // distort PolyPolygon. rOriginal describes the original range, where the given points describe the distorted + // corresponding points. + BASEGFX_DLLPUBLIC B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); + + // expand all segments (which are not yet) to curve segments. This is done with setting the control + // vectors on the 1/3 resp. 2/3 distances on each segment. + BASEGFX_DLLPUBLIC B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate); + + /** Predicate whether a given poly-polygon is a rectangle. + + @param rPoly + PolyPolygon to check + + @return true, if the poly-polygon describes a rectangle + (contains exactly one polygon, polygon is closed, and the + points are either cw or ccw enumerations of a rectangle's + vertices). Note that intermediate points and duplicate + points are ignored. + */ + BASEGFX_DLLPUBLIC bool isRectangle( const B2DPolyPolygon& rPoly ); + + /** Export poly-polygon to SVG. + + This function exports a poly-polygon into an SVG-D + statement. Currently, output of relative point sequences + is not yet supported (might cause slightly larger output) + + @param rPolyPoly + The poly-polygon to export + + @param bUseRelativeCoordinates + When true, all coordinate values are exported as relative + to the current position. This tends to save some space, + since fewer digits needs to be written. + + @param bDetectQuadraticBeziers + When true, the export tries to detect cubic bezier + segments in the input polygon, which can be represented by + quadratic bezier segments. Note that the generated string + causes versions prior to OOo2.0 to crash. + + @return the generated SVG-D statement (the XML d attribute + value alone, without any "<path ...>" or "d="...") + */ + BASEGFX_DLLPUBLIC OUString exportToSvgD( const B2DPolyPolygon& rPolyPoly, + bool bUseRelativeCoordinates=true, + bool bDetectQuadraticBeziers=true ); + + // #i76891# Try to remove existing curve segments if they are simply edges + BASEGFX_DLLPUBLIC B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate); + + /** snap some polygon coordinates to discrete coordinates + + This method allows to snap some polygon points to discrete (integer) values + which equals e.g. a snap to discrete coordinates. It will snap points of + horizontal and vertical edges + + @param rCandidate + The source polygon + + @return + The modified version of the source polygon + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b2dtrapezoid.hxx b/include/basegfx/polygon/b2dtrapezoid.hxx new file mode 100644 index 000000000000..43ee9fb37f6c --- /dev/null +++ b/include/basegfx/polygon/b2dtrapezoid.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 . + */ + +#ifndef _BGFX_POLYGON_B2DTRAPEZOID_HXX +#define _BGFX_POLYGON_B2DTRAPEZOID_HXX + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // class to hold a single trapezoid + class BASEGFX_DLLPUBLIC B2DTrapezoid + { + private: + // Geometry data. YValues are down-oriented, this means bottom should + // be bigger than top to be below it. The constructor implementation + // guarantees: + // + // - mfBottomY >= mfTopY + // - mfTopXRight >= mfTopXLeft + // - mfBottomXRight >= mfBottomXLeft + double mfTopXLeft; + double mfTopXRight; + double mfTopY; + double mfBottomXLeft; + double mfBottomXRight; + double mfBottomY; + + public: + // constructor + B2DTrapezoid( + const double& rfTopXLeft, + const double& rfTopXRight, + const double& rfTopY, + const double& rfBottomXLeft, + const double& rfBottomXRight, + const double& rfBottomY); + + // data read access + const double& getTopXLeft() const { return mfTopXLeft; } + const double& getTopXRight() const { return mfTopXRight; } + const double& getTopY() const { return mfTopY; } + const double& getBottomXLeft() const { return mfBottomXLeft; } + const double& getBottomXRight() const { return mfBottomXRight; } + const double& getBottomY() const { return mfBottomY; } + + // convenience method to get content as Polygon + B2DPolygon getB2DPolygon() const; + }; + + typedef ::std::vector< B2DTrapezoid > B2DTrapezoidVector; + +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + // convert SourcePolyPolygon to trapezoids. The trapezoids will be appended to + // ro_Result. ro_Result will not be cleared. If SourcePolyPolygon contains curves, + // it's default AdaptiveSubdivision will be used. + // CAUTION: Trapezoids are oreintation-dependent in the sense that the upper and lower + // lines have to be parallel to the X-Axis, thus this subdivision is NOT simply usable + // for primitive decompositions. To use it, the shear and rotate parts of the + // involved transformations HAVE to be taken into account. + BASEGFX_DLLPUBLIC void trapezoidSubdivide( + B2DTrapezoidVector& ro_Result, + const B2DPolyPolygon& rSourcePolyPolygon); + + // directly create trapezoids from given edge. Depending on the given geometry, + // none up to three trapezoids will be created + BASEGFX_DLLPUBLIC void createLineTrapezoidFromEdge( + B2DTrapezoidVector& ro_Result, + const B2DPoint& rPointA, + const B2DPoint& rPointB, + double fLineWidth = 1.0); + + // create trapezoids for all edges of the given polygon. The closed state of + // the polygon is taken into account. If curves are contaned, the default + // AdaptiveSubdivision will be used. + BASEGFX_DLLPUBLIC void createLineTrapezoidFromB2DPolygon( + B2DTrapezoidVector& ro_Result, + const B2DPolygon& rPolygon, + double fLineWidth = 1.0); + + // create trapezoids for all edges of the given polyPolygon. The closed state of + // the PolyPolygon is taken into account. If curves are contaned, the default + // AdaptiveSubdivision will be used. + BASEGFX_DLLPUBLIC void createLineTrapezoidFromB2DPolyPolygon( + B2DTrapezoidVector& ro_Result, + const B2DPolyPolygon& rPolyPolygon, + double fLineWidth = 1.0); + + } // end of namespace tools +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POLYGON_B2DTRAPEZOID_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b3dpolygon.hxx b/include/basegfx/polygon/b3dpolygon.hxx new file mode 100644 index 000000000000..7199eea9684c --- /dev/null +++ b/include/basegfx/polygon/b3dpolygon.hxx @@ -0,0 +1,130 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B3DPOLYGON_HXX +#define _BGFX_POLYGON_B3DPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations +class ImplB3DPolygon; + +namespace basegfx +{ + class B3DPolygon; + class B3DPoint; + class B3DHomMatrix; + class B3DVector; + class B2DPoint; + class B2DHomMatrix; + class BColor; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC B3DPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB3DPolygon > ImplType; + + private: + // internal data. + ImplType mpPolygon; + + public: + B3DPolygon(); + B3DPolygon(const B3DPolygon& rPolygon); + ~B3DPolygon(); + + // assignment operator + B3DPolygon& operator=(const B3DPolygon& rPolygon); + + // compare operators + bool operator==(const B3DPolygon& rPolygon) const; + bool operator!=(const B3DPolygon& rPolygon) const; + + // member count + sal_uInt32 count() const; + + // Coordinate interface + B3DPoint getB3DPoint(sal_uInt32 nIndex) const; + void setB3DPoint(sal_uInt32 nIndex, const B3DPoint& rValue); + + // Coordinate append + void append(const B3DPoint& rPoint, sal_uInt32 nCount = 1); + + // BColor interface + BColor getBColor(sal_uInt32 nIndex) const; + void setBColor(sal_uInt32 nIndex, const BColor& rValue); + bool areBColorsUsed() const; + void clearBColors(); + + // Normals interface + B3DVector getNormal() const; // plane normal + B3DVector getNormal(sal_uInt32 nIndex) const; // normal in each point + void setNormal(sal_uInt32 nIndex, const B3DVector& rValue); + void transformNormals(const B3DHomMatrix& rMatrix); + bool areNormalsUsed() const; + void clearNormals(); + + // TextureCoordinate interface + B2DPoint getTextureCoordinate(sal_uInt32 nIndex) const; + void setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue); + void transformTextureCoordiantes(const B2DHomMatrix& rMatrix); + bool areTextureCoordinatesUsed() const; + void clearTextureCoordinates(); + + // append other 2D polygons + void append(const B3DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0); + + // remove + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + // clear all points + void clear(); + + // closed state + bool isClosed() const; + void setClosed(bool bNew); + + // flip polygon direction + void flip(); + + // test if Polygon has double points + bool hasDoublePoints() const; + + // remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + // apply transformation given in matrix form to the polygon + void transform(const B3DHomMatrix& rMatrix); + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + + +#endif /* _BGFX_POLYGON_B3DPOLYGON_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b3dpolygontools.hxx b/include/basegfx/polygon/b3dpolygontools.hxx new file mode 100644 index 000000000000..9ed32b42fb90 --- /dev/null +++ b/include/basegfx/polygon/b3dpolygontools.hxx @@ -0,0 +1,135 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX +#define _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX + +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <basegfx/polygon/b3dpolypolygon.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B3DPolygon; + class B3DRange; + + namespace tools + { + // B3DPolygon tools + + /** Check if given polygon is closed. This is kind of a + 'classic' method to support old polygon definitions. + Those old polygon definitions define the closed state + of the polygon using identical start and endpoints. This + method corrects this (removes double start/end points) + and sets the Closed()-state of the polygon correctly. + */ + BASEGFX_DLLPUBLIC void checkClosed(B3DPolygon& rCandidate); + + // Get successor and predecessor indices. Returning the same index means there + // is none. Same for successor. + BASEGFX_DLLPUBLIC sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const B3DPolygon& rCandidate); + + // get size of polygon. Control vectors are included in that ranges. + BASEGFX_DLLPUBLIC B3DRange getRange(const B3DPolygon& rCandidate); + + // get normal vector of polygon + BASEGFX_DLLPUBLIC B3DVector getNormal(const B3DPolygon& rCandidate); + + // get area of polygon + BASEGFX_DLLPUBLIC double getArea(const ::basegfx::B3DPolygon& rCandidate); + + // get length of polygon + BASEGFX_DLLPUBLIC double getLength(const B3DPolygon& rCandidate); + + /** Apply given LineDashing to given polygon + + For a description see applyLineDashing in b2dpolygontoos.hxx + */ + BASEGFX_DLLPUBLIC void applyLineDashing( + const B3DPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B3DPolyPolygon* pLineTarget, + B3DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + /** Create/replace normals for given 3d geometry with default normals from given center to outside. + rCandidate: the 3d geometry to change + rCenter: the center of the 3d geometry + */ + BASEGFX_DLLPUBLIC B3DPolygon applyDefaultNormalsSphere( const B3DPolygon& rCandidate, const B3DPoint& rCenter); + + /** invert normals for given 3d geometry. + */ + BASEGFX_DLLPUBLIC B3DPolygon invertNormals( const B3DPolygon& rCandidate); + + /** Create/replace texture coordinates for given 3d geometry with parallel projected one + rRange: the full range of the 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + BASEGFX_DLLPUBLIC B3DPolygon applyDefaultTextureCoordinatesParallel( const B3DPolygon& rCandidate, const B3DRange& rRange, bool bChangeX = true, bool bChangeY = true); + + /** Create/replace texture coordinates for given 3d geometry with spherical one + rCenter: the centre of the used 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + BASEGFX_DLLPUBLIC B3DPolygon applyDefaultTextureCoordinatesSphere( const B3DPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX = true, bool bChangeY = true); + + // isInside tests for B3DPoint. On border is not inside as long as not true is given in bWithBorder flag. + BASEGFX_DLLPUBLIC bool isInside(const B3DPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder = false); + + // calculates if given point is on given line, taking care of the numerical epsilon + BASEGFX_DLLPUBLIC bool isPointOnLine(const B3DPoint& rStart, const B3DPoint& rEnd, const B3DPoint& rCandidate, bool bWithPoints = false); + + // calculates if given point is on given polygon, taking care of the numerical epsilon. Uses + // isPointOnLine internally + BASEGFX_DLLPUBLIC bool isPointOnPolygon(const B3DPolygon& rCandidate, const B3DPoint& rPoint, bool bWithPoints = true); + + // helper to get a fCut position between a plane (given with normal and a point) + // and a line given by start and end point + BASEGFX_DLLPUBLIC bool getCutBetweenLineAndPlane(const B3DVector& rPlaneNormal, const B3DPoint& rPlanePoint, const B3DPoint& rEdgeStart, const B3DPoint& rEdgeEnd, double& fCut); + + /** snap some polygon coordinates to discrete coordinates + + This method allows to snap some polygon points to discrete (integer) values + which equals e.g. a snap to discrete coordinates. It will snap points of + horizontal and vertical edges + + @param rCandidate + The source polygon + + @return + The modified version of the source polygon + */ + BASEGFX_DLLPUBLIC B3DPolygon snapPointsOfHorizontalOrVerticalEdges(const B3DPolygon& rCandidate); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b3dpolypolygon.hxx b/include/basegfx/polygon/b3dpolypolygon.hxx new file mode 100644 index 000000000000..d67da6ad690b --- /dev/null +++ b/include/basegfx/polygon/b3dpolypolygon.hxx @@ -0,0 +1,117 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYGON_B3DPOLYPOLYGON_HXX +#define _BGFX_POLYGON_B3DPOLYPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + +// predeclarations +class ImplB3DPolyPolygon; + +namespace basegfx +{ + class B3DPolygon; + class B3DHomMatrix; + class B2DHomMatrix; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC B3DPolyPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB3DPolyPolygon > ImplType; + + private: + ImplType mpPolyPolygon; + + public: + B3DPolyPolygon(); + B3DPolyPolygon(const B3DPolyPolygon& rPolyPolygon); + explicit B3DPolyPolygon(const B3DPolygon& rPolygon); + ~B3DPolyPolygon(); + + // assignment operator + B3DPolyPolygon& operator=(const B3DPolyPolygon& rPolyPolygon); + + // compare operators + bool operator==(const B3DPolyPolygon& rPolyPolygon) const; + bool operator!=(const B3DPolyPolygon& rPolyPolygon) const; + + // polygon interface + sal_uInt32 count() const; + + // B3DPolygon interface + B3DPolygon getB3DPolygon(sal_uInt32 nIndex) const; + void setB3DPolygon(sal_uInt32 nIndex, const B3DPolygon& rPolygon); + + // BColor interface + bool areBColorsUsed() const; + void clearBColors(); + + // Normals interface + void transformNormals(const B3DHomMatrix& rMatrix); + bool areNormalsUsed() const; + void clearNormals(); + + // TextureCoordinate interface + void transformTextureCoordiantes(const B2DHomMatrix& rMatrix); + bool areTextureCoordinatesUsed() const; + void clearTextureCoordinates(); + + // append single polygon + void append(const B3DPolygon& rPolygon, sal_uInt32 nCount = 1); + + // append multiple polygons + void append(const B3DPolyPolygon& rPolyPolygon); + + // remove + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + // reset to empty state + void clear(); + + // flip polygon direction + void flip(); + + // test if PolyPolygon has double points + bool hasDoublePoints() const; + + // remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + // apply transformation given in matrix form to the polygon + void transform(const basegfx::B3DHomMatrix& rMatrix); + + // polygon iterators (same iterator validity conditions as for vector) + const B3DPolygon* begin() const; + const B3DPolygon* end() const; + B3DPolygon* begin(); + B3DPolygon* end(); + }; +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B3DPOLYPOLYGON_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/polygon/b3dpolypolygontools.hxx b/include/basegfx/polygon/b3dpolypolygontools.hxx new file mode 100644 index 000000000000..a50167f9b4de --- /dev/null +++ b/include/basegfx/polygon/b3dpolypolygontools.hxx @@ -0,0 +1,133 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX +#define _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <vector> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B3DPolyPolygon; + class B3DRange; + + namespace tools + { + // B3DPolyPolygon tools + + // get size of PolyPolygon. Control vectors are included in that ranges. + BASEGFX_DLLPUBLIC B3DRange getRange(const B3DPolyPolygon& rCandidate); + + /** Create a unit 3D line polyPolygon which defines a cube. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createUnitCubePolyPolygon(); + + /** Create a unit 3D fill polyPolygon which defines a cube. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createUnitCubeFillPolyPolygon(); + + /** Create a 3D line polyPolygon from a B3DRange which defines a cube. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange); + + /** Create a 3D fill polyPolygon from a B3DRange which defines a cube. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange); + + /** Create a unit 3D line polyPolygon which defines a sphere with the given count of hor and ver segments. + Result will be centered at (0.0, 0.0, 0.0) and sized [-1.0 .. 1.0] in all dimensions. + If nHorSeg == 0 and/or nVerSeg == 0, a default will be calculated to have a step at least each 15 degrees. + With VerStart, VerStop and hor range in cartesian may be specified to create a partial sphere only. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createUnitSpherePolyPolygon( + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** Create a 3D line polyPolygon from a B3DRange which defines a sphere with the given count of hor and ver segments. + If nHorSeg == 0 and/or nVerSeg == 0, a default will be calculated to have a step at least each 15 degrees. + With VerStart, VerStop and hor range in cartesian may be specified to create a partial sphere only. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createSpherePolyPolygonFromB3DRange( + const B3DRange& rRange, + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** same as createUnitSpherePolyPolygon, but creates filled polygons (closed and oriented) + There is one extra, the bool bNormals defines if normals will be set, default is false + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createUnitSphereFillPolyPolygon( + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + bool bNormals = false, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** same as createSpherePolyPolygonFromB3DRange, but creates filled polygons (closed and oriented) + There is one extra, the bool bNormals defines if normals will be set, default is false + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( + const B3DRange& rRange, + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + bool bNormals = false, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** Create/replace normals for given 3d geometry with default normals from given center to outside. + rCandidate: the 3d geometry to change + rCenter: the center of the 3d geometry + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter); + + /** invert normals for given 3d geometry. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate); + + /** Create/replace texture coordinates for given 3d geometry with parallel projected one + rRange: the full range of the 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX = true, bool bChangeY = true); + + /** Create/replace texture coordinates for given 3d geometry with spherical one + rCenter: the centre of the used 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + BASEGFX_DLLPUBLIC B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX = true, bool bChangeY = true); + + // isInside test for B3DPoint. On border is not inside as long as not true is given + // in bWithBorder flag. It is assumed that the orientations of the given polygon are correct. + BASEGFX_DLLPUBLIC bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder = false); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b1drange.hxx b/include/basegfx/range/b1drange.hxx new file mode 100644 index 000000000000..ffe704a1b845 --- /dev/null +++ b/include/basegfx/range/b1drange.hxx @@ -0,0 +1,174 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B1DRANGE_HXX +#define _BGFX_RANGE_B1DRANGE_HXX + +#include <basegfx/range/basicrange.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + class B1IRange; + + /** A one-dimensional interval over doubles + + This is a set of real numbers, bounded by a lower and an upper + value. All inbetween values are included in the set (see also + http://en.wikipedia.org/wiki/Interval_%28mathematics%29). + + The set is closed, i.e. the upper and the lower bound are + included (if you're used to the notation - we're talking about + [a,b] here, compared to half-open [a,b) or open intervals + (a,b)). + + That means, isInside(val) will return true also for values of + val=a or val=b. + */ + class B1DRange + { + ::basegfx::BasicRange< double, DoubleTraits > maRange; + + public: + B1DRange() {} + + /// Create degenerate interval consisting of a single double number + explicit B1DRange(double fStartValue) + : maRange(fStartValue) + { + } + + /// Create proper interval between the two given double values + B1DRange(double fStartValue1, double fStartValue2) + : maRange(fStartValue1) + { + expand(fStartValue2); + } + + /** Check if the interval set is empty + + @return false, if no value is in this set - having a + single value included will already return true. + */ + bool isEmpty() const + { + return maRange.isEmpty(); + } + + /// reset the object to empty state again, clearing all values + void reset() + { + maRange.reset(); + } + + bool operator==( const B1DRange& rRange ) const + { + return (maRange == rRange.maRange); + } + + bool operator!=( const B1DRange& rRange ) const + { + return (maRange != rRange.maRange); + } + + bool equal(const B1DRange& rRange) const + { + return (maRange.equal(rRange.maRange)); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + double getMinimum() const + { + return maRange.getMinimum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + double getMaximum() const + { + return maRange.getMaximum(); + } + + /// return difference between upper and lower value. returns 0 for empty sets. + double getRange() const + { + return maRange.getRange(); + } + + /// return middle of upper and lower value. returns 0 for empty sets. + double getCenter() const + { + return maRange.getCenter(); + } + + /// yields true if value is contained in set + bool isInside(double fValue) const + { + return maRange.isInside(fValue); + } + + /// yields true if rRange is inside, or equal to set + bool isInside(const B1DRange& rRange) const + { + return maRange.isInside(rRange.maRange); + } + + /// yields true if rRange at least partly inside set + bool overlaps(const B1DRange& rRange) const + { + return maRange.overlaps(rRange.maRange); + } + + /// yields true if overlaps(rRange) does, and the overlap is larger than infinitesimal + bool overlapsMore(const B1DRange& rRange) const + { + return maRange.overlapsMore(rRange.maRange); + } + + /// add fValue to the set, expanding as necessary + void expand(double fValue) + { + maRange.expand(fValue); + } + + /// add rRange to the set, expanding as necessary + void expand(const B1DRange& rRange) + { + maRange.expand(rRange.maRange); + } + + /// calc set intersection + void intersect(const B1DRange& rRange) + { + maRange.intersect(rRange.maRange); + } + + /// grow set by fValue on both sides + void grow(double fValue) + { + maRange.grow(fValue); + } + }; + +} // end of namespace basegfx + + +#endif /* _BGFX_RANGE_B1DRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b1ibox.hxx b/include/basegfx/range/b1ibox.hxx new file mode 100644 index 000000000000..7c81e37c1288 --- /dev/null +++ b/include/basegfx/range/b1ibox.hxx @@ -0,0 +1,164 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B1IBOX_HXX +#define _BGFX_RANGE_B1IBOX_HXX + +#include <basegfx/range/basicbox.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** A one-dimensional interval over integers + + This is most easily depicted as a set of integers, bounded by + a lower and an upper value - but excluding the upper + value. All inbetween values are included in the set (see also + http://en.wikipedia.org/wiki/Interval_%28mathematics%29). + + The set is half-open, i.e. the lower bound is included, the + upper bound not (if you're used to the notation - we're + talking about [a,b) here, compared to closed [a,b] or fully + open intervals (a,b)). + + If you don't need a half-open interval, check B1IRange. + + That means, isInside(val) will return true also for values of + val=a, but not for val=b. + + @see B1IRange + */ + class B1IBox + { + ::basegfx::BasicBox maRange; + + public: + B1IBox() {} + + /// Create degenerate interval that's still empty + explicit B1IBox(sal_Int32 nStartValue) + : maRange(nStartValue) + { + } + + /// Create proper interval between the two given values + B1IBox(sal_Int32 nStartValue1, sal_Int32 nStartValue2) + : maRange(nStartValue1) + { + expand(nStartValue2); + } + + /** Check if the interval set is empty + + @return false, if no value is in this set - having a + single value included will still return false. + */ + bool isEmpty() const + { + return maRange.isEmpty(); + } + + /// reset the object to empty state again, clearing all values + void reset() + { + maRange.reset(); + } + + bool operator==( const B1IBox& rBox ) const + { + return (maRange == rBox.maRange); + } + + bool operator!=( const B1IBox& rBox ) const + { + return (maRange != rBox.maRange); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMinimum() const + { + return maRange.getMinimum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMaximum() const + { + return maRange.getMaximum(); + } + + /// return difference between upper and lower value. returns 0 for empty sets. + Int32Traits::DifferenceType getRange() const + { + return maRange.getRange(); + } + + /// return middle of upper and lower value. returns 0 for empty sets. + double getCenter() const + { + return maRange.getCenter(); + } + + /// yields true if value is contained in set + bool isInside(sal_Int32 nValue) const + { + return maRange.isInside(nValue); + } + + /// yields true if rRange is inside, or equal to set + bool isInside(const B1IBox& rBox) const + { + return maRange.isInside(rBox.maRange); + } + + /// yields true if rRange at least partly inside set + bool overlaps(const B1IBox& rBox) const + { + return maRange.overlaps(rBox.maRange); + } + + /// add nValue to the set, expanding as necessary + void expand(sal_Int32 nValue) + { + maRange.expand(nValue); + } + + /// add rBox to the set, expanding as necessary + void expand(const B1IBox& rBox) + { + maRange.expand(rBox.maRange); + } + + /// calc set intersection + void intersect(const B1IBox& rBox) + { + maRange.intersect(rBox.maRange); + } + + /// grow set by nValue on both sides + void grow(sal_Int32 nValue) + { + maRange.grow(nValue); + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_B1IBOX_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b1irange.hxx b/include/basegfx/range/b1irange.hxx new file mode 100644 index 000000000000..0ba5878fb0c8 --- /dev/null +++ b/include/basegfx/range/b1irange.hxx @@ -0,0 +1,169 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B1IRANGE_HXX +#define _BGFX_RANGE_B1IRANGE_HXX + +#include <basegfx/range/basicrange.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** A one-dimensional interval over integers + + This is a set of real numbers, bounded by a lower and an upper + value. All inbetween values are included in the set (see also + http://en.wikipedia.org/wiki/Interval_%28mathematics%29). + + Probably you rather want B1IBox for integers. + + The set is closed, i.e. the upper and the lower bound are + included (if you're used to the notation - we're talking about + [a,b] here, compared to half-open [a,b) or open intervals + (a,b)). + + That means, isInside(val) will return true also for values of + val=a or val=b. + + @see B1IBox + */ + class B1IRange + { + ::basegfx::BasicRange< sal_Int32, Int32Traits > maRange; + + public: + B1IRange() {} + + /// Create degenerate interval consisting of a single double number + explicit B1IRange(sal_Int32 nStartValue) + : maRange(nStartValue) + { + } + + /// Create proper interval between the two given values + B1IRange(sal_Int32 nStartValue1, sal_Int32 nStartValue2) + : maRange(nStartValue1) + { + expand(nStartValue2); + } + + /** Check if the interval set is empty + + @return false, if no value is in this set - having a + single value included will already return true. + */ + bool isEmpty() const + { + return maRange.isEmpty(); + } + + /// reset the object to empty state again, clearing all values + void reset() + { + maRange.reset(); + } + + bool operator==( const B1IRange& rRange ) const + { + return (maRange == rRange.maRange); + } + + bool operator!=( const B1IRange& rRange ) const + { + return (maRange != rRange.maRange); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMinimum() const + { + return maRange.getMinimum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMaximum() const + { + return maRange.getMaximum(); + } + + /// return difference between upper and lower value. returns 0 for empty sets. + Int32Traits::DifferenceType getRange() const + { + return maRange.getRange(); + } + + /// return middle of upper and lower value. returns 0 for empty sets. + double getCenter() const + { + return maRange.getCenter(); + } + + /// yields true if value is contained in set + bool isInside(sal_Int32 nValue) const + { + return maRange.isInside(nValue); + } + + /// yields true if rRange is inside, or equal to set + bool isInside(const B1IRange& rRange) const + { + return maRange.isInside(rRange.maRange); + } + + /// yields true if rRange at least partly inside set + bool overlaps(const B1IRange& rRange) const + { + return maRange.overlaps(rRange.maRange); + } + + /// yields true if overlaps(rRange) does, and the overlap is larger than infinitesimal + bool overlapsMore(const B1IRange& rRange) const + { + return maRange.overlapsMore(rRange.maRange); + } + + /// add nValue to the set, expanding as necessary + void expand(sal_Int32 nValue) + { + maRange.expand(nValue); + } + + /// add rRange to the set, expanding as necessary + void expand(const B1IRange& rRange) + { + maRange.expand(rRange.maRange); + } + + /// calc set intersection + void intersect(const B1IRange& rRange) + { + maRange.intersect(rRange.maRange); + } + + /// grow set by nValue on both sides + void grow(sal_Int32 nValue) + { + maRange.grow(nValue); + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_B1IRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2dconnectedranges.hxx b/include/basegfx/range/b2dconnectedranges.hxx new file mode 100644 index 000000000000..f1d65196bd8f --- /dev/null +++ b/include/basegfx/range/b2dconnectedranges.hxx @@ -0,0 +1,257 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2DCONNECTEDRANGES_HXX +#define _BGFX_RANGE_B2DCONNECTEDRANGES_HXX + +#include <osl/diagnose.h> +#include <basegfx/range/b2drange.hxx> +#include <list> +#include <utility> +#include <algorithm> + + +namespace basegfx +{ + /** Calculate connected ranges from input ranges. + + This template constructs a list of connected ranges from the + given input ranges. That is, the output will contain a set of + ranges, itself containing a number of input ranges, which will + be mutually non-intersecting. + + Example: + <code> + ------------------- + | -------| + | | || + | --- | || + | | | -------| -------- + | | +--------- | | | + | --+ | | | | + | | | | -------- + | ---------- | + ------------------- + </code + + Here, the outer rectangles represent the output + ranges. Contained are the input rectangles that comprise these + output ranges. + + @tpl UserData + User data to be stored along with the range, to later identify + which range went into which connected component. Must be + assignable, default- and copy-constructible. + */ + template< typename UserData > class B2DConnectedRanges + { + public: + /// Type of the basic entity (rect + user data) + typedef ::std::pair< B2DRange, UserData > ComponentType; + typedef ::std::list< ComponentType > ComponentListType; + + /// List of (intersecting) components, plus overall bounds + struct ConnectedComponents + { + ComponentListType maComponentList; + B2DRange maTotalBounds; + }; + + typedef ::std::list< ConnectedComponents > ConnectedComponentsType; + + + /// Create the range calculator + B2DConnectedRanges() : + maDisjunctAggregatesList(), + maTotalBounds() + { + } + + /** Query total bounds of all added ranges. + + @return the union bound rect over all added ranges. + */ + B2DRange getBounds() const + { + return maTotalBounds; + } + + /** Add an additional range. + + This method integrates a new range into the connected + ranges lists. The method has a worst-case time complexity + of O(n^2), with n denoting the number of already added + ranges (typically, for well-behaved input, it is O(n) + though). + */ + void addRange( const B2DRange& rRange, + const UserData& rUserData ) + { + // check whether fast path is possible: if new range is + // outside accumulated total range, can add it as a + // separate component right away. + const bool bNotOutsideEverything( + maTotalBounds.overlaps( rRange ) ); + + // update own global bounds range + maTotalBounds.expand( rRange ); + + // assemble anything intersecting with rRange into + // this new connected component + ConnectedComponents aNewConnectedComponent; + + // as at least rRange will be a member of + // aNewConnectedComponent (will be added below), can + // preset the overall bounds here. + aNewConnectedComponent.maTotalBounds = rRange; + + + // + // STAGE 1: Search for intersecting maDisjunctAggregatesList entries + // ================================================================= + // + + // if rRange is empty, it will intersect with no + // maDisjunctAggregatesList member. Thus, we can safe us + // the check. + // if rRange is outside all other rectangle, skip here, + // too + if( bNotOutsideEverything && + !rRange.isEmpty() ) + { + typename ConnectedComponentsType::iterator aCurrAggregate; + typename ConnectedComponentsType::iterator aLastAggregate; + + // flag, determining whether we touched one or more of + // the maDisjunctAggregatesList entries. _If_ we did, + // we have to repeat the intersection process, because + // these changes might have generated new + // intersections. + bool bSomeAggregatesChanged; + + // loop, until bSomeAggregatesChanged stays false + do + { + // only continue loop if 'intersects' branch below was hit + bSomeAggregatesChanged = false; + + // iterate over all current members of maDisjunctAggregatesList + for( aCurrAggregate=maDisjunctAggregatesList.begin(), + aLastAggregate=maDisjunctAggregatesList.end(); + aCurrAggregate != aLastAggregate; ) + { + // first check if current component's bounds + // are empty. This ensures that distinct empty + // components are not merged into one + // aggregate. As a matter of fact, they have + // no position and size. + + if( !aCurrAggregate->maTotalBounds.isEmpty() && + aCurrAggregate->maTotalBounds.overlaps( + aNewConnectedComponent.maTotalBounds ) ) + { + // union the intersecting + // maDisjunctAggregatesList element into + // aNewConnectedComponent + + // calc union bounding box + aNewConnectedComponent.maTotalBounds.expand( aCurrAggregate->maTotalBounds ); + + // extract all aCurrAggregate components + // to aNewConnectedComponent + aNewConnectedComponent.maComponentList.splice( + aNewConnectedComponent.maComponentList.end(), + aCurrAggregate->maComponentList ); + + // remove and delete aCurrAggregate entry + // from list (we've gutted it's content + // above). list::erase() will update our + // iterator with the predecessor here. + aCurrAggregate = maDisjunctAggregatesList.erase( aCurrAggregate ); + + // at least one aggregate changed, need to rescan everything + bSomeAggregatesChanged = true; + } + else + { + aCurrAggregate++; + } + } + } + while( bSomeAggregatesChanged ); + } + + // + // STAGE 2: Add newly generated connected component list element + // ============================================================= + // + + // add new component to the end of the component list + aNewConnectedComponent.maComponentList.push_back( + ComponentType( rRange, rUserData ) ); + + // do some consistency checks (aka post conditions) + OSL_ENSURE( !aNewConnectedComponent.maComponentList.empty(), + "B2DConnectedRanges::addRange(): empty aggregate list" ); + OSL_ENSURE( !aNewConnectedComponent.maTotalBounds.isEmpty() || + (aNewConnectedComponent.maTotalBounds.isEmpty() && + aNewConnectedComponent.maComponentList.size() == 1), + "B2DConnectedRanges::addRange(): empty ranges must be solitary"); + + // add aNewConnectedComponent as a new entry to + // maDisjunctAggregatesList + maDisjunctAggregatesList.push_back( aNewConnectedComponent ); + } + + /** Apply a functor to each of the disjunct component + aggregates. + + @param aFunctor + Functor to apply. Must provide an operator( const ConnectedComponents& ). + + @return a copy of the functor, as applied to all aggregates. + */ + template< typename UnaryFunctor > UnaryFunctor forEachAggregate( UnaryFunctor aFunctor ) const + { + return ::std::for_each( maDisjunctAggregatesList.begin(), + maDisjunctAggregatesList.end(), + aFunctor ); + } + + private: + // default: disabled copy/assignment + B2DConnectedRanges(const B2DConnectedRanges&); + B2DConnectedRanges& operator=( const B2DConnectedRanges& ); + + /** Current list of disjunct sets of connected components + + Each entry corresponds to one of the top-level rectangles + in the drawing above. + */ + ConnectedComponentsType maDisjunctAggregatesList; + + /** Global bound rect over all added ranges. + */ + B2DRange maTotalBounds; + }; +} + +#endif /* _BGFX_RANGE_B2DCONNECTEDRANGES_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2dpolyrange.hxx b/include/basegfx/range/b2dpolyrange.hxx new file mode 100644 index 000000000000..b910062d11a3 --- /dev/null +++ b/include/basegfx/range/b2dpolyrange.hxx @@ -0,0 +1,94 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2DPOLYRANGE_HXX +#define _BGFX_RANGE_B2DPOLYRANGE_HXX + +#include <o3tl/cow_wrapper.hxx> +#include <boost/tuple/tuple.hpp> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B2DTuple; + class B2DRange; + class B2DPolyPolygon; + class ImplB2DPolyRange; + + /** Multiple ranges in one object. + + This class combines multiple ranges in one object, providing a + total, enclosing range for it. + + You can use this class e.g. when updating views containing + rectangular objects. Add each modified object to a + B2DMultiRange, then test each viewable object against + intersection with the multi range. + + Similar in spirit to the poly-polygon vs. polygon relationship. + + Note that comparable to polygons, a poly-range can also + contain 'holes' - this is encoded via polygon orientation at + the poly-polygon, and via explicit flags for the poly-range. + */ + class BASEGFX_DLLPUBLIC B2DPolyRange + { + public: + typedef boost::tuple<B2DRange,B2VectorOrientation> ElementType ; + + B2DPolyRange(); + ~B2DPolyRange(); + + /** Create a multi range with exactly one containing range + */ + B2DPolyRange( const B2DPolyRange& ); + B2DPolyRange& operator=( const B2DPolyRange& ); + + bool operator==(const B2DPolyRange&) const; + bool operator!=(const B2DPolyRange&) const; + + /// Number of included ranges + sal_uInt32 count() const; + + ElementType getElement(sal_uInt32 nIndex) const; + + // insert/append a single range + void appendElement(const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount = 1); + + void clear(); + + /** Test whether given range overlaps one or more of the + included ranges. Does *not* use overall range, but checks + individually. + */ + bool overlaps( const B2DRange& rRange ) const; + + /** Request a poly-polygon with solved cross-overs + */ + B2DPolyPolygon solveCrossovers() const; + + private: + o3tl::cow_wrapper< ImplB2DPolyRange > mpImpl; + }; +} + +#endif /* _BGFX_RANGE_B2DPOLYRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2drange.hxx b/include/basegfx/range/b2drange.hxx new file mode 100644 index 000000000000..1f3884c1c9ce --- /dev/null +++ b/include/basegfx/range/b2drange.hxx @@ -0,0 +1,320 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2DRANGE_HXX +#define _BGFX_RANGE_B2DRANGE_HXX + +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/range/basicrange.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + // predeclarations + class B2IRange; + class B2DHomMatrix; + + /** A two-dimensional interval over doubles + + This is a set of real numbers, bounded by a lower and an upper + pair. All inbetween values are included in the set (see also + http://en.wikipedia.org/wiki/Interval_%28mathematics%29). + + The set is closed, i.e. the upper and the lower bound are + included (if you're used to the notation - we're talking about + [a,b] here, compared to half-open [a,b) or open intervals + (a,b)). + + That means, isInside(val) will return true also for values of + val=a or val=b. + + @see B1DRange + */ + class B2DRange + { + public: + typedef double ValueType; + typedef DoubleTraits TraitsType; + + B2DRange() {} + + /// Create degenerate interval consisting of a single point + explicit B2DRange(const B2DTuple& rTuple) + : maRangeX(rTuple.getX()), + maRangeY(rTuple.getY()) + { + } + + /// Create proper interval between the two given double pairs + B2DRange(double x1, + double y1, + double x2, + double y2) + : maRangeX(x1), + maRangeY(y1) + { + maRangeX.expand(x2); + maRangeY.expand(y2); + } + + /// Create proper interval between the two given points + B2DRange(const B2DTuple& rTuple1, + const B2DTuple& rTuple2) + : maRangeX(rTuple1.getX()), + maRangeY(rTuple1.getY()) + { + expand( rTuple2 ); + } + + BASEGFX_DLLPUBLIC explicit B2DRange(const B2IRange& rRange); + + /** Check if the interval set is empty + + @return false, if no value is in this set - having a + single point included will already return true. + */ + bool isEmpty() const + { + return ( + maRangeX.isEmpty() + || maRangeY.isEmpty() + ); + } + + /// reset the object to empty state again, clearing all values + void reset() + { + maRangeX.reset(); + maRangeY.reset(); + } + + bool operator==( const B2DRange& rRange ) const + { + return (maRangeX == rRange.maRangeX + && maRangeY == rRange.maRangeY); + } + + bool operator!=( const B2DRange& rRange ) const + { + return (maRangeX != rRange.maRangeX + || maRangeY != rRange.maRangeY); + } + + bool equal(const B2DRange& rRange) const + { + return (maRangeX.equal(rRange.maRangeX) + && maRangeY.equal(rRange.maRangeY)); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + double getMinX() const + { + return maRangeX.getMinimum(); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + double getMinY() const + { + return maRangeY.getMinimum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + double getMaxX() const + { + return maRangeX.getMaximum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + double getMaxY() const + { + return maRangeY.getMaximum(); + } + + /// return difference between upper and lower X value. returns 0 for empty sets. + double getWidth() const + { + return maRangeX.getRange(); + } + + /// return difference between upper and lower Y value. returns 0 for empty sets. + double getHeight() const + { + return maRangeY.getRange(); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + B2DPoint getMinimum() const + { + return B2DPoint( + maRangeX.getMinimum(), + maRangeY.getMinimum() + ); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + B2DPoint getMaximum() const + { + return B2DPoint( + maRangeX.getMaximum(), + maRangeY.getMaximum() + ); + } + + /// return difference between upper and lower point. returns (0,0) for empty sets. + B2DVector getRange() const + { + return B2DVector( + maRangeX.getRange(), + maRangeY.getRange() + ); + } + + /// return center point of set. returns (0,0) for empty sets. + B2DPoint getCenter() const + { + return B2DPoint( + maRangeX.getCenter(), + maRangeY.getCenter() + ); + } + + /// return center X value of set. returns 0 for empty sets. + double getCenterX() const + { + return maRangeX.getCenter(); + } + + /// return center Y value of set. returns 0 for empty sets. + double getCenterY() const + { + return maRangeY.getCenter(); + } + + /// yields true if given point is contained in set + bool isInside(const B2DTuple& rTuple) const + { + return ( + maRangeX.isInside(rTuple.getX()) + && maRangeY.isInside(rTuple.getY()) + ); + } + + /// yields true if rRange is inside, or equal to set + bool isInside(const B2DRange& rRange) const + { + return ( + maRangeX.isInside(rRange.maRangeX) + && maRangeY.isInside(rRange.maRangeY) + ); + } + + /// yields true if rRange at least partly inside set + bool overlaps(const B2DRange& rRange) const + { + return ( + maRangeX.overlaps(rRange.maRangeX) + && maRangeY.overlaps(rRange.maRangeY) + ); + } + + /// yields true if overlaps(rRange) does, and the overlap is larger than infinitesimal + bool overlapsMore(const B2DRange& rRange) const + { + return ( + maRangeX.overlapsMore(rRange.maRangeX) + && maRangeY.overlapsMore(rRange.maRangeY) + ); + } + + /// add point to the set, expanding as necessary + void expand(const B2DTuple& rTuple) + { + maRangeX.expand(rTuple.getX()); + maRangeY.expand(rTuple.getY()); + } + + /// add rRange to the set, expanding as necessary + void expand(const B2DRange& rRange) + { + maRangeX.expand(rRange.maRangeX); + maRangeY.expand(rRange.maRangeY); + } + + /// calc set intersection + void intersect(const B2DRange& rRange) + { + maRangeX.intersect(rRange.maRangeX); + maRangeY.intersect(rRange.maRangeY); + } + + /// grow set by fValue on all sides + void grow(double fValue) + { + maRangeX.grow(fValue); + maRangeY.grow(fValue); + } + + BASEGFX_DLLPUBLIC void transform(const B2DHomMatrix& rMatrix); + + private: + typedef ::basegfx::BasicRange< ValueType, TraitsType > MyBasicRange; + + MyBasicRange maRangeX; + MyBasicRange maRangeY; + }; + + /** Round double to nearest integer for 2D range + + @return the nearest integer for this range + */ + BASEGFX_DLLPUBLIC B2IRange fround(const B2DRange& rRange); + + /** Compute the set difference of the two given ranges + + This method calculates the symmetric difference (aka XOR) + between the two given ranges, and returning the resulting + ranges. Thus, the result will contain all areas where one, but + not both ranges lie. + + @param o_rResult + Result vector. The up to four difference ranges are returned + within this vector + + @param rFirst + The first range + + @param rSecond + The second range + + @return the input vector + */ + BASEGFX_DLLPUBLIC ::std::vector< B2DRange >& computeSetDifference( ::std::vector< B2DRange >& o_rResult, + const B2DRange& rFirst, + const B2DRange& rSecond ); + +} // end of namespace basegfx + + +#endif /* _BGFX_RANGE_B2DRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2drangeclipper.hxx b/include/basegfx/range/b2drangeclipper.hxx new file mode 100644 index 000000000000..99bc8763369d --- /dev/null +++ b/include/basegfx/range/b2drangeclipper.hxx @@ -0,0 +1,45 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2DRANGECLIPPER_HXX +#define _BGFX_RANGE_B2DRANGECLIPPER_HXX + +#include <basegfx/range/b2dpolyrange.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + namespace tools + { + /** Extract poly-polygon w/o self-intersections from poly-range + + Similar to the solveCrossovers(const B2DPolyPolygon&) + method, this one calculates a self-intersection-free + poly-polygon with the same topology, and encoding + inside/outsidedness via polygon orientation and layering. + */ + BASEGFX_DLLPUBLIC B2DPolyPolygon solveCrossovers(const std::vector<B2DRange>& rRanges, + const std::vector<B2VectorOrientation>& rOrientations); + } +} + +#endif /* _BGFX_RANGE_B2DRANGECLIPPER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2drectangle.hxx b/include/basegfx/range/b2drectangle.hxx new file mode 100644 index 000000000000..8d4715d64410 --- /dev/null +++ b/include/basegfx/range/b2drectangle.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2DRECTANGLE_HXX +#define _BGFX_RANGE_B2DRECTANGLE_HXX + +#include <basegfx/range/b2drange.hxx> + +namespace basegfx +{ + // syntactic sugar: a B2DRange exactly models a Rectangle, thus, + // for interface clarity, we provide an alias name + + /// Alias name for interface clarity (not everybody is aware of the identity) + typedef B2DRange B2DRectangle; +} + +#endif /* _BGFX_RANGE_B2DRECTANGLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2ibox.hxx b/include/basegfx/range/b2ibox.hxx new file mode 100644 index 000000000000..7c182a4ab327 --- /dev/null +++ b/include/basegfx/range/b2ibox.hxx @@ -0,0 +1,261 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2IBOX_HXX +#define _BGFX_RANGE_B2IBOX_HXX + +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/tuple/b2ituple.hxx> +#include <basegfx/tuple/b2i64tuple.hxx> +#include <basegfx/range/basicbox.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** A two-dimensional interval over integers + + This is most easily depicted as a set of integers, bounded by + a lower and an upper value - but excluding the upper + value. All inbetween values are included in the set (see also + http://en.wikipedia.org/wiki/Interval_%28mathematics%29). + + The set is half-open, i.e. the lower bound is included, the + upper bound not (if you're used to the notation - we're + talking about [a,b) here, compared to closed [a,b] or fully + open intervals (a,b)). + + If you don't need a half-open interval, check B2IRange. + + That means, isInside(val) will return true also for values of + val=a, but not for val=b. + + Alternatively, consider this a rectangle, where the rightmost + pixel column and the bottommost pixel row are excluded - this + is much like polygon filling. As a result, filling a given + rectangle with basebmp::BitmapDevice::fillPolyPolygon(), will + affect exactly the same set of pixel as isInside() would + return true for. + + @see B2IRange + */ + class B2IBox + { + public: + typedef sal_Int32 ValueType; + typedef Int32Traits TraitsType; + + B2IBox() {} + + /// Create degenerate interval that's still empty + explicit B2IBox(const B2ITuple& rTuple) + : maRangeX(rTuple.getX()), + maRangeY(rTuple.getY()) + { + } + + /// Create proper interval between the two given points + B2IBox(sal_Int32 x1, + sal_Int32 y1, + sal_Int32 x2, + sal_Int32 y2) : + maRangeX(x1), + maRangeY(y1) + { + maRangeX.expand(x2); + maRangeY.expand(y2); + } + + /// Create proper interval between the two given points + B2IBox(const B2ITuple& rTuple1, + const B2ITuple& rTuple2) : + maRangeX(rTuple1.getX()), + maRangeY(rTuple1.getY()) + { + expand( rTuple2 ); + } + + /** Check if the interval set is empty + + @return false, if no value is in this set - having a + single value included will still return false. + */ + bool isEmpty() const + { + return maRangeX.isEmpty() || maRangeY.isEmpty(); + } + + /// reset the object to empty state again, clearing all values + void reset() + { + maRangeX.reset(); + maRangeY.reset(); + } + + bool operator==( const B2IBox& rBox ) const + { + return (maRangeX == rBox.maRangeX + && maRangeY == rBox.maRangeY); + } + + bool operator!=( const B2IBox& rBox ) const + { + return (maRangeX != rBox.maRangeX + || maRangeY != rBox.maRangeY); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMinX() const + { + return maRangeX.getMinimum(); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMinY() const + { + return maRangeY.getMinimum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMaxX() const + { + return maRangeX.getMaximum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMaxY() const + { + return maRangeY.getMaximum(); + } + + /// return difference between upper and lower X value. returns 0 for empty sets. + sal_Int64 getWidth() const + { + return maRangeX.getRange(); + } + + /// return difference between upper and lower Y value. returns 0 for empty sets. + sal_Int64 getHeight() const + { + return maRangeY.getRange(); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + B2IPoint getMinimum() const + { + return B2IPoint( + maRangeX.getMinimum(), + maRangeY.getMinimum() + ); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + B2IPoint getMaximum() const + { + return B2IPoint( + maRangeX.getMaximum(), + maRangeY.getMaximum() + ); + } + + /// return difference between upper and lower value. returns (0,0) for empty sets. + B2I64Tuple getRange() const + { + return B2I64Tuple( + maRangeX.getRange(), + maRangeY.getRange() + ); + } + + /// return center point of set. returns (0,0) for empty sets. + B2DPoint getCenter() const + { + return B2DPoint( + maRangeX.getCenter(), + maRangeY.getCenter() + ); + } + + /// yields true if point is contained in set + bool isInside(const B2ITuple& rTuple) const + { + return ( + maRangeX.isInside(rTuple.getX()) + && maRangeY.isInside(rTuple.getY()) + ); + } + + /// yields true if rBox is inside, or equal to set + bool isInside(const B2IBox& rBox) const + { + return ( + maRangeX.isInside(rBox.maRangeX) + && maRangeY.isInside(rBox.maRangeY) + ); + } + + /// yields true if rBox at least partly inside set + bool overlaps(const B2IBox& rBox) const + { + return ( + maRangeX.overlaps(rBox.maRangeX) + && maRangeY.overlaps(rBox.maRangeY) + ); + } + + /// add point to the set, expanding as necessary + void expand(const B2ITuple& rTuple) + { + maRangeX.expand(rTuple.getX()); + maRangeY.expand(rTuple.getY()); + } + + /// add rBox to the set, expanding as necessary + void expand(const B2IBox& rBox) + { + maRangeX.expand(rBox.maRangeX); + maRangeY.expand(rBox.maRangeY); + } + + /// calc set intersection + void intersect(const B2IBox& rBox) + { + maRangeX.intersect(rBox.maRangeX); + maRangeY.intersect(rBox.maRangeY); + } + + /// grow set by nValue on all sides + void grow(sal_Int32 nValue) + { + maRangeX.grow(nValue); + maRangeY.grow(nValue); + } + + private: + BasicBox maRangeX; + BasicBox maRangeY; + }; + +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_B2IBOX_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2irange.hxx b/include/basegfx/range/b2irange.hxx new file mode 100644 index 000000000000..60f9fc79fa67 --- /dev/null +++ b/include/basegfx/range/b2irange.hxx @@ -0,0 +1,287 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2IRANGE_HXX +#define _BGFX_RANGE_B2IRANGE_HXX + +#include <basegfx/point/b2ipoint.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/tuple/b2ituple.hxx> +#include <basegfx/tuple/b2i64tuple.hxx> +#include <basegfx/range/basicrange.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** A two-dimensional interval over integers + + This is a set of real numbers, bounded by a lower and an upper + pair. All inbetween values are included in the set (see also + http://en.wikipedia.org/wiki/Interval_%28mathematics%29). + + Probably you rather want B2IBox for integers. + + The set is closed, i.e. the upper and the lower bound are + included (if you're used to the notation - we're talking about + [a,b] here, compared to half-open [a,b) or open intervals + (a,b)). + + That means, isInside(val) will return true also for values of + val=a or val=b. + + @see B2IBox + */ + class B2IRange + { + public: + typedef sal_Int32 ValueType; + typedef Int32Traits TraitsType; + + B2IRange() {} + + /// Create degenerate interval consisting of a single point + explicit B2IRange(const B2ITuple& rTuple) + : maRangeX(rTuple.getX()), + maRangeY(rTuple.getY()) + { + } + + /// Create proper interval between the two given integer pairs + B2IRange(sal_Int32 x1, + sal_Int32 y1, + sal_Int32 x2, + sal_Int32 y2) + : maRangeX(x1), + maRangeY(y1) + { + maRangeX.expand(x2); + maRangeY.expand(y2); + } + + /// Create proper interval between the two given points + B2IRange(const B2ITuple& rTuple1, + const B2ITuple& rTuple2) + : maRangeX(rTuple1.getX()), + maRangeY(rTuple1.getY()) + { + expand( rTuple2 ); + } + + /** Check if the interval set is empty + + @return false, if no value is in this set - having a + single point included will already return true. + */ + bool isEmpty() const + { + return maRangeX.isEmpty() || maRangeY.isEmpty(); + } + + /// reset the object to empty state again, clearing all values + void reset() + { + maRangeX.reset(); + maRangeY.reset(); + } + + bool operator==( const B2IRange& rRange ) const + { + return (maRangeX == rRange.maRangeX + && maRangeY == rRange.maRangeY); + } + + bool operator!=( const B2IRange& rRange ) const + { + return (maRangeX != rRange.maRangeX + || maRangeY != rRange.maRangeY); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMinX() const + { + return maRangeX.getMinimum(); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMinY() const + { + return maRangeY.getMinimum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMaxX() const + { + return maRangeX.getMaximum(); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + sal_Int32 getMaxY() const + { + return maRangeY.getMaximum(); + } + + /// return difference between upper and lower X value. returns 0 for empty sets. + sal_Int64 getWidth() const + { + return maRangeX.getRange(); + } + + /// return difference between upper and lower Y value. returns 0 for empty sets. + sal_Int64 getHeight() const + { + return maRangeY.getRange(); + } + + /// get lower bound of the set. returns arbitrary values for empty sets. + B2IPoint getMinimum() const + { + return B2IPoint( + maRangeX.getMinimum(), + maRangeY.getMinimum() + ); + } + + /// get upper bound of the set. returns arbitrary values for empty sets. + B2IPoint getMaximum() const + { + return B2IPoint( + maRangeX.getMaximum(), + maRangeY.getMaximum() + ); + } + + /// return difference between upper and lower point. returns (0,0) for empty sets. + B2I64Tuple getRange() const + { + return B2I64Tuple( + maRangeX.getRange(), + maRangeY.getRange() + ); + } + + /// return center point of set. returns (0,0) for empty sets. + B2DPoint getCenter() const + { + return B2DPoint( + maRangeX.getCenter(), + maRangeY.getCenter() + ); + } + + /// yields true if given point is contained in set + bool isInside(const B2ITuple& rTuple) const + { + return ( + maRangeX.isInside(rTuple.getX()) + && maRangeY.isInside(rTuple.getY()) + ); + } + + /// yields true if rRange is inside, or equal to set + bool isInside(const B2IRange& rRange) const + { + return ( + maRangeX.isInside(rRange.maRangeX) + && maRangeY.isInside(rRange.maRangeY) + ); + } + + /// yields true if rRange at least partly inside set + bool overlaps(const B2IRange& rRange) const + { + return ( + maRangeX.overlaps(rRange.maRangeX) + && maRangeY.overlaps(rRange.maRangeY) + ); + } + + /// yields true if overlaps(rRange) does, and the overlap is larger than infinitesimal + bool overlapsMore(const B2IRange& rRange) const + { + return ( + maRangeX.overlapsMore(rRange.maRangeX) + && maRangeY.overlapsMore(rRange.maRangeY) + ); + } + + /// add point to the set, expanding as necessary + void expand(const B2ITuple& rTuple) + { + maRangeX.expand(rTuple.getX()); + maRangeY.expand(rTuple.getY()); + } + + /// add rRange to the set, expanding as necessary + void expand(const B2IRange& rRange) + { + maRangeX.expand(rRange.maRangeX); + maRangeY.expand(rRange.maRangeY); + } + + /// calc set intersection + void intersect(const B2IRange& rRange) + { + maRangeX.intersect(rRange.maRangeX); + maRangeY.intersect(rRange.maRangeY); + } + + /// grow set by nValue on all sides + void grow(sal_Int32 nValue) + { + maRangeX.grow(nValue); + maRangeY.grow(nValue); + } + + private: + typedef ::basegfx::BasicRange< ValueType, TraitsType > MyBasicRange; + + MyBasicRange maRangeX; + MyBasicRange maRangeY; + }; + + /** Compute the set difference of the two given ranges + + This method calculates the symmetric difference (aka XOR) + between the two given ranges, and returning the resulting + ranges. Thus, the result will contain all areas where one, but + not both ranges lie. + + @param o_rResult + Result vector. The up to four difference ranges are returned + within this vector + + @param rFirst + The first range + + @param rSecond + The second range + + @return the input vector + */ + BASEGFX_DLLPUBLIC ::std::vector< B2IRange >& computeSetDifference( ::std::vector< B2IRange >& o_rResult, + const B2IRange& rFirst, + const B2IRange& rSecond ); + +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_B2IRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b2irectangle.hxx b/include/basegfx/range/b2irectangle.hxx new file mode 100644 index 000000000000..40792732ab1d --- /dev/null +++ b/include/basegfx/range/b2irectangle.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B2IRECTANGLE_HXX +#define _BGFX_RANGE_B2IRECTANGLE_HXX + +#include <basegfx/range/b2irange.hxx> + +namespace basegfx +{ + // syntactic sugar: a B2IRange exactly models a Rectangle, thus, + // for interface clarity, we provide an alias name + + /// Alias name for interface clarity (not everybody is aware of the identity) + typedef B2IRange B2IRectangle; +} + +#endif /* _BGFX_RANGE_B2IRECTANGLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b3drange.hxx b/include/basegfx/range/b3drange.hxx new file mode 100644 index 000000000000..7b17f04e4964 --- /dev/null +++ b/include/basegfx/range/b3drange.hxx @@ -0,0 +1,273 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B3DRANGE_HXX +#define _BGFX_RANGE_B3DRANGE_HXX + +#include <basegfx/vector/b3dvector.hxx> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/range/basicrange.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclarations + class B3IRange; + class B3DHomMatrix; + + class B3DRange + { + typedef ::basegfx::BasicRange< double, DoubleTraits > MyBasicRange; + + MyBasicRange maRangeX; + MyBasicRange maRangeY; + MyBasicRange maRangeZ; + + public: + B3DRange() {} + + explicit B3DRange(const B3DTuple& rTuple) + : maRangeX(rTuple.getX()), + maRangeY(rTuple.getY()), + maRangeZ(rTuple.getZ()) + { + } + + B3DRange(double x1, + double y1, + double z1, + double x2, + double y2, + double z2) + : maRangeX(x1), + maRangeY(y1), + maRangeZ(z1) + { + maRangeX.expand(x2); + maRangeY.expand(y2); + maRangeZ.expand(z2); + } + + B3DRange(const B3DTuple& rTuple1, + const B3DTuple& rTuple2) + : maRangeX(rTuple1.getX()), + maRangeY(rTuple1.getY()), + maRangeZ(rTuple1.getZ()) + { + expand(rTuple2); + } + + bool isEmpty() const + { + return ( + maRangeX.isEmpty() + || maRangeY.isEmpty() + || maRangeZ.isEmpty() + ); + } + + void reset() + { + maRangeX.reset(); + maRangeY.reset(); + maRangeZ.reset(); + } + + bool operator==( const B3DRange& rRange ) const + { + return (maRangeX == rRange.maRangeX + && maRangeY == rRange.maRangeY + && maRangeZ == rRange.maRangeZ); + } + + bool operator!=( const B3DRange& rRange ) const + { + return (maRangeX != rRange.maRangeX + || maRangeY != rRange.maRangeY + || maRangeZ != rRange.maRangeZ); + } + + bool equal(const B3DRange& rRange) const + { + return (maRangeX.equal(rRange.maRangeX) + && maRangeY.equal(rRange.maRangeY) + && maRangeZ.equal(rRange.maRangeZ)); + } + + double getMinX() const + { + return maRangeX.getMinimum(); + } + + double getMinY() const + { + return maRangeY.getMinimum(); + } + + double getMinZ() const + { + return maRangeZ.getMinimum(); + } + + double getMaxX() const + { + return maRangeX.getMaximum(); + } + + double getMaxY() const + { + return maRangeY.getMaximum(); + } + + double getMaxZ() const + { + return maRangeZ.getMaximum(); + } + + double getWidth() const + { + return maRangeX.getRange(); + } + + double getHeight() const + { + return maRangeY.getRange(); + } + + double getDepth() const + { + return maRangeZ.getRange(); + } + + B3DPoint getMinimum() const + { + return B3DPoint( + maRangeX.getMinimum(), + maRangeY.getMinimum(), + maRangeZ.getMinimum() + ); + } + + B3DPoint getMaximum() const + { + return B3DPoint( + maRangeX.getMaximum(), + maRangeY.getMaximum(), + maRangeZ.getMaximum() + ); + } + + B3DVector getRange() const + { + return B3DVector( + maRangeX.getRange(), + maRangeY.getRange(), + maRangeZ.getRange() + ); + } + + B3DPoint getCenter() const + { + return B3DPoint( + maRangeX.getCenter(), + maRangeY.getCenter(), + maRangeZ.getCenter() + ); + } + + double getCenterX() const + { + return maRangeX.getCenter(); + } + + double getCenterY() const + { + return maRangeY.getCenter(); + } + + double getCenterZ() const + { + return maRangeZ.getCenter(); + } + + bool isInside(const B3DTuple& rTuple) const + { + return ( + maRangeX.isInside(rTuple.getX()) + && maRangeY.isInside(rTuple.getY()) + && maRangeZ.isInside(rTuple.getZ()) + ); + } + + bool isInside(const B3DRange& rRange) const + { + return ( + maRangeX.isInside(rRange.maRangeX) + && maRangeY.isInside(rRange.maRangeY) + && maRangeZ.isInside(rRange.maRangeZ) + ); + } + + bool overlaps(const B3DRange& rRange) const + { + return ( + maRangeX.overlaps(rRange.maRangeX) + && maRangeY.overlaps(rRange.maRangeY) + && maRangeZ.overlaps(rRange.maRangeZ) + ); + } + + void expand(const B3DTuple& rTuple) + { + maRangeX.expand(rTuple.getX()); + maRangeY.expand(rTuple.getY()); + maRangeZ.expand(rTuple.getZ()); + } + + void expand(const B3DRange& rRange) + { + maRangeX.expand(rRange.maRangeX); + maRangeY.expand(rRange.maRangeY); + maRangeZ.expand(rRange.maRangeZ); + } + + void intersect(const B3DRange& rRange) + { + maRangeX.intersect(rRange.maRangeX); + maRangeY.intersect(rRange.maRangeY); + maRangeZ.intersect(rRange.maRangeZ); + } + + void grow(double fValue) + { + maRangeX.grow(fValue); + maRangeY.grow(fValue); + maRangeZ.grow(fValue); + } + + BASEGFX_DLLPUBLIC void transform(const B3DHomMatrix& rMatrix); + }; + +} // end of namespace basegfx + + +#endif /* _BGFX_RANGE_B3DRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/b3irange.hxx b/include/basegfx/range/b3irange.hxx new file mode 100644 index 000000000000..558c2abb4d62 --- /dev/null +++ b/include/basegfx/range/b3irange.hxx @@ -0,0 +1,240 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_B3IRANGE_HXX +#define _BGFX_RANGE_B3IRANGE_HXX + +#include <basegfx/point/b3ipoint.hxx> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/tuple/b3ituple.hxx> +#include <basegfx/tuple/b3i64tuple.hxx> +#include <basegfx/range/basicrange.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B3IRange + { + typedef ::basegfx::BasicRange< sal_Int32, Int32Traits > MyBasicRange; + + MyBasicRange maRangeX; + MyBasicRange maRangeY; + MyBasicRange maRangeZ; + + public: + B3IRange() {} + + explicit B3IRange(const B3ITuple& rTuple) + : maRangeX(rTuple.getX()), + maRangeY(rTuple.getY()), + maRangeZ(rTuple.getZ()) + { + } + + B3IRange(sal_Int32 x1, + sal_Int32 y1, + sal_Int32 z1, + sal_Int32 x2, + sal_Int32 y2, + sal_Int32 z2) + : maRangeX(x1), + maRangeY(y1), + maRangeZ(z1) + { + maRangeX.expand(x2); + maRangeY.expand(y2); + maRangeZ.expand(z2); + } + + B3IRange(const B3ITuple& rTuple1, + const B3ITuple& rTuple2) + : maRangeX(rTuple1.getX()), + maRangeY(rTuple1.getY()), + maRangeZ(rTuple1.getZ()) + { + expand(rTuple2); + } + + bool isEmpty() const + { + return maRangeX.isEmpty() || maRangeY.isEmpty() || maRangeZ.isEmpty(); + } + + void reset() + { + maRangeX.reset(); + maRangeY.reset(); + maRangeZ.reset(); + } + + bool operator==( const B3IRange& rRange ) const + { + return (maRangeX == rRange.maRangeX + && maRangeY == rRange.maRangeY + && maRangeZ == rRange.maRangeZ); + } + + bool operator!=( const B3IRange& rRange ) const + { + return (maRangeX != rRange.maRangeX + || maRangeY != rRange.maRangeY + || maRangeZ != rRange.maRangeZ); + } + + sal_Int32 getMinX() const + { + return maRangeX.getMinimum(); + } + + sal_Int32 getMinY() const + { + return maRangeY.getMinimum(); + } + + sal_Int32 getMinZ() const + { + return maRangeZ.getMinimum(); + } + + sal_Int32 getMaxX() const + { + return maRangeX.getMaximum(); + } + + sal_Int32 getMaxY() const + { + return maRangeY.getMaximum(); + } + + sal_Int32 getMaxZ() const + { + return maRangeZ.getMaximum(); + } + + sal_Int64 getWidth() const + { + return maRangeX.getRange(); + } + + sal_Int64 getHeight() const + { + return maRangeY.getRange(); + } + + sal_Int64 getDepth() const + { + return maRangeZ.getRange(); + } + + B3IPoint getMinimum() const + { + return B3IPoint( + maRangeX.getMinimum(), + maRangeY.getMinimum(), + maRangeZ.getMinimum() + ); + } + + B3IPoint getMaximum() const + { + return B3IPoint( + maRangeX.getMaximum(), + maRangeY.getMaximum(), + maRangeZ.getMaximum() + ); + } + + B3I64Tuple getRange() const + { + return B3I64Tuple( + maRangeX.getRange(), + maRangeY.getRange(), + maRangeZ.getRange() + ); + } + + B3DPoint getCenter() const + { + return B3DPoint( + maRangeX.getCenter(), + maRangeY.getCenter(), + maRangeZ.getCenter() + ); + } + + bool isInside(const B3ITuple& rTuple) const + { + return ( + maRangeX.isInside(rTuple.getX()) + && maRangeY.isInside(rTuple.getY()) + && maRangeZ.isInside(rTuple.getZ()) + ); + } + + bool isInside(const B3IRange& rRange) const + { + return ( + maRangeX.isInside(rRange.maRangeX) + && maRangeY.isInside(rRange.maRangeY) + && maRangeZ.isInside(rRange.maRangeZ) + ); + } + + bool overlaps(const B3IRange& rRange) const + { + return ( + maRangeX.overlaps(rRange.maRangeX) + && maRangeY.overlaps(rRange.maRangeY) + && maRangeZ.overlaps(rRange.maRangeZ) + ); + } + + void expand(const B3ITuple& rTuple) + { + maRangeX.expand(rTuple.getX()); + maRangeY.expand(rTuple.getY()); + maRangeZ.expand(rTuple.getZ()); + } + + void expand(const B3IRange& rRange) + { + maRangeX.expand(rRange.maRangeX); + maRangeY.expand(rRange.maRangeY); + maRangeZ.expand(rRange.maRangeZ); + } + + void intersect(const B3IRange& rRange) + { + maRangeX.intersect(rRange.maRangeX); + maRangeY.intersect(rRange.maRangeY); + maRangeZ.intersect(rRange.maRangeZ); + } + + void grow(sal_Int32 nValue) + { + maRangeX.grow(nValue); + maRangeY.grow(nValue); + maRangeZ.grow(nValue); + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_B3IRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/basicbox.hxx b/include/basegfx/range/basicbox.hxx new file mode 100644 index 000000000000..bab84c17f89a --- /dev/null +++ b/include/basegfx/range/basicbox.hxx @@ -0,0 +1,127 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_BASICBOX_HXX +#define _BGFX_RANGE_BASICBOX_HXX + +#include <basegfx/range/basicrange.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** Explicitely different from BasicRange, handling the inside predicates + differently. + + This is modelled after how polygon fill algorithms set pixel - + typically excluding rightmost and bottommost ones. + */ + class BasicBox : public BasicRange< sal_Int32, Int32Traits > + { + typedef BasicRange< sal_Int32, Int32Traits > Base; + public: + BasicBox() {} + + explicit BasicBox( sal_Int32 nValue ) : + Base( nValue ) + { + } + + bool isEmpty() const + { + return mnMinimum >= mnMaximum; + } + + double getCenter() const + { + if(isEmpty()) + { + return 0.0; + } + else + { + return ((mnMaximum + mnMinimum - 1.0) / 2.0); + } + } + + using Base::isInside; + + bool isInside(sal_Int32 nValue) const + { + if(isEmpty()) + { + return false; + } + else + { + return (nValue >= mnMinimum) && (nValue < mnMaximum); + } + } + + using Base::overlaps; + + bool overlaps(const BasicBox& rBox) const + { + if(isEmpty()) + { + return false; + } + else + { + if(rBox.isEmpty()) + { + return false; + } + else + { + return !((rBox.mnMaximum <= mnMinimum) || (rBox.mnMinimum >= mnMaximum)); + } + } + } + + void grow(sal_Int32 nValue) + { + if(!isEmpty()) + { + bool bLessThanZero(nValue < 0); + + if(nValue > 0 || bLessThanZero) + { + mnMinimum -= nValue; + mnMaximum += nValue; + + if(bLessThanZero) + { + // test if range did collapse + if(mnMinimum > mnMaximum) + { + // if yes, collapse to center + mnMinimum = mnMaximum = ((mnMaximum + mnMinimum - 1) / 2); + } + } + } + } + } + }; + +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_BASICBOX_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/range/basicrange.hxx b/include/basegfx/range/basicrange.hxx new file mode 100644 index 000000000000..51b5593ae61d --- /dev/null +++ b/include/basegfx/range/basicrange.hxx @@ -0,0 +1,278 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RANGE_BASICRANGE_HXX +#define _BGFX_RANGE_BASICRANGE_HXX + +#include <sal/types.h> +#include <float.h> +#include <basegfx/numeric/ftools.hxx> + + +namespace basegfx +{ + template< typename T, typename Traits > class BasicRange + { + protected: + T mnMinimum; + T mnMaximum; + + public: + typedef T ValueType; + typedef Traits TraitsType; + + BasicRange() : + mnMinimum(Traits::maxVal()), + mnMaximum(Traits::minVal()) + { + } + + explicit BasicRange( T nValue ) : + mnMinimum(nValue), + mnMaximum(nValue) + { + } + + void reset() + { + mnMinimum = Traits::maxVal(); + mnMaximum = Traits::minVal(); + } + + bool isEmpty() const + { + return Traits::maxVal() == mnMinimum; + } + + T getMinimum() const { return mnMinimum; } + T getMaximum() const { return mnMaximum; } + + double getCenter() const + { + if(isEmpty()) + { + return 0.0; + } + else + { + return ((mnMaximum + mnMinimum) / 2.0); + } + } + + bool isInside(T nValue) const + { + if(isEmpty()) + { + return false; + } + else + { + return (nValue >= mnMinimum) && (nValue <= mnMaximum); + } + } + + bool isInside(const BasicRange& rRange) const + { + if(isEmpty()) + { + return false; + } + else + { + if(rRange.isEmpty()) + { + return false; + } + else + { + return (rRange.mnMinimum >= mnMinimum) && (rRange.mnMaximum <= mnMaximum); + } + } + } + + bool overlaps(const BasicRange& rRange) const + { + if(isEmpty()) + { + return false; + } + else + { + if(rRange.isEmpty()) + { + return false; + } + else + { + return !((rRange.mnMaximum < mnMinimum) || (rRange.mnMinimum > mnMaximum)); + } + } + } + + bool overlapsMore(const BasicRange& rRange) const + { + if(isEmpty() || rRange.isEmpty()) + return false; + // returns true if the overlap is more than just a touching at the limits + return ((rRange.mnMaximum > mnMinimum) && (rRange.mnMinimum < mnMaximum)); + } + + bool operator==( const BasicRange& rRange ) const + { + return (mnMinimum == rRange.mnMinimum && mnMaximum == rRange.mnMaximum); + } + + bool operator!=( const BasicRange& rRange ) const + { + return (mnMinimum != rRange.mnMinimum || mnMaximum != rRange.mnMaximum); + } + + bool equal(const BasicRange& rRange) const + { + return ( + fTools::equal(mnMinimum, rRange.mnMinimum) && + fTools::equal(mnMaximum, rRange.mnMaximum)); + } + + void expand(T nValue) + { + if(isEmpty()) + { + mnMinimum = mnMaximum = nValue; + } + else + { + if(nValue < mnMinimum) + { + mnMinimum = nValue; + } + + if(nValue > mnMaximum) + { + mnMaximum = nValue; + } + } + } + + void expand(const BasicRange& rRange) + { + if(isEmpty()) + { + mnMinimum = rRange.mnMinimum; + mnMaximum = rRange.mnMaximum; + } + else + { + if(!rRange.isEmpty()) + { + if(rRange.mnMinimum < mnMinimum) + { + mnMinimum = rRange.mnMinimum; + } + + if(rRange.mnMaximum > mnMaximum) + { + mnMaximum = rRange.mnMaximum; + } + } + } + } + + void intersect(const BasicRange& rRange) + { + // here, overlaps also tests all isEmpty() conditions already. + if( !overlaps( rRange ) ) + { + reset(); + } + else + { + if(rRange.mnMinimum > mnMinimum) + { + mnMinimum = rRange.mnMinimum; + } + + if(rRange.mnMaximum < mnMaximum) + { + mnMaximum = rRange.mnMaximum; + } + } + } + + void grow(T nValue) + { + if(!isEmpty()) + { + bool bLessThanZero(nValue < 0); + + if(nValue > 0 || bLessThanZero) + { + mnMinimum -= nValue; + mnMaximum += nValue; + + if(bLessThanZero) + { + // test if range did collapse + if(mnMinimum > mnMaximum) + { + // if yes, collapse to center + mnMinimum = mnMaximum = (mnMinimum + mnMaximum) / 2; + } + } + } + } + } + + typename Traits::DifferenceType getRange() const + { + if(isEmpty()) + { + return Traits::neutral(); + } + else + { + return (mnMaximum - mnMinimum); + } + } + }; + + // some pre-fabricated traits + struct DoubleTraits + { + static double minVal() { return DBL_MIN; }; + static double maxVal() { return DBL_MAX; }; + static double neutral() { return 0.0; }; + + typedef double DifferenceType; + }; + + struct Int32Traits + { + static sal_Int32 minVal() { return SAL_MIN_INT32; }; + static sal_Int32 maxVal() { return SAL_MAX_INT32; }; + static sal_Int32 neutral() { return 0L; }; + + typedef sal_Int64 DifferenceType; + }; + +} // end of namespace basegfx + +#endif /* _BGFX_RANGE_BASICRANGE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/raster/bpixelraster.hxx b/include/basegfx/raster/bpixelraster.hxx new file mode 100644 index 000000000000..ed7ac931d805 --- /dev/null +++ b/include/basegfx/raster/bpixelraster.hxx @@ -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 . + */ + +#ifndef _BGFX_RASTER_BPIXELRASTER_HXX +#define _BGFX_RASTER_BPIXELRASTER_HXX + +#include <algorithm> +#include <string.h> +#include <sal/types.h> +#include <basegfx/pixel/bpixel.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BPixelRaster + { + private: + // do not allow copy constructor and assignment operator + BPixelRaster(const BPixelRaster&); + BPixelRaster& operator=(const BPixelRaster&); + + protected: + sal_uInt32 mnWidth; + sal_uInt32 mnHeight; + sal_uInt32 mnCount; + BPixel* mpContent; + + public: + // reset + void reset() + { + memset(mpContent, 0, sizeof(BPixel) * mnCount); + } + + // constructor/destructor + BPixelRaster(sal_uInt32 nWidth, sal_uInt32 nHeight) + : mnWidth(nWidth), + mnHeight(nHeight), + mnCount(nWidth * nHeight), + mpContent(new BPixel[mnCount]) + { + reset(); + } + + ~BPixelRaster() + { + delete [] mpContent; + } + + // coordinate calcs between X/Y and span + sal_uInt32 getIndexFromXY(sal_uInt32 nX, sal_uInt32 nY) const { return (nX + (nY * mnWidth)); } + sal_uInt32 getXFromIndex(sal_uInt32 nIndex) const { return (nIndex % mnWidth); } + sal_uInt32 getYFromIndex(sal_uInt32 nIndex) const { return (nIndex / mnWidth); } + + // data access read + sal_uInt32 getWidth() const { return mnWidth; } + sal_uInt32 getHeight() const { return mnHeight; } + sal_uInt32 getCount() const { return mnCount; } + + // data access read only + const BPixel& getBPixel(sal_uInt32 nIndex) const + { + assert(nIndex < mnCount); //Access out of range + return mpContent[nIndex]; + } + + // data access read/write + BPixel& getBPixel(sal_uInt32 nIndex) + { + assert(nIndex < mnCount); //Access out of range + return mpContent[nIndex]; + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_RASTER_BPIXELRASTER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/raster/bzpixelraster.hxx b/include/basegfx/raster/bzpixelraster.hxx new file mode 100644 index 000000000000..ddd4f1e56cb0 --- /dev/null +++ b/include/basegfx/raster/bzpixelraster.hxx @@ -0,0 +1,90 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RASTER_BZPIXELRASTER_HXX +#define _BGFX_RASTER_BZPIXELRASTER_HXX + +#include <basegfx/raster/bpixelraster.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BZPixelRaster : public BPixelRaster + { + protected: + // additionally, host a ZBuffer + sal_uInt16* mpZBuffer; + + public: + // reset + void resetZ() + { + reset(); + memset(mpZBuffer, 0, sizeof(sal_uInt16) * mnCount); + } + + // constructor/destructor + BZPixelRaster(sal_uInt32 nWidth, sal_uInt32 nHeight) + : BPixelRaster(nWidth, nHeight), + mpZBuffer(new sal_uInt16[mnCount]) + { + memset(mpZBuffer, 0, sizeof(sal_uInt16) * mnCount); + } + + ~BZPixelRaster() + { + delete [] mpZBuffer; + } + + // data access read only + const sal_uInt16& getZ(sal_uInt32 nIndex) const + { +#ifdef DBG_UTIL + if(nIndex >= mnCount) + { + OSL_FAIL("getZ: Access out of range (!)"); + return mpZBuffer[0L]; + } +#endif + return mpZBuffer[nIndex]; + } + + // data access read/write + sal_uInt16& getZ(sal_uInt32 nIndex) + { +#ifdef DBG_UTIL + if(nIndex >= mnCount) + { + OSL_FAIL("getZ: Access out of range (!)"); + return mpZBuffer[0L]; + } +#endif + return mpZBuffer[nIndex]; + } + }; +} // end of namespace basegfx + +#endif /* _BGFX_RASTER_BZPIXELRASTER_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/raster/rasterconvert3d.hxx b/include/basegfx/raster/rasterconvert3d.hxx new file mode 100644 index 000000000000..1bfbe20b1cf0 --- /dev/null +++ b/include/basegfx/raster/rasterconvert3d.hxx @@ -0,0 +1,340 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_RASTER_RASTERCONVERT3D_HXX +#define _BGFX_RASTER_RASTERCONVERT3D_HXX + +#include <sal/types.h> +#include <vector> +#include <basegfx/color/bcolor.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +namespace basegfx +{ + class B3DPolygon; + class B3DPolyPolygon; +} + +////////////////////////////////////////////////////////////////////////////// +// interpolators for double precision + +namespace basegfx +{ + class ip_single + { + private: + double mfVal; + double mfInc; + + public: + ip_single() + : mfVal(0.0), + mfInc(0.0) + {} + + ip_single(double fVal, double fInc) + : mfVal(fVal), + mfInc(fInc) + {} + + double getVal() const { return mfVal; } + double getInc() const { return mfInc; } + + void increment(double fStep) { mfVal += fStep * mfInc; } + }; +} // end of namespace basegfx + +namespace basegfx +{ + class ip_double + { + private: + ip_single maX; + ip_single maY; + + public: + ip_double() + : maX(), + maY() + {} + + ip_double(double fXVal, double fXInc, double fYVal, double fYInc) + : maX(fXVal, fXInc), + maY(fYVal, fYInc) + {} + + const ip_single& getX() const { return maX; } + const ip_single& getY() const { return maY; } + + void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); } + }; +} // end of namespace basegfx + +namespace basegfx +{ + class ip_triple + { + private: + ip_single maX; + ip_single maY; + ip_single maZ; + + public: + ip_triple() + : maX(), + maY(), + maZ() + {} + + ip_triple(double fXVal, double fXInc, double fYVal, double fYInc, double fZVal, double fZInc) + : maX(fXVal, fXInc), + maY(fYVal, fYInc), + maZ(fZVal, fZInc) + {} + + const ip_single& getX() const { return maX; } + const ip_single& getY() const { return maY; } + const ip_single& getZ() const { return maZ; } + + void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); maZ.increment(fStep); } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// +// InterpolatorProvider3D to have a common source for allocating interpolators +// which may then be addressed using the index to the vectors + +namespace basegfx +{ + #define SCANLINE_EMPTY_INDEX (0xffffffff) + + class InterpolatorProvider3D + { + private: + ::std::vector< ip_triple > maColorInterpolators; + ::std::vector< ip_triple > maNormalInterpolators; + ::std::vector< ip_double > maTextureInterpolators; + ::std::vector< ip_triple > maInverseTextureInterpolators; + + protected: + sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta) + { + B3DVector aDelta(rB.getRed() - rA.getRed(), rB.getGreen() - rA.getGreen(), rB.getBlue() - rA.getBlue()); + aDelta *= fInvYDelta; + maColorInterpolators.push_back(ip_triple(rA.getRed(), aDelta.getX(), rA.getGreen(), aDelta.getY(), rA.getBlue(), aDelta.getZ())); + return (maColorInterpolators.size() - 1L); + } + + sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta) + { + B3DVector aDelta(rB.getX() - rA.getX(), rB.getY() - rA.getY(), rB.getZ() - rA.getZ()); + aDelta *= fInvYDelta; + maNormalInterpolators.push_back(ip_triple(rA.getX(), aDelta.getX(), rA.getY(), aDelta.getY(), rA.getZ(), aDelta.getZ())); + return (maNormalInterpolators.size() - 1L); + } + + sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta) + { + B2DVector aDelta(rB.getX() - rA.getX(), rB.getY() - rA.getY()); + aDelta *= fInvYDelta; + maTextureInterpolators.push_back(ip_double(rA.getX(), aDelta.getX(), rA.getY(), aDelta.getY())); + return (maTextureInterpolators.size() - 1L); + } + + sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta) + { + const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA); + const double fInvZEyeB(fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB); + const B2DPoint aInvA(rA * fInvZEyeA); + const B2DPoint aInvB(rB * fInvZEyeB); + double fZDelta(fInvZEyeB - fInvZEyeA); + B2DVector aDelta(aInvB.getX() - aInvA.getX(), aInvB.getY() - aInvA.getY()); + + fZDelta *= fInvYDelta; + aDelta *= fInvYDelta; + + maInverseTextureInterpolators.push_back(ip_triple(aInvA.getX(), aDelta.getX(), aInvA.getY(), aDelta.getY(), fInvZEyeA, fZDelta)); + return (maInverseTextureInterpolators.size() - 1L); + } + + void reset() + { + maColorInterpolators.clear(); + maNormalInterpolators.clear(); + maTextureInterpolators.clear(); + maInverseTextureInterpolators.clear(); + } + + public: + InterpolatorProvider3D() {} + + ::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; } + ::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; } + ::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; } + ::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// +// RasterConversionLineEntry3D for Raterconversion of 3D PolyPolygons + +namespace basegfx +{ + class RasterConversionLineEntry3D + { + private: + ip_single maX; + ip_single maZ; + sal_Int32 mnY; + sal_uInt32 mnCount; + + sal_uInt32 mnColorIndex; + sal_uInt32 mnNormalIndex; + sal_uInt32 mnTextureIndex; + sal_uInt32 mnInverseTextureIndex; + + public: + RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount) + : maX(rfX, rfDeltaX), + maZ(rfZ, rfDeltaZ), + mnY(nY), + mnCount(nCount), + mnColorIndex(SCANLINE_EMPTY_INDEX), + mnNormalIndex(SCANLINE_EMPTY_INDEX), + mnTextureIndex(SCANLINE_EMPTY_INDEX), + mnInverseTextureIndex(SCANLINE_EMPTY_INDEX) + {} + + void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; } + void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; } + void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; } + void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; } + + bool operator<(const RasterConversionLineEntry3D& rComp) const + { + if(mnY == rComp.mnY) + { + return maX.getVal() < rComp.maX.getVal(); + } + + return mnY < rComp.mnY; + } + + bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep) + { + if(nStep >= mnCount) + { + return false; + } + else + { + mnCount -= nStep; + return true; + } + } + + void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider) + { + const double fStep((double)nStep); + maX.increment(fStep); + maZ.increment(fStep); + mnY += nStep; + + if(SCANLINE_EMPTY_INDEX != mnColorIndex) + { + rProvider.getColorInterpolators()[mnColorIndex].increment(fStep); + } + + if(SCANLINE_EMPTY_INDEX != mnNormalIndex) + { + rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep); + } + + if(SCANLINE_EMPTY_INDEX != mnTextureIndex) + { + rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep); + } + + if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex) + { + rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep); + } + } + + // data read access + const ip_single& getX() const { return maX; } + sal_Int32 getY() const { return mnY; } + const ip_single& getZ() const { return maZ; } + sal_uInt32 getColorIndex() const { return mnColorIndex; } + sal_uInt32 getNormalIndex() const { return mnNormalIndex; } + sal_uInt32 getTextureIndex() const { return mnTextureIndex; } + sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// +// the basic RaterConverter itself. Only one method needs to be overloaded. The +// class itself is strictly virtual + +namespace basegfx +{ + class BASEGFX_DLLPUBLIC RasterConverter3D : public InterpolatorProvider3D + { + private: + // the line entries for an area conversion run + ::std::vector< RasterConversionLineEntry3D > maLineEntries; + + struct lineComparator + { + bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB) + { + OSL_ENSURE(pA && pB, "lineComparator: empty pointer (!)"); + return pA->getX().getVal() < pB->getX().getVal(); + } + }; + + void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye); + void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye); + void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye); + + void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine); + void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth); + + virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0; + + public: + RasterConverter3D(); + virtual ~RasterConverter3D(); + + void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine); + void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth); + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_RASTER_RASTERCONVERT3D_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/b2dclipstate.hxx b/include/basegfx/tools/b2dclipstate.hxx new file mode 100644 index 000000000000..f1d750ae636b --- /dev/null +++ b/include/basegfx/tools/b2dclipstate.hxx @@ -0,0 +1,94 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TOOLS_CLIPSTATE_HXX +#define _BGFX_TOOLS_CLIPSTATE_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B2DRange; + class B2DPolyRange; + class B2DPolygon; + class B2DPolyPolygon; + + namespace tools + { + 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& ); + explicit B2DClipState( const B2DPolyPolygon& ); + B2DClipState& operator=( const 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& ); + + B2DPolyPolygon getClipPoly() const; + }; + } +} + +#endif // _BGFX_TOOLS_CLIPSTATE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/canvastools.hxx b/include/basegfx/tools/canvastools.hxx new file mode 100644 index 000000000000..819a62e47b28 --- /dev/null +++ b/include/basegfx/tools/canvastools.hxx @@ -0,0 +1,205 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TOOLS_CANVASTOOLS_HXX +#define _BGFX_TOOLS_CANVASTOOLS_HXX + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace com { namespace sun { namespace star { namespace geometry +{ + struct AffineMatrix2D; + struct AffineMatrix3D; + struct Matrix2D; + struct RealPoint2D; + struct RealSize2D; + struct RealRectangle2D; + struct RealRectangle3D; + struct IntegerPoint2D; + struct IntegerSize2D; + struct IntegerRectangle2D; + struct RealBezierSegment2D; +} } } } + +namespace com { namespace sun { namespace star { namespace rendering +{ + class XGraphicDevice; + class XPolyPolygon2D; +} } } } + +namespace com { namespace sun { namespace star { namespace awt +{ + struct Point; + struct Size; + struct Rectangle; +} } } } + +namespace basegfx +{ + class B2DHomMatrix; + class B3DHomMatrix; + class B2DVector; + class B2DPoint; + class B2DRange; + class B3DRange; + class B2IBox; + class B2IVector; + class B2IPoint; + class B2IRange; + class B2DPolygon; + class B2DPolyPolygon; + + namespace unotools + { + // Polygon conversions + // =================================================================== + + BASEGFX_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > + xPolyPolygonFromB2DPolygon( const ::com::sun::star::uno::Reference< + ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice, + const ::basegfx::B2DPolygon& rPoly ); + + BASEGFX_DLLPUBLIC ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D > + xPolyPolygonFromB2DPolyPolygon( const ::com::sun::star::uno::Reference< + ::com::sun::star::rendering::XGraphicDevice >& xGraphicDevice, + const ::basegfx::B2DPolyPolygon& rPolyPoly ); + + + BASEGFX_DLLPUBLIC ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< + ::com::sun::star::geometry::RealBezierSegment2D > > + bezierSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ); + + BASEGFX_DLLPUBLIC ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< + ::com::sun::star::geometry::RealPoint2D > > + pointSequenceSequenceFromB2DPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolygon polygonFromPoint2DSequence( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::geometry::RealPoint2D >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolyPolygon polyPolygonFromPoint2DSequenceSequence( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolygon polygonFromBezier2DSequence( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::geometry::RealBezierSegment2D >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolyPolygon polyPolygonFromBezier2DSequenceSequence( + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealBezierSegment2D > >& rPoints ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPolyPolygon b2DPolyPolygonFromXPolyPolygon2D( + const ::com::sun::star::uno::Reference< + ::com::sun::star::rendering::XPolyPolygon2D >& rPoly ); + + // Matrix conversions + // =================================================================== + + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::AffineMatrix2D& + affineMatrixFromHomMatrix( ::com::sun::star::geometry::AffineMatrix2D& matrix, + const ::basegfx::B2DHomMatrix& transform); + + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::AffineMatrix3D& affineMatrixFromHomMatrix3D( + ::com::sun::star::geometry::AffineMatrix3D& matrix, + const ::basegfx::B3DHomMatrix& transform); + + BASEGFX_DLLPUBLIC ::basegfx::B2DHomMatrix& + homMatrixFromAffineMatrix( ::basegfx::B2DHomMatrix& transform, + const ::com::sun::star::geometry::AffineMatrix2D& matrix ); + + BASEGFX_DLLPUBLIC ::basegfx::B3DHomMatrix homMatrixFromAffineMatrix3D( const ::com::sun::star::geometry::AffineMatrix3D& matrix ); + + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::Matrix2D& + matrixFromHomMatrix( ::com::sun::star::geometry::Matrix2D& matrix, + const ::basegfx::B2DHomMatrix& transform); + + BASEGFX_DLLPUBLIC ::basegfx::B2DHomMatrix& + homMatrixFromMatrix( ::basegfx::B2DHomMatrix& transform, + const ::com::sun::star::geometry::Matrix2D& matrix ); + + // Geometry conversions + // =================================================================== + + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::RealSize2D size2DFromB2DSize( const ::basegfx::B2DVector& ); + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::RealPoint2D point2DFromB2DPoint( const ::basegfx::B2DPoint& ); + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::RealRectangle2D rectangle2DFromB2DRectangle( const ::basegfx::B2DRange& ); + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::RealRectangle3D rectangle3DFromB3DRectangle( const ::basegfx::B3DRange& ); + + BASEGFX_DLLPUBLIC ::basegfx::B2DPoint b2DPointFromRealPoint2D( const ::com::sun::star::geometry::RealPoint2D& ); + BASEGFX_DLLPUBLIC ::basegfx::B2DRange b2DRectangleFromRealRectangle2D( const ::com::sun::star::geometry::RealRectangle2D& ); + BASEGFX_DLLPUBLIC ::basegfx::B3DRange b3DRectangleFromRealRectangle3D( const ::com::sun::star::geometry::RealRectangle3D& ); + + BASEGFX_DLLPUBLIC ::com::sun::star::geometry::IntegerSize2D integerSize2DFromB2ISize( const ::basegfx::B2IVector& ); + + BASEGFX_DLLPUBLIC ::basegfx::B2IVector b2ISizeFromIntegerSize2D( const ::com::sun::star::geometry::IntegerSize2D& ); + BASEGFX_DLLPUBLIC ::basegfx::B2IRange b2IRectangleFromIntegerRectangle2D( const ::com::sun::star::geometry::IntegerRectangle2D& ); + + BASEGFX_DLLPUBLIC ::basegfx::B2IRange b2IRectangleFromAwtRectangle( const ::com::sun::star::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 integer box, 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 box, which completely contains + rRange. Note that this box will contain all pixel affected + by a polygon fill operation over the input range. + */ + BASEGFX_DLLPUBLIC ::basegfx::B2IBox b2ISurroundingBoxFromB2DRange( 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 ); + + } +} + +#endif /* _BGFX_TOOLS_CANVASTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/gradienttools.hxx b/include/basegfx/tools/gradienttools.hxx new file mode 100644 index 000000000000..aa7479d2c369 --- /dev/null +++ b/include/basegfx/tools/gradienttools.hxx @@ -0,0 +1,405 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TOOLS_GRADIENTTOOLS_HXX +#define _BGFX_TOOLS_GRADIENTTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/basegfxdllapi.h> + +#include <vector> +#include <algorithm> + +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. + */ + struct BASEGFX_DLLPUBLIC ODFGradientInfo + { + /** 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 mnSteps; + }; + + namespace tools + { + /** 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 nSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo& createLinearODFGradientInfo(ODFGradientInfo& o_rGradientInfo, + const B2DRange& rTargetArea, + sal_uInt32 nSteps, + 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 + */ + inline double getLinearGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo ) + { + const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV); + const double t(clamp(aCoor.getY(), 0.0, 1.0)); + const sal_uInt32 nSteps(rGradInfo.mnSteps); + + if(nSteps > 2L && nSteps < 128L) + return floor(t * nSteps) / double(nSteps + 1L); + + return t; + } + + /** 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 nSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo& createAxialODFGradientInfo(ODFGradientInfo& o_rGradientInfo, + const B2DRange& rTargetArea, + sal_uInt32 nSteps, + 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 + */ + inline double getAxialGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo ) + { + const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV); + const double t(clamp(fabs(aCoor.getY()), 0.0, 1.0)); + const sal_uInt32 nSteps(rGradInfo.mnSteps); + const double fInternalSteps((nSteps * 2L) - 1L); + + if(nSteps > 2L && nSteps < 128L) + return floor(((t * fInternalSteps) + 1.0) / 2.0) / double(nSteps - 1L); + + return t; + } + + /** 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 nSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo& createRadialODFGradientInfo(ODFGradientInfo& o_rGradientInfo, + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nSteps, + 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 + */ + inline double getRadialGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo ) + { + const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV); + const double fDist( + clamp(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY(), + 0.0, + 1.0)); + + const double t(1.0 - sqrt(fDist)); + const sal_uInt32 nSteps(rGradInfo.mnSteps); + + if(nSteps > 2L && nSteps < 128L) + return floor(t * nSteps) / double(nSteps - 1L); + + return t; + } + + /** 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 nSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo& createEllipticalODFGradientInfo(ODFGradientInfo& o_rGradientInfo, + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nSteps, + 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 + */ + inline double getEllipticalGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo ) + { + return getRadialGradientAlpha(rUV,rGradInfo); // only matrix setup differs + } + + /** 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 nSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo& createSquareODFGradientInfo(ODFGradientInfo& o_rGradientInfo, + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nSteps, + 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 + */ + inline double getSquareGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo ) + { + const B2DPoint aCoor(rGradInfo.maBackTextureTransform * rUV); + const double fAbsX(fabs(aCoor.getX())); + const double fAbsY(fabs(aCoor.getY())); + + if(fTools::moreOrEqual(fAbsX, 1.0) || fTools::moreOrEqual(fAbsY, 1.0)) + return 0.0; + + const double t(1.0 - (fAbsX > fAbsY ? fAbsX : fAbsY)); + const sal_uInt32 nSteps(rGradInfo.mnSteps); + + if(nSteps > 2L && nSteps < 128L) + return floor(t * nSteps) / double(nSteps - 1L); + + return t; + } + + /** 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 nSteps + Number of gradient steps (from ODF) + + @param fBorder + Width of gradient border (from ODF) + + @param fAngle + Gradient angle (from ODF) + */ + BASEGFX_DLLPUBLIC ODFGradientInfo& createRectangularODFGradientInfo(ODFGradientInfo& o_rGradientInfo, + const B2DRange& rTargetArea, + const B2DVector& rOffset, + sal_uInt32 nSteps, + 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 + */ + inline double getRectangularGradientAlpha(const B2DPoint& rUV, + const ODFGradientInfo& rGradInfo ) + { + return getSquareGradientAlpha(rUV, rGradInfo); // only matrix setup differs + } + } +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/keystoplerp.hxx b/include/basegfx/tools/keystoplerp.hxx new file mode 100644 index 000000000000..8d6d41af63d9 --- /dev/null +++ b/include/basegfx/tools/keystoplerp.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 . + */ + +#ifndef _BGFX_TOOLS_KEYSTOPLERP_HXX +#define _BGFX_TOOLS_KEYSTOPLERP_HXX + +#include <basegfx/numeric/ftools.hxx> +#include <vector> +#include <basegfx/basegfxdllapi.h> + +namespace com{ namespace sun{ namespace star{ namespace uno { + template<typename T> class Sequence; +}}}} + +namespace basegfx +{ + namespace tools + { + /** 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 preferrably 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 std::vector<double>& rKeyStops ); + + /** Create lerper with given sequence of stops + + @param rKeyStops + + Sequence of stops, must contain at least two elements + (though preferrably 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 ::com::sun::star::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; + }; + } +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/lerp.hxx b/include/basegfx/tools/lerp.hxx new file mode 100644 index 000000000000..a0c0d714a295 --- /dev/null +++ b/include/basegfx/tools/lerp.hxx @@ -0,0 +1,51 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TOOLS_LERP_HXX +#define _BGFX_TOOLS_LERP_HXX + +#include <sal/types.h> + +namespace basegfx +{ + namespace tools + { + /** 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 ); + } + } +} + +#endif /* _BGFX_TOOLS_LERP_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/rectcliptools.hxx b/include/basegfx/tools/rectcliptools.hxx new file mode 100644 index 000000000000..3d5f77e18e0e --- /dev/null +++ b/include/basegfx/tools/rectcliptools.hxx @@ -0,0 +1,96 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TOOLS_RECTCLIPTOOLS_HXX +#define _BGFX_TOOLS_RECTCLIPTOOLS_HXX + +#include <sal/types.h> +#include <basegfx/range/b2ibox.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + namespace RectClipFlags + { + static const sal_uInt32 LEFT = (sal_Int32)0x01; + static const sal_uInt32 RIGHT = (sal_Int32)0x02; + static const sal_uInt32 TOP = (sal_Int32)0x04; + static 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 = (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 = (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; + } + + /** Determine number of clip planes hit by given clip mask + + This method returns the number of one bits in the four + least significant bits of the argument, which amounts to + the number of clip planes hit within the + getCohenSutherlandClipFlags() method. + */ + inline sal_uInt32 getNumberOfClipPlanes( sal_uInt32 nFlags ) + { + // classic bit count algo, see e.g. Reingold, Nievergelt, + // Deo: Combinatorial Algorithms, Theory and Practice, + // Prentice-Hall 1977 + nFlags = (nFlags & 0x05) + ((nFlags >> 1) & 0x05); + nFlags = (nFlags & 0x03) + (nFlags >> 2); // no need for & + // 0x03, can't + // overflow + return nFlags; + } + } +} + +#endif // _BGFX_TOOLS_RECTCLIPTOOLS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/tools.hxx b/include/basegfx/tools/tools.hxx new file mode 100644 index 000000000000..c1fa0940ae35 --- /dev/null +++ b/include/basegfx/tools/tools.hxx @@ -0,0 +1,102 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TOOLS_TOOLS_HXX +#define _BGFX_TOOLS_TOOLS_HXX + +#include <sal/types.h> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B2DPoint; + class B2DRange; + + namespace tools + { + /** 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 ); + + } +} + +#endif /* _BGFX_TOOLS_TOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/unopolypolygon.hxx b/include/basegfx/tools/unopolypolygon.hxx new file mode 100644 index 000000000000..72ed9418663a --- /dev/null +++ b/include/basegfx/tools/unopolypolygon.hxx @@ -0,0 +1,110 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_BASEGFX_UNOPOLYPOLYGON_HXX +#define INCLUDED_BASEGFX_UNOPOLYPOLYGON_HXX + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase3.hxx> +#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 <boost/utility.hpp> + + +namespace basegfx +{ +namespace unotools +{ + typedef ::cppu::WeakComponentImplHelper3< + ::com::sun::star::rendering::XLinePolyPolygon2D, + ::com::sun::star::rendering::XBezierPolyPolygon2D, + ::com::sun::star::lang::XServiceInfo > UnoPolyPolygonBase; + + class BASEGFX_DLLPUBLIC UnoPolyPolygon + : private cppu::BaseMutex + , private boost::noncopyable + , public UnoPolyPolygonBase + { + public: + explicit UnoPolyPolygon( const B2DPolyPolygon& ); + + // XPolyPolygon2D + virtual void SAL_CALL addPolyPolygon( const ::com::sun::star::geometry::RealPoint2D& position, const ::com::sun::star::uno::Reference< ::com::sun::star::rendering::XPolyPolygon2D >& polyPolygon ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getNumberOfPolygons( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getNumberOfPolygonPoints( ::sal_Int32 polygon ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::rendering::FillRule SAL_CALL getFillRule( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFillRule( ::com::sun::star::rendering::FillRule fillRule ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Bool SAL_CALL isClosed( ::sal_Int32 index ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setClosed( ::sal_Int32 index, ::sal_Bool closedState ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XLinePolyPolygon2D + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > > SAL_CALL getPoints( ::sal_Int32 nPolygonIndex, ::sal_Int32 nNumberOfPolygons, ::sal_Int32 nPointIndex, ::sal_Int32 nNumberOfPoints ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPoints( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealPoint2D > >& points, ::sal_Int32 nPolygonIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::geometry::RealPoint2D SAL_CALL getPoint( ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPoint( const ::com::sun::star::geometry::RealPoint2D& point, ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XBezierPolyPolygon2D + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealBezierSegment2D > > SAL_CALL getBezierSegments( ::sal_Int32 nPolygonIndex, ::sal_Int32 nNumberOfPolygons, ::sal_Int32 nPointIndex, ::sal_Int32 nNumberOfPoints ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBezierSegments( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::geometry::RealBezierSegment2D > >& points, ::sal_Int32 nPolygonIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::geometry::RealBezierSegment2D SAL_CALL getBezierSegment( ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setBezierSegment( const ::com::sun::star::geometry::RealBezierSegment2D& point, ::sal_Int32 nPolygonIndex, ::sal_Int32 nPointIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException ); + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException ); + + B2DPolyPolygon getPolyPolygon() const; + + protected: + /// Check whether index is a valid polygon index + void checkIndex( sal_Int32 nIndex ) const // throw (::com::sun::star::lang::IndexOutOfBoundsException); + { + if( nIndex < 0 || nIndex >= static_cast<sal_Int32>(maPolyPoly.count()) ) + throw ::com::sun::star::lang::IndexOutOfBoundsException(); + } + + 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. + B2DPolyPolygon getPolyPolygonUnsafe() const + { + return maPolyPoly; + } + + /// Called whenever internal polypolygon gets modified + virtual void modifying() const {} + + private: + B2DPolyPolygon maPolyPoly; + ::com::sun::star::rendering::FillRule meFillRule; + }; +} +} + +#endif /* INCLUDED_BASEGFX_UNOPOLYPOLYGON_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/unotools.hxx b/include/basegfx/tools/unotools.hxx new file mode 100644 index 000000000000..c95eb5361f5c --- /dev/null +++ b/include/basegfx/tools/unotools.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_BASEGFX_UNOTOOLS_HXX +#define INCLUDED_BASEGFX_UNOTOOLS_HXX + +#include <cppuhelper/basemutex.hxx> +#include <cppuhelper/compbase3.hxx> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.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> + + +namespace basegfx +{ +class B2DPolyPolygon; + +namespace unotools +{ + + BASEGFX_DLLPUBLIC B2DPolyPolygon polyPolygonBezierToB2DPolyPolygon(const ::com::sun::star::drawing::PolyPolygonBezierCoords& rSourcePolyPolygon) + throw( ::com::sun::star::lang::IllegalArgumentException ); + + BASEGFX_DLLPUBLIC void b2DPolyPolygonToPolyPolygonBezier( const B2DPolyPolygon& rPolyPoly, + ::com::sun::star::drawing::PolyPolygonBezierCoords& rRetval ); +} +} + +#endif /* INCLUDED_BASEGFX_UNOTOOLS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tools/zoomtools.hxx b/include/basegfx/tools/zoomtools.hxx new file mode 100644 index 000000000000..44d9052a2552 --- /dev/null +++ b/include/basegfx/tools/zoomtools.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Version: MPL 1.1 / GPLv3+ / LGPLv3+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2012 Tim Hardeck <thardeck@suse.com> + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 3 or later (the "GPLv3+"), or + * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"), + * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable + * instead of those above. + */ + +#ifndef _BGFX_TOOLS_ZOOMTOOLS_HXX +#define _BGFX_TOOLS_ZOOMTOOLS_HXX + +#include <sal/types.h> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + /** This namespace provides functions for optimized geometric zooming + */ + namespace zoomtools + { + BASEGFX_DLLPUBLIC long zoomOut(long nCurrent); + BASEGFX_DLLPUBLIC long zoomIn(long nCurrent); + } +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tuple/b2dtuple.hxx b/include/basegfx/tuple/b2dtuple.hxx new file mode 100644 index 000000000000..380ba8adf493 --- /dev/null +++ b/include/basegfx/tuple/b2dtuple.hxx @@ -0,0 +1,352 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TUPLE_B2DTUPLE_HXX +#define _BGFX_TUPLE_B2DTUPLE_HXX + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclarations + class B2ITuple; + + /** Base class for all Points/Vectors with two double values + + This class provides all methods common to Point + avd Vector classes which are derived from here. + + @derive Use this class to implement Points or Vectors + which are based on two double values + */ + class SAL_WARN_UNUSED B2DTuple + { + protected: + double mfX; + double mfY; + + public: + /** Create a 2D Tuple + + The tuple is initialized to (0.0, 0.0) + */ + B2DTuple() + : mfX(0.0), + mfY(0.0) + {} + + /** Create a 2D Tuple + + @param fX + This parameter is used to initialize the X-coordinate + of the 2D Tuple. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 2D Tuple. + */ + B2DTuple(double fX, double fY) + : mfX( fX ), + mfY( fY ) + {} + + /** Create a copy of a 2D Tuple + + @param rTup + The 2D Tuple which will be copied. + */ + B2DTuple(const B2DTuple& rTup) + : mfX( rTup.mfX ), + mfY( rTup.mfY ) + {} + + /** Create a copy of a 2D integer Tuple + + @param rTup + The 2D Tuple which will be copied. + */ + BASEGFX_DLLPUBLIC explicit B2DTuple(const B2ITuple& rTup); + + ~B2DTuple() + {} + + /// Get X-Coordinate of 2D Tuple + double getX() const + { + return mfX; + } + + /// Get Y-Coordinate of 2D Tuple + double getY() const + { + return mfY; + } + + /// Set X-Coordinate of 2D Tuple + void setX(double fX) + { + mfX = fX; + } + + /// Set Y-Coordinate of 2D Tuple + void setY(double fY) + { + mfY = fY; + } + + /// Array-access to 2D Tuple + const double& operator[] (int nPos) const + { + // Here, normally one if(...) should be used. In the assumption that + // both double members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mfX; return mfY; + return *((&mfX) + nPos); + } + + /// Array-access to 2D Tuple + double& operator[] (int nPos) + { + // Here, normally one if(...) should be used. In the assumption that + // both double members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mfX; return mfY; + return *((&mfX) + nPos); + } + + // comparators with tolerance + ////////////////////////////////////////////////////////////////////// + + bool equalZero() const + { + return (this == &getEmptyTuple() || + (fTools::equalZero(mfX) && fTools::equalZero(mfY))); + } + + bool equalZero(const double& rfSmallValue) const + { + return (this == &getEmptyTuple() || + (fTools::equalZero(mfX, rfSmallValue) && fTools::equalZero(mfY, rfSmallValue))); + } + + bool equal(const B2DTuple& rTup) const + { + return ( + this == &rTup || + (fTools::equal(mfX, rTup.mfX) && + fTools::equal(mfY, rTup.mfY))); + } + + bool equal(const B2DTuple& rTup, const double& rfSmallValue) const + { + return ( + this == &rTup || + (fTools::equal(mfX, rTup.mfX, rfSmallValue) && + fTools::equal(mfY, rTup.mfY, rfSmallValue))); + } + + // operators + ////////////////////////////////////////////////////////////////////// + + B2DTuple& operator+=( const B2DTuple& rTup ) + { + mfX += rTup.mfX; + mfY += rTup.mfY; + return *this; + } + + B2DTuple& operator-=( const B2DTuple& rTup ) + { + mfX -= rTup.mfX; + mfY -= rTup.mfY; + return *this; + } + + B2DTuple& operator/=( const B2DTuple& rTup ) + { + mfX /= rTup.mfX; + mfY /= rTup.mfY; + return *this; + } + + B2DTuple& operator*=( const B2DTuple& rTup ) + { + mfX *= rTup.mfX; + mfY *= rTup.mfY; + return *this; + } + + B2DTuple& operator*=(double t) + { + mfX *= t; + mfY *= t; + return *this; + } + + B2DTuple& operator/=(double t) + { + const double fVal(1.0 / t); + mfX *= fVal; + mfY *= fVal; + return *this; + } + + B2DTuple operator-(void) const + { + return B2DTuple(-mfX, -mfY); + } + + bool operator==( const B2DTuple& rTup ) const + { + return equal(rTup); + } + + bool operator!=( const B2DTuple& rTup ) const + { + return !equal(rTup); + } + + B2DTuple& operator=( const B2DTuple& rTup ) + { + mfX = rTup.mfX; + mfY = rTup.mfY; + return *this; + } + + BASEGFX_DLLPUBLIC static const B2DTuple& getEmptyTuple(); + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + inline B2DTuple minimum(const B2DTuple& rTupA, const B2DTuple& rTupB) + { + B2DTuple aMin( + (rTupB.getX() < rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() < rTupA.getY()) ? rTupB.getY() : rTupA.getY()); + return aMin; + } + + inline B2DTuple maximum(const B2DTuple& rTupA, const B2DTuple& rTupB) + { + B2DTuple aMax( + (rTupB.getX() > rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() > rTupA.getY()) ? rTupB.getY() : rTupA.getY()); + return aMax; + } + + inline B2DTuple absolute(const B2DTuple& rTup) + { + B2DTuple aAbs( + (0.0 > rTup.getX()) ? -rTup.getX() : rTup.getX(), + (0.0 > rTup.getY()) ? -rTup.getY() : rTup.getY()); + return aAbs; + } + + inline B2DTuple interpolate(const B2DTuple& rOld1, const B2DTuple& rOld2, double t) + { + B2DTuple aInt( + ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), + ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY()); + return aInt; + } + + inline B2DTuple average(const B2DTuple& rOld1, const B2DTuple& rOld2) + { + B2DTuple aAvg( + (rOld1.getX() + rOld2.getX()) * 0.5, + (rOld1.getY() + rOld2.getY()) * 0.5); + return aAvg; + } + + inline B2DTuple average(const B2DTuple& rOld1, const B2DTuple& rOld2, const B2DTuple& rOld3) + { + B2DTuple aAvg( + (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), + (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0)); + return aAvg; + } + + inline B2DTuple operator+(const B2DTuple& rTupA, const B2DTuple& rTupB) + { + B2DTuple aSum(rTupA); + aSum += rTupB; + return aSum; + } + + inline B2DTuple operator-(const B2DTuple& rTupA, const B2DTuple& rTupB) + { + B2DTuple aSub(rTupA); + aSub -= rTupB; + return aSub; + } + + inline B2DTuple operator/(const B2DTuple& rTupA, const B2DTuple& rTupB) + { + B2DTuple aDiv(rTupA); + aDiv /= rTupB; + return aDiv; + } + + inline B2DTuple operator*(const B2DTuple& rTupA, const B2DTuple& rTupB) + { + B2DTuple aMul(rTupA); + aMul *= rTupB; + return aMul; + } + + inline B2DTuple operator*(const B2DTuple& rTup, double t) + { + B2DTuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B2DTuple operator*(double t, const B2DTuple& rTup) + { + B2DTuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B2DTuple operator/(const B2DTuple& rTup, double t) + { + B2DTuple aNew(rTup); + aNew /= t; + return aNew; + } + + inline B2DTuple operator/(double t, const B2DTuple& rTup) + { + B2DTuple aNew(t, t); + B2DTuple aTmp(rTup); + aNew /= aTmp; + return aNew; + } + + /** Round double to nearest integer for 2D tuple + + @return the nearest integer for this tuple + */ + BASEGFX_DLLPUBLIC B2ITuple fround(const B2DTuple& rTup); +} // end of namespace basegfx + +#endif /* _BGFX_TUPLE_B2DTUPLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tuple/b2i64tuple.hxx b/include/basegfx/tuple/b2i64tuple.hxx new file mode 100644 index 000000000000..debb4cabe578 --- /dev/null +++ b/include/basegfx/tuple/b2i64tuple.hxx @@ -0,0 +1,305 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TUPLE_B2I64TUPLE_HXX +#define _BGFX_TUPLE_B2I64TUPLE_HXX + +#include <sal/types.h> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** Base class for all Points/Vectors with two sal_Int64 values + + This class provides all methods common to Point + avd Vector classes which are derived from here. + + @derive Use this class to implement Points or Vectors + which are based on two sal_Int64 values + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B2I64Tuple + { + protected: + sal_Int64 mnX; + sal_Int64 mnY; + + public: + /** Create a 2D Tuple + + The tuple is initialized to (0, 0) + */ + B2I64Tuple() + : mnX(0), + mnY(0) + {} + + /** Create a 2D Tuple + + @param fX + This parameter is used to initialize the X-coordinate + of the 2D Tuple. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 2D Tuple. + */ + B2I64Tuple(sal_Int64 fX, sal_Int64 fY) + : mnX( fX ), + mnY( fY ) + {} + + /** Create a copy of a 2D Tuple + + @param rTup + The 2D Tuple which will be copied. + */ + B2I64Tuple(const B2I64Tuple& rTup) + : mnX( rTup.mnX ), + mnY( rTup.mnY ) + {} + + ~B2I64Tuple() + {} + + /// Get X-Coordinate of 2D Tuple + sal_Int64 getX() const + { + return mnX; + } + + /// Get Y-Coordinate of 2D Tuple + sal_Int64 getY() const + { + return mnY; + } + + /// Set X-Coordinate of 2D Tuple + void setX(sal_Int64 fX) + { + mnX = fX; + } + + /// Set Y-Coordinate of 2D Tuple + void setY(sal_Int64 fY) + { + mnY = fY; + } + + /// Array-access to 2D Tuple + const sal_Int64& operator[] (int nPos) const + { + // Here, normally one if(...) should be used. In the assumption that + // both sal_Int64 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; return mnY; + return *((&mnX) + nPos); + } + + /// Array-access to 2D Tuple + sal_Int64& operator[] (int nPos) + { + // Here, normally one if(...) should be used. In the assumption that + // both sal_Int64 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; return mnY; + return *((&mnX) + nPos); + } + + // operators + ////////////////////////////////////////////////////////////////////// + + B2I64Tuple& operator+=( const B2I64Tuple& rTup ) + { + mnX += rTup.mnX; + mnY += rTup.mnY; + return *this; + } + + B2I64Tuple& operator-=( const B2I64Tuple& rTup ) + { + mnX -= rTup.mnX; + mnY -= rTup.mnY; + return *this; + } + + B2I64Tuple& operator/=( const B2I64Tuple& rTup ) + { + mnX /= rTup.mnX; + mnY /= rTup.mnY; + return *this; + } + + B2I64Tuple& operator*=( const B2I64Tuple& rTup ) + { + mnX *= rTup.mnX; + mnY *= rTup.mnY; + return *this; + } + + B2I64Tuple& operator*=(sal_Int64 t) + { + mnX *= t; + mnY *= t; + return *this; + } + + B2I64Tuple& operator/=(sal_Int64 t) + { + mnX /= t; + mnY /= t; + return *this; + } + + B2I64Tuple operator-(void) const + { + return B2I64Tuple(-mnX, -mnY); + } + + bool equalZero() const { return mnX == 0 && mnY == 0; } + + bool operator==( const B2I64Tuple& rTup ) const + { + return this == &rTup || (rTup.mnX == mnX && rTup.mnY == mnY); + } + + bool operator!=( const B2I64Tuple& rTup ) const + { + return !(*this == rTup); + } + + B2I64Tuple& operator=( const B2I64Tuple& rTup ) + { + mnX = rTup.mnX; + mnY = rTup.mnY; + return *this; + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + inline B2I64Tuple minimum(const B2I64Tuple& rTupA, const B2I64Tuple& rTupB) + { + B2I64Tuple aMin( + (rTupB.getX() < rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() < rTupA.getY()) ? rTupB.getY() : rTupA.getY()); + return aMin; + } + + inline B2I64Tuple maximum(const B2I64Tuple& rTupA, const B2I64Tuple& rTupB) + { + B2I64Tuple aMax( + (rTupB.getX() > rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() > rTupA.getY()) ? rTupB.getY() : rTupA.getY()); + return aMax; + } + + inline B2I64Tuple absolute(const B2I64Tuple& rTup) + { + B2I64Tuple aAbs( + (0 > rTup.getX()) ? -rTup.getX() : rTup.getX(), + (0 > rTup.getY()) ? -rTup.getY() : rTup.getY()); + return aAbs; + } + + inline B2DTuple interpolate(const B2I64Tuple& rOld1, const B2I64Tuple& rOld2, double t) + { + B2DTuple aInt( + ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), + ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY()); + return aInt; + } + + inline B2DTuple average(const B2I64Tuple& rOld1, const B2I64Tuple& rOld2) + { + B2DTuple aAvg( + (rOld1.getX() + rOld2.getX()) * 0.5, + (rOld1.getY() + rOld2.getY()) * 0.5); + return aAvg; + } + + inline B2DTuple average(const B2I64Tuple& rOld1, const B2I64Tuple& rOld2, const B2I64Tuple& rOld3) + { + B2DTuple aAvg( + (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), + (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0)); + return aAvg; + } + + inline B2I64Tuple operator+(const B2I64Tuple& rTupA, const B2I64Tuple& rTupB) + { + B2I64Tuple aSum(rTupA); + aSum += rTupB; + return aSum; + } + + inline B2I64Tuple operator-(const B2I64Tuple& rTupA, const B2I64Tuple& rTupB) + { + B2I64Tuple aSub(rTupA); + aSub -= rTupB; + return aSub; + } + + inline B2I64Tuple operator/(const B2I64Tuple& rTupA, const B2I64Tuple& rTupB) + { + B2I64Tuple aDiv(rTupA); + aDiv /= rTupB; + return aDiv; + } + + inline B2I64Tuple operator*(const B2I64Tuple& rTupA, const B2I64Tuple& rTupB) + { + B2I64Tuple aMul(rTupA); + aMul *= rTupB; + return aMul; + } + + inline B2I64Tuple operator*(const B2I64Tuple& rTup, sal_Int64 t) + { + B2I64Tuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B2I64Tuple operator*(sal_Int64 t, const B2I64Tuple& rTup) + { + B2I64Tuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B2I64Tuple operator/(const B2I64Tuple& rTup, sal_Int64 t) + { + B2I64Tuple aNew(rTup); + aNew /= t; + return aNew; + } + + inline B2I64Tuple operator/(sal_Int64 t, const B2I64Tuple& rTup) + { + B2I64Tuple aNew(t, t); + B2I64Tuple aTmp(rTup); + aNew /= aTmp; + return aNew; + } +} // end of namespace basegfx + +#endif /* _BGFX_TUPLE_B2I64TUPLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tuple/b2ituple.hxx b/include/basegfx/tuple/b2ituple.hxx new file mode 100644 index 000000000000..41203a0c58c4 --- /dev/null +++ b/include/basegfx/tuple/b2ituple.hxx @@ -0,0 +1,208 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TUPLE_B2ITUPLE_HXX +#define _BGFX_TUPLE_B2ITUPLE_HXX + +#include <sal/types.h> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + /** Base class for all Points/Vectors with two sal_Int32 values + + This class provides all methods common to Point + avd Vector classes which are derived from here. + + @derive Use this class to implement Points or Vectors + which are based on two sal_Int32 values + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B2ITuple + { + protected: + sal_Int32 mnX; + sal_Int32 mnY; + + public: + /** Create a 2D Tuple + + The tuple is initialized to (0, 0) + */ + B2ITuple() + : mnX(0), + mnY(0) + {} + + /** Create a 2D Tuple + + @param fX + This parameter is used to initialize the X-coordinate + of the 2D Tuple. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 2D Tuple. + */ + B2ITuple(sal_Int32 fX, sal_Int32 fY) + : mnX( fX ), + mnY( fY ) + {} + + /** Create a copy of a 2D Tuple + + @param rTup + The 2D Tuple which will be copied. + */ + B2ITuple(const B2ITuple& rTup) + : mnX( rTup.mnX ), + mnY( rTup.mnY ) + {} + + ~B2ITuple() + {} + + /// Get X-Coordinate of 2D Tuple + sal_Int32 getX() const + { + return mnX; + } + + /// Get Y-Coordinate of 2D Tuple + sal_Int32 getY() const + { + return mnY; + } + + /// Set X-Coordinate of 2D Tuple + void setX(sal_Int32 fX) + { + mnX = fX; + } + + /// Set Y-Coordinate of 2D Tuple + void setY(sal_Int32 fY) + { + mnY = fY; + } + + /// Array-access to 2D Tuple + const sal_Int32& operator[] (int nPos) const + { + // Here, normally one if(...) should be used. In the assumption that + // both sal_Int32 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; return mnY; + return *((&mnX) + nPos); + } + + /// Array-access to 2D Tuple + sal_Int32& operator[] (int nPos) + { + // Here, normally one if(...) should be used. In the assumption that + // both sal_Int32 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; return mnY; + return *((&mnX) + nPos); + } + + // operators + ////////////////////////////////////////////////////////////////////// + + B2ITuple& operator+=( const B2ITuple& rTup ) + { + mnX += rTup.mnX; + mnY += rTup.mnY; + return *this; + } + + B2ITuple& operator-=( const B2ITuple& rTup ) + { + mnX -= rTup.mnX; + mnY -= rTup.mnY; + return *this; + } + + B2ITuple& operator/=( const B2ITuple& rTup ) + { + mnX /= rTup.mnX; + mnY /= rTup.mnY; + return *this; + } + + B2ITuple& operator*=( const B2ITuple& rTup ) + { + mnX *= rTup.mnX; + mnY *= rTup.mnY; + return *this; + } + + B2ITuple& operator*=(sal_Int32 t) + { + mnX *= t; + mnY *= t; + return *this; + } + + B2ITuple& operator/=(sal_Int32 t) + { + mnX /= t; + mnY /= t; + return *this; + } + + B2ITuple operator-(void) const + { + return B2ITuple(-mnX, -mnY); + } + + bool equalZero() const { return mnX == 0 && mnY == 0; } + + bool operator==( const B2ITuple& rTup ) const + { + return this == &rTup || (rTup.mnX == mnX && rTup.mnY == mnY); + } + + bool operator!=( const B2ITuple& rTup ) const + { + return !(*this == rTup); + } + + B2ITuple& operator=( const B2ITuple& rTup ) + { + mnX = rTup.mnX; + mnY = rTup.mnY; + return *this; + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + class B2DTuple; + + BASEGFX_DLLPUBLIC B2ITuple operator+(const B2ITuple& rTupA, const B2ITuple& rTupB); + BASEGFX_DLLPUBLIC B2ITuple operator-(const B2ITuple& rTupA, const B2ITuple& rTupB); + BASEGFX_DLLPUBLIC B2ITuple operator/(const B2ITuple& rTupA, const B2ITuple& rTupB); + BASEGFX_DLLPUBLIC B2ITuple operator*(const B2ITuple& rTupA, const B2ITuple& rTupB); + BASEGFX_DLLPUBLIC B2ITuple operator*(const B2ITuple& rTup, sal_Int32 t); + BASEGFX_DLLPUBLIC B2ITuple operator*(sal_Int32 t, const B2ITuple& rTup); + BASEGFX_DLLPUBLIC B2ITuple operator/(const B2ITuple& rTup, sal_Int32 t); + BASEGFX_DLLPUBLIC B2ITuple operator/(sal_Int32 t, const B2ITuple& rTup); +} // end of namespace basegfx + +#endif /* _BGFX_TUPLE_B2ITUPLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tuple/b3dtuple.hxx b/include/basegfx/tuple/b3dtuple.hxx new file mode 100644 index 000000000000..1eb4dd38de09 --- /dev/null +++ b/include/basegfx/tuple/b3dtuple.hxx @@ -0,0 +1,421 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TUPLE_B3DTUPLE_HXX +#define _BGFX_TUPLE_B3DTUPLE_HXX + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclarations + class B3ITuple; + + /** Base class for all Points/Vectors with three double values + + This class provides all methods common to Point + avd Vector classes which are derived from here. + + @derive Use this class to implement Points or Vectors + which are based on three double values + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B3DTuple + { + protected: + double mfX; + double mfY; + double mfZ; + + public: + /** Create a 3D Tuple + + The tuple is initialized to (0.0, 0.0, 0.0) + */ + B3DTuple() + : mfX(0.0), + mfY(0.0), + mfZ(0.0) + {} + + /** Create a 3D Tuple + + @param fX + This parameter is used to initialize the X-coordinate + of the 3D Tuple. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 3D Tuple. + + @param fZ + This parameter is used to initialize the Z-coordinate + of the 3D Tuple. + */ + B3DTuple(double fX, double fY, double fZ) + : mfX(fX), + mfY(fY), + mfZ(fZ) + {} + + /** Create a copy of a 3D Tuple + + @param rTup + The 3D Tuple which will be copied. + */ + B3DTuple(const B3DTuple& rTup) + : mfX( rTup.mfX ), + mfY( rTup.mfY ), + mfZ( rTup.mfZ ) + {} + + ~B3DTuple() + {} + + /// get X-Coordinate of 3D Tuple + double getX() const + { + return mfX; + } + + /// get Y-Coordinate of 3D Tuple + double getY() const + { + return mfY; + } + + /// get Z-Coordinate of 3D Tuple + double getZ() const + { + return mfZ; + } + + /// set X-Coordinate of 3D Tuple + void setX(double fX) + { + mfX = fX; + } + + /// set Y-Coordinate of 3D Tuple + void setY(double fY) + { + mfY = fY; + } + + /// set Z-Coordinate of 3D Tuple + void setZ(double fZ) + { + mfZ = fZ; + } + + /// Array-access to 3D Tuple + const double& operator[] (int nPos) const + { + // Here, normally two if(...)'s should be used. In the assumption that + // both double members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mfX; if(1 == nPos) return mfY; return mfZ; + return *((&mfX) + nPos); + } + + /// Array-access to 3D Tuple + double& operator[] (int nPos) + { + // Here, normally two if(...)'s should be used. In the assumption that + // both double members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mfX; if(1 == nPos) return mfY; return mfZ; + return *((&mfX) + nPos); + } + + // comparators with tolerance + ////////////////////////////////////////////////////////////////////// + + bool equalZero() const + { + return (this == &getEmptyTuple() || + (::basegfx::fTools::equalZero(mfX) + && ::basegfx::fTools::equalZero(mfY) + && ::basegfx::fTools::equalZero(mfZ))); + } + + bool equalZero(const double& rfSmallValue) const + { + return (this == &getEmptyTuple() || + (::basegfx::fTools::equalZero(mfX, rfSmallValue) + && ::basegfx::fTools::equalZero(mfY, rfSmallValue) + && ::basegfx::fTools::equalZero(mfZ, rfSmallValue))); + } + + bool equal(const B3DTuple& rTup) const + { + return ( + this == &rTup || + (::basegfx::fTools::equal(mfX, rTup.mfX) && + ::basegfx::fTools::equal(mfY, rTup.mfY) && + ::basegfx::fTools::equal(mfZ, rTup.mfZ))); + } + + bool equal(const B3DTuple& rTup, const double& rfSmallValue) const + { + return ( + this == &rTup || + (::basegfx::fTools::equal(mfX, rTup.mfX, rfSmallValue) && + ::basegfx::fTools::equal(mfY, rTup.mfY, rfSmallValue) && + ::basegfx::fTools::equal(mfZ, rTup.mfZ, rfSmallValue))); + } + + // operators + ////////////////////////////////////////////////////////////////////// + + B3DTuple& operator+=( const B3DTuple& rTup ) + { + mfX += rTup.mfX; + mfY += rTup.mfY; + mfZ += rTup.mfZ; + return *this; + } + + B3DTuple& operator-=( const B3DTuple& rTup ) + { + mfX -= rTup.mfX; + mfY -= rTup.mfY; + mfZ -= rTup.mfZ; + return *this; + } + + B3DTuple& operator/=( const B3DTuple& rTup ) + { + mfX /= rTup.mfX; + mfY /= rTup.mfY; + mfZ /= rTup.mfZ; + return *this; + } + + B3DTuple& operator*=( const B3DTuple& rTup ) + { + mfX *= rTup.mfX; + mfY *= rTup.mfY; + mfZ *= rTup.mfZ; + return *this; + } + + B3DTuple& operator*=(double t) + { + mfX *= t; + mfY *= t; + mfZ *= t; + return *this; + } + + B3DTuple& operator/=(double t) + { + const double fVal(1.0 / t); + mfX *= fVal; + mfY *= fVal; + mfZ *= fVal; + return *this; + } + + B3DTuple operator-(void) const + { + return B3DTuple(-mfX, -mfY, -mfZ); + } + + bool operator==( const B3DTuple& rTup ) const + { + return equal(rTup); + } + + bool operator!=( const B3DTuple& rTup ) const + { + return !equal(rTup); + } + + B3DTuple& operator=( const B3DTuple& rTup ) + { + mfX = rTup.mfX; + mfY = rTup.mfY; + mfZ = rTup.mfZ; + return *this; + } + + void correctValues(const double fCompareValue = 0.0) + { + if(0.0 == fCompareValue) + { + if(::basegfx::fTools::equalZero(mfX)) + { + mfX = 0.0; + } + + if(::basegfx::fTools::equalZero(mfY)) + { + mfY = 0.0; + } + + if(::basegfx::fTools::equalZero(mfZ)) + { + mfZ = 0.0; + } + } + else + { + if(::basegfx::fTools::equal(mfX, fCompareValue)) + { + mfX = fCompareValue; + } + + if(::basegfx::fTools::equal(mfY, fCompareValue)) + { + mfY = fCompareValue; + } + + if(::basegfx::fTools::equal(mfZ, fCompareValue)) + { + mfZ = fCompareValue; + } + } + } + + static const B3DTuple& getEmptyTuple(); + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + inline B3DTuple minimum(const B3DTuple& rTupA, const B3DTuple& rTupB) + { + B3DTuple aMin( + (rTupB.getX() < rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() < rTupA.getY()) ? rTupB.getY() : rTupA.getY(), + (rTupB.getZ() < rTupA.getZ()) ? rTupB.getZ() : rTupA.getZ()); + return aMin; + } + + inline B3DTuple maximum(const B3DTuple& rTupA, const B3DTuple& rTupB) + { + B3DTuple aMax( + (rTupB.getX() > rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() > rTupA.getY()) ? rTupB.getY() : rTupA.getY(), + (rTupB.getZ() > rTupA.getZ()) ? rTupB.getZ() : rTupA.getZ()); + return aMax; + } + + inline B3DTuple absolute(const B3DTuple& rTup) + { + B3DTuple aAbs( + (0.0 > rTup.getX()) ? -rTup.getX() : rTup.getX(), + (0.0 > rTup.getY()) ? -rTup.getY() : rTup.getY(), + (0.0 > rTup.getZ()) ? -rTup.getZ() : rTup.getZ()); + return aAbs; + } + + inline B3DTuple interpolate(const B3DTuple& rOld1, const B3DTuple& rOld2, double t) + { + B3DTuple aInt( + ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), + ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY(), + ((rOld2.getZ() - rOld1.getZ()) * t) + rOld1.getZ()); + return aInt; + } + + inline B3DTuple average(const B3DTuple& rOld1, const B3DTuple& rOld2) + { + B3DTuple aAvg( + (rOld1.getX() + rOld2.getX()) * 0.5, + (rOld1.getY() + rOld2.getY()) * 0.5, + (rOld1.getZ() + rOld2.getZ()) * 0.5); + return aAvg; + } + + inline B3DTuple average(const B3DTuple& rOld1, const B3DTuple& rOld2, const B3DTuple& rOld3) + { + B3DTuple aAvg( + (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), + (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0), + (rOld1.getZ() + rOld2.getZ() + rOld3.getZ()) * (1.0 / 3.0)); + return aAvg; + } + + inline B3DTuple operator+(const B3DTuple& rTupA, const B3DTuple& rTupB) + { + B3DTuple aSum(rTupA); + aSum += rTupB; + return aSum; + } + + inline B3DTuple operator-(const B3DTuple& rTupA, const B3DTuple& rTupB) + { + B3DTuple aSub(rTupA); + aSub -= rTupB; + return aSub; + } + + inline B3DTuple operator/(const B3DTuple& rTupA, const B3DTuple& rTupB) + { + B3DTuple aDiv(rTupA); + aDiv /= rTupB; + return aDiv; + } + + inline B3DTuple operator*(const B3DTuple& rTupA, const B3DTuple& rTupB) + { + B3DTuple aMul(rTupA); + aMul *= rTupB; + return aMul; + } + + inline B3DTuple operator*(const B3DTuple& rTup, double t) + { + B3DTuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B3DTuple operator*(double t, const B3DTuple& rTup) + { + B3DTuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B3DTuple operator/(const B3DTuple& rTup, double t) + { + B3DTuple aNew(rTup); + aNew /= t; + return aNew; + } + + inline B3DTuple operator/(double t, const B3DTuple& rTup) + { + B3DTuple aNew(rTup); + aNew /= t; + return aNew; + } + + /** Round double to nearest integer for 3D tuple + + @return the nearest integer for this tuple + */ + BASEGFX_DLLPUBLIC B3ITuple fround(const B3DTuple& rTup); +} // end of namespace basegfx + +#endif /* _BGFX_TUPLE_B3DTUPLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tuple/b3i64tuple.hxx b/include/basegfx/tuple/b3i64tuple.hxx new file mode 100644 index 000000000000..bcc1acaee6b1 --- /dev/null +++ b/include/basegfx/tuple/b3i64tuple.hxx @@ -0,0 +1,336 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TUPLE_B3I64TUPLE_HXX +#define _BGFX_TUPLE_B3I64TUPLE_HXX + +#include <sal/types.h> +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/basegfxdllapi.h> + + +namespace basegfx +{ + /** Base class for all Points/Vectors with three sal_Int64 values + + This class provides all methods common to Point + avd Vector classes which are derived from here. + + @derive Use this class to implement Points or Vectors + which are based on three sal_Int64 values + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B3I64Tuple + { + protected: + sal_Int64 mnX; + sal_Int64 mnY; + sal_Int64 mnZ; + + public: + /** Create a 3D Tuple + + The tuple is initialized to (0, 0, 0) + */ + B3I64Tuple() + : mnX(0), + mnY(0), + mnZ(0) + {} + + /** Create a 3D Tuple + + @param nX + This parameter is used to initialize the X-coordinate + of the 3D Tuple. + + @param nY + This parameter is used to initialize the Y-coordinate + of the 3D Tuple. + + @param nZ + This parameter is used to initialize the Z-coordinate + of the 3D Tuple. + */ + B3I64Tuple(sal_Int64 nX, sal_Int64 nY, sal_Int64 nZ) + : mnX(nX), + mnY(nY), + mnZ(nZ) + {} + + /** Create a copy of a 3D Tuple + + @param rTup + The 3D Tuple which will be copied. + */ + B3I64Tuple(const B3I64Tuple& rTup) + : mnX( rTup.mnX ), + mnY( rTup.mnY ), + mnZ( rTup.mnZ ) + {} + + ~B3I64Tuple() + {} + + /// get X-Coordinate of 3D Tuple + sal_Int64 getX() const + { + return mnX; + } + + /// get Y-Coordinate of 3D Tuple + sal_Int64 getY() const + { + return mnY; + } + + /// get Z-Coordinate of 3D Tuple + sal_Int64 getZ() const + { + return mnZ; + } + + /// set X-Coordinate of 3D Tuple + void setX(sal_Int64 nX) + { + mnX = nX; + } + + /// set Y-Coordinate of 3D Tuple + void setY(sal_Int64 nY) + { + mnY = nY; + } + + /// set Z-Coordinate of 3D Tuple + void setZ(sal_Int64 nZ) + { + mnZ = nZ; + } + + /// Array-access to 3D Tuple + const sal_Int64& operator[] (int nPos) const + { + // Here, normally two if(...)'s should be used. In the assumption that + // both sal_Int64 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; if(1 == nPos) return mnY; return mnZ; + return *((&mnX) + nPos); + } + + /// Array-access to 3D Tuple + sal_Int64& operator[] (int nPos) + { + // Here, normally two if(...)'s should be used. In the assumption that + // both sal_Int64 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; if(1 == nPos) return mnY; return mnZ; + return *((&mnX) + nPos); + } + + // operators + ////////////////////////////////////////////////////////////////////// + + B3I64Tuple& operator+=( const B3I64Tuple& rTup ) + { + mnX += rTup.mnX; + mnY += rTup.mnY; + mnZ += rTup.mnZ; + return *this; + } + + B3I64Tuple& operator-=( const B3I64Tuple& rTup ) + { + mnX -= rTup.mnX; + mnY -= rTup.mnY; + mnZ -= rTup.mnZ; + return *this; + } + + B3I64Tuple& operator/=( const B3I64Tuple& rTup ) + { + mnX /= rTup.mnX; + mnY /= rTup.mnY; + mnZ /= rTup.mnZ; + return *this; + } + + B3I64Tuple& operator*=( const B3I64Tuple& rTup ) + { + mnX *= rTup.mnX; + mnY *= rTup.mnY; + mnZ *= rTup.mnZ; + return *this; + } + + B3I64Tuple& operator*=(sal_Int64 t) + { + mnX *= t; + mnY *= t; + mnZ *= t; + return *this; + } + + B3I64Tuple& operator/=(sal_Int64 t) + { + mnX /= t; + mnY /= t; + mnZ /= t; + return *this; + } + + B3I64Tuple operator-(void) const + { + return B3I64Tuple(-mnX, -mnY, -mnZ); + } + + bool operator==( const B3I64Tuple& rTup ) const + { + return this == &rTup || (rTup.mnX == mnX && rTup.mnY == mnY && rTup.mnZ == mnZ); + } + + bool operator!=( const B3I64Tuple& rTup ) const + { + return !(*this == rTup); + } + + B3I64Tuple& operator=( const B3I64Tuple& rTup ) + { + mnX = rTup.mnX; + mnY = rTup.mnY; + mnZ = rTup.mnZ; + return *this; + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + inline B3I64Tuple minimum(const B3I64Tuple& rTupA, const B3I64Tuple& rTupB) + { + B3I64Tuple aMin( + (rTupB.getX() < rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() < rTupA.getY()) ? rTupB.getY() : rTupA.getY(), + (rTupB.getZ() < rTupA.getZ()) ? rTupB.getZ() : rTupA.getZ()); + return aMin; + } + + inline B3I64Tuple maximum(const B3I64Tuple& rTupA, const B3I64Tuple& rTupB) + { + B3I64Tuple aMax( + (rTupB.getX() > rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() > rTupA.getY()) ? rTupB.getY() : rTupA.getY(), + (rTupB.getZ() > rTupA.getZ()) ? rTupB.getZ() : rTupA.getZ()); + return aMax; + } + + inline B3I64Tuple absolute(const B3I64Tuple& rTup) + { + B3I64Tuple aAbs( + (0 > rTup.getX()) ? -rTup.getX() : rTup.getX(), + (0 > rTup.getY()) ? -rTup.getY() : rTup.getY(), + (0 > rTup.getZ()) ? -rTup.getZ() : rTup.getZ()); + return aAbs; + } + + inline B3DTuple interpolate(const B3I64Tuple& rOld1, const B3I64Tuple& rOld2, double t) + { + B3DTuple aInt( + ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), + ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY(), + ((rOld2.getZ() - rOld1.getZ()) * t) + rOld1.getZ()); + return aInt; + } + + inline B3DTuple average(const B3I64Tuple& rOld1, const B3I64Tuple& rOld2) + { + B3DTuple aAvg( + (rOld1.getX() + rOld2.getX()) * 0.5, + (rOld1.getY() + rOld2.getY()) * 0.5, + (rOld1.getZ() + rOld2.getZ()) * 0.5); + return aAvg; + } + + inline B3DTuple average(const B3I64Tuple& rOld1, const B3I64Tuple& rOld2, const B3I64Tuple& rOld3) + { + B3DTuple aAvg( + (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), + (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0), + (rOld1.getZ() + rOld2.getZ() + rOld3.getZ()) * (1.0 / 3.0)); + return aAvg; + } + + inline B3I64Tuple operator+(const B3I64Tuple& rTupA, const B3I64Tuple& rTupB) + { + B3I64Tuple aSum(rTupA); + aSum += rTupB; + return aSum; + } + + inline B3I64Tuple operator-(const B3I64Tuple& rTupA, const B3I64Tuple& rTupB) + { + B3I64Tuple aSub(rTupA); + aSub -= rTupB; + return aSub; + } + + inline B3I64Tuple operator/(const B3I64Tuple& rTupA, const B3I64Tuple& rTupB) + { + B3I64Tuple aDiv(rTupA); + aDiv /= rTupB; + return aDiv; + } + + inline B3I64Tuple operator*(const B3I64Tuple& rTupA, const B3I64Tuple& rTupB) + { + B3I64Tuple aMul(rTupA); + aMul *= rTupB; + return aMul; + } + + inline B3I64Tuple operator*(const B3I64Tuple& rTup, sal_Int64 t) + { + B3I64Tuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B3I64Tuple operator*(sal_Int64 t, const B3I64Tuple& rTup) + { + B3I64Tuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B3I64Tuple operator/(const B3I64Tuple& rTup, sal_Int64 t) + { + B3I64Tuple aNew(rTup); + aNew /= t; + return aNew; + } + + inline B3I64Tuple operator/(sal_Int64 t, const B3I64Tuple& rTup) + { + B3I64Tuple aNew(t, t, t); + B3I64Tuple aTmp(rTup); + aNew /= aTmp; + return aNew; + } +} // end of namespace basegfx + +#endif /* _BGFX_TUPLE_B3I64TUPLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/tuple/b3ituple.hxx b/include/basegfx/tuple/b3ituple.hxx new file mode 100644 index 000000000000..49fb24634ed4 --- /dev/null +++ b/include/basegfx/tuple/b3ituple.hxx @@ -0,0 +1,335 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_TUPLE_B3ITUPLE_HXX +#define _BGFX_TUPLE_B3ITUPLE_HXX + +#include <sal/types.h> +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + /** Base class for all Points/Vectors with three sal_Int32 values + + This class provides all methods common to Point + avd Vector classes which are derived from here. + + @derive Use this class to implement Points or Vectors + which are based on three sal_Int32 values + */ + class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED B3ITuple + { + protected: + sal_Int32 mnX; + sal_Int32 mnY; + sal_Int32 mnZ; + + public: + /** Create a 3D Tuple + + The tuple is initialized to (0, 0, 0) + */ + B3ITuple() + : mnX(0), + mnY(0), + mnZ(0) + {} + + /** Create a 3D Tuple + + @param nX + This parameter is used to initialize the X-coordinate + of the 3D Tuple. + + @param nY + This parameter is used to initialize the Y-coordinate + of the 3D Tuple. + + @param nZ + This parameter is used to initialize the Z-coordinate + of the 3D Tuple. + */ + B3ITuple(sal_Int32 nX, sal_Int32 nY, sal_Int32 nZ) + : mnX(nX), + mnY(nY), + mnZ(nZ) + {} + + /** Create a copy of a 3D Tuple + + @param rTup + The 3D Tuple which will be copied. + */ + B3ITuple(const B3ITuple& rTup) + : mnX( rTup.mnX ), + mnY( rTup.mnY ), + mnZ( rTup.mnZ ) + {} + + ~B3ITuple() + {} + + /// get X-Coordinate of 3D Tuple + sal_Int32 getX() const + { + return mnX; + } + + /// get Y-Coordinate of 3D Tuple + sal_Int32 getY() const + { + return mnY; + } + + /// get Z-Coordinate of 3D Tuple + sal_Int32 getZ() const + { + return mnZ; + } + + /// set X-Coordinate of 3D Tuple + void setX(sal_Int32 nX) + { + mnX = nX; + } + + /// set Y-Coordinate of 3D Tuple + void setY(sal_Int32 nY) + { + mnY = nY; + } + + /// set Z-Coordinate of 3D Tuple + void setZ(sal_Int32 nZ) + { + mnZ = nZ; + } + + /// Array-access to 3D Tuple + const sal_Int32& operator[] (int nPos) const + { + // Here, normally two if(...)'s should be used. In the assumption that + // both sal_Int32 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; if(1 == nPos) return mnY; return mnZ; + return *((&mnX) + nPos); + } + + /// Array-access to 3D Tuple + sal_Int32& operator[] (int nPos) + { + // Here, normally two if(...)'s should be used. In the assumption that + // both sal_Int32 members can be accessed as an array a shortcut is used here. + // if(0 == nPos) return mnX; if(1 == nPos) return mnY; return mnZ; + return *((&mnX) + nPos); + } + + // operators + ////////////////////////////////////////////////////////////////////// + + B3ITuple& operator+=( const B3ITuple& rTup ) + { + mnX += rTup.mnX; + mnY += rTup.mnY; + mnZ += rTup.mnZ; + return *this; + } + + B3ITuple& operator-=( const B3ITuple& rTup ) + { + mnX -= rTup.mnX; + mnY -= rTup.mnY; + mnZ -= rTup.mnZ; + return *this; + } + + B3ITuple& operator/=( const B3ITuple& rTup ) + { + mnX /= rTup.mnX; + mnY /= rTup.mnY; + mnZ /= rTup.mnZ; + return *this; + } + + B3ITuple& operator*=( const B3ITuple& rTup ) + { + mnX *= rTup.mnX; + mnY *= rTup.mnY; + mnZ *= rTup.mnZ; + return *this; + } + + B3ITuple& operator*=(sal_Int32 t) + { + mnX *= t; + mnY *= t; + mnZ *= t; + return *this; + } + + B3ITuple& operator/=(sal_Int32 t) + { + mnX /= t; + mnY /= t; + mnZ /= t; + return *this; + } + + B3ITuple operator-(void) const + { + return B3ITuple(-mnX, -mnY, -mnZ); + } + + bool operator==( const B3ITuple& rTup ) const + { + return this == &rTup || (rTup.mnX == mnX && rTup.mnY == mnY && rTup.mnZ == mnZ); + } + + bool operator!=( const B3ITuple& rTup ) const + { + return !(*this == rTup); + } + + B3ITuple& operator=( const B3ITuple& rTup ) + { + mnX = rTup.mnX; + mnY = rTup.mnY; + mnZ = rTup.mnZ; + return *this; + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + inline B3ITuple minimum(const B3ITuple& rTupA, const B3ITuple& rTupB) + { + B3ITuple aMin( + (rTupB.getX() < rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() < rTupA.getY()) ? rTupB.getY() : rTupA.getY(), + (rTupB.getZ() < rTupA.getZ()) ? rTupB.getZ() : rTupA.getZ()); + return aMin; + } + + inline B3ITuple maximum(const B3ITuple& rTupA, const B3ITuple& rTupB) + { + B3ITuple aMax( + (rTupB.getX() > rTupA.getX()) ? rTupB.getX() : rTupA.getX(), + (rTupB.getY() > rTupA.getY()) ? rTupB.getY() : rTupA.getY(), + (rTupB.getZ() > rTupA.getZ()) ? rTupB.getZ() : rTupA.getZ()); + return aMax; + } + + inline B3ITuple absolute(const B3ITuple& rTup) + { + B3ITuple aAbs( + (0 > rTup.getX()) ? -rTup.getX() : rTup.getX(), + (0 > rTup.getY()) ? -rTup.getY() : rTup.getY(), + (0 > rTup.getZ()) ? -rTup.getZ() : rTup.getZ()); + return aAbs; + } + + inline B3DTuple interpolate(const B3ITuple& rOld1, const B3ITuple& rOld2, double t) + { + B3DTuple aInt( + ((rOld2.getX() - rOld1.getX()) * t) + rOld1.getX(), + ((rOld2.getY() - rOld1.getY()) * t) + rOld1.getY(), + ((rOld2.getZ() - rOld1.getZ()) * t) + rOld1.getZ()); + return aInt; + } + + inline B3DTuple average(const B3ITuple& rOld1, const B3ITuple& rOld2) + { + B3DTuple aAvg( + (rOld1.getX() + rOld2.getX()) * 0.5, + (rOld1.getY() + rOld2.getY()) * 0.5, + (rOld1.getZ() + rOld2.getZ()) * 0.5); + return aAvg; + } + + inline B3DTuple average(const B3ITuple& rOld1, const B3ITuple& rOld2, const B3ITuple& rOld3) + { + B3DTuple aAvg( + (rOld1.getX() + rOld2.getX() + rOld3.getX()) * (1.0 / 3.0), + (rOld1.getY() + rOld2.getY() + rOld3.getY()) * (1.0 / 3.0), + (rOld1.getZ() + rOld2.getZ() + rOld3.getZ()) * (1.0 / 3.0)); + return aAvg; + } + + inline B3ITuple operator+(const B3ITuple& rTupA, const B3ITuple& rTupB) + { + B3ITuple aSum(rTupA); + aSum += rTupB; + return aSum; + } + + inline B3ITuple operator-(const B3ITuple& rTupA, const B3ITuple& rTupB) + { + B3ITuple aSub(rTupA); + aSub -= rTupB; + return aSub; + } + + inline B3ITuple operator/(const B3ITuple& rTupA, const B3ITuple& rTupB) + { + B3ITuple aDiv(rTupA); + aDiv /= rTupB; + return aDiv; + } + + inline B3ITuple operator*(const B3ITuple& rTupA, const B3ITuple& rTupB) + { + B3ITuple aMul(rTupA); + aMul *= rTupB; + return aMul; + } + + inline B3ITuple operator*(const B3ITuple& rTup, sal_Int32 t) + { + B3ITuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B3ITuple operator*(sal_Int32 t, const B3ITuple& rTup) + { + B3ITuple aNew(rTup); + aNew *= t; + return aNew; + } + + inline B3ITuple operator/(const B3ITuple& rTup, sal_Int32 t) + { + B3ITuple aNew(rTup); + aNew /= t; + return aNew; + } + + inline B3ITuple operator/(sal_Int32 t, const B3ITuple& rTup) + { + B3ITuple aNew(t, t, t); + B3ITuple aTmp(rTup); + aNew /= aTmp; + return aNew; + } +} // end of namespace basegfx + +#endif /* _BGFX_TUPLE_B3ITUPLE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b2dsize.hxx b/include/basegfx/vector/b2dsize.hxx new file mode 100644 index 000000000000..bde343b46685 --- /dev/null +++ b/include/basegfx/vector/b2dsize.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B2DSIZE_HXX +#define _BGFX_VECTOR_B2DSIZE_HXX + +#include <basegfx/vector/b2dvector.hxx> + +namespace basegfx +{ + // syntactic sugar: a B2DVector exactly models a Size object, + // thus, for interface clarity, we provide an alias name + + /// Alias name for interface clarity (not everybody is aware of the identity) + typedef B2DVector B2DSize; +} + +#endif /* _BGFX_VECTOR_B2DSIZE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b2dvector.hxx b/include/basegfx/vector/b2dvector.hxx new file mode 100644 index 000000000000..99489eb7169c --- /dev/null +++ b/include/basegfx/vector/b2dvector.hxx @@ -0,0 +1,254 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B2DVECTOR_HXX +#define _BGFX_VECTOR_B2DVECTOR_HXX + +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/vector/b2ivector.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclaration + class B2DHomMatrix; + + /** Base Point class with two double values + + This class derives all operators and common handling for + a 2D data class from B2DTuple. All necessary extensions + which are special for 2D Vectors are added here. + + @see B2DTuple + */ + class BASEGFX_DLLPUBLIC B2DVector : public ::basegfx::B2DTuple + { + public: + /** Create a 2D Vector + + The vector is initialized to (0.0, 0.0) + */ + B2DVector() + : B2DTuple() + {} + + /** Create a 2D Vector + + @param fX + This parameter is used to initialize the X-coordinate + of the 2D Vector. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 2D Vector. + */ + B2DVector(double fX, double fY) + : B2DTuple(fX, fY) + {} + + /** Create a copy of a 2D Vector + + @param rVec + The 2D Vector which will be copied. + */ + B2DVector(const B2DVector& rVec) + : B2DTuple(rVec) + {} + + /** Create a copy of a 2D Vector + + @param rVec + The 2D Vector which will be copied. + */ + explicit B2DVector(const ::basegfx::B2IVector& rVec) + : B2DTuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B2DTuple-based classes + */ + B2DVector(const ::basegfx::B2DTuple& rTuple) + : B2DTuple(rTuple) + {} + + ~B2DVector() + {} + + /** *=operator to allow usage from B2DVector, too + */ + B2DVector& operator*=( const B2DVector& rPnt ) + { + mfX *= rPnt.mfX; + mfY *= rPnt.mfY; + return *this; + } + + /** *=operator to allow usage from B2DVector, too + */ + B2DVector& operator*=(double t) + { + mfX *= t; + mfY *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B2DTuple calculations + */ + B2DVector& operator=( const ::basegfx::B2DTuple& rVec ); + + /** Calculate the length of this 2D Vector + + @return The Length of the 2D Vector + */ + double getLength() const; + + /** Set the length of this 2D Vector + + @param fLen + The to be achieved length of the 2D Vector + */ + B2DVector& setLength(double fLen); + + /** Normalize this 2D Vector + + The length of the 2D Vector is set to 1.0 + */ + B2DVector& normalize(); + + /** Calculate the Scalar with another 2D Vector + + @param rVec + The second 2D Vector + + @return + The Scalar value of the two involved 2D Vectors + */ + double scalar( const B2DVector& rVec ) const; + + /** Calculate the length of the cross product with another 2D Vector + + In 2D, returning an actual vector does not make much + sense here. The magnitude, although, can be readily + used for tasks such as angle calculations, since for + the returned value, the following equation holds: + retVal = getLength(this)*getLength(rVec)*sin(theta), + with theta being the angle between the two vectors. + + @param rVec + The second 2D Vector + + @return + The length of the cross product of the two involved 2D Vectors + */ + double cross( const B2DVector& rVec ) const; + + /** Calculate the Angle with another 2D Vector + + @param rVec + The second 2D Vector + + @return + The Angle value of the two involved 2D Vectors in -pi/2 < return < pi/2 + */ + double angle( const B2DVector& rVec ) const; + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + B2DVector& operator*=( const B2DHomMatrix& rMat ); + + static const B2DVector& getEmptyVector(); + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + /** Calculate the orientation to another 2D Vector + + @param rVecA + The first 2D Vector + + @param rVecB + The second 2D Vector + + @return + The mathematical Orientation of the two involved 2D Vectors + */ + BASEGFX_DLLPUBLIC B2VectorOrientation getOrientation( const B2DVector& rVecA, const B2DVector& rVecB ); + + /** Calculate a perpendicular 2D Vector to the given one + + @param rVec + The source 2D Vector + + @attention This only works if the given 2D Vector is normalized. + + @return + A 2D Vector perpendicular to the one given in parameter rVec + */ + BASEGFX_DLLPUBLIC B2DVector getPerpendicular( const B2DVector& rNormalizedVec ); + + /** Calculate a perpendicular 2D Vector to the given one, + normalize the given one as preparation + + @param rVec + The source 2D Vector + + @return + A normalized 2D Vector perpendicular to the one given in parameter rVec + */ + BASEGFX_DLLPUBLIC B2DVector getNormalizedPerpendicular( const B2DVector& rVec ); + + /** Test two vectors which need not to be normalized for parallelism + + @param rVecA + The first 2D Vector + + @param rVecB + The second 2D Vector + + @return + bool if the two values are parallel. Also true if + one of the vectors is empty. + */ + BASEGFX_DLLPUBLIC bool areParallel( const B2DVector& rVecA, const B2DVector& rVecB ); + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + BASEGFX_DLLPUBLIC B2DVector operator*( const B2DHomMatrix& rMat, const B2DVector& rVec ); + + /** Test continuity between given vectors. + + The two given vectors are assumed to describe control points on a + common point. Calculate if there is a continuity between them. + */ + BASEGFX_DLLPUBLIC B2VectorContinuity getContinuity( const B2DVector& rBackVector, const B2DVector& rForwardVector ); + +} // end of namespace basegfx + +#endif /* _BGFX_VECTOR_B2DVECTOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b2enums.hxx b/include/basegfx/vector/b2enums.hxx new file mode 100644 index 000000000000..abbf4cfaf546 --- /dev/null +++ b/include/basegfx/vector/b2enums.hxx @@ -0,0 +1,70 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B2ENUMS_HXX +#define _BGFX_VECTOR_B2ENUMS_HXX + +#include <sal/types.h> + +namespace basegfx +{ + /** Descriptor for the mathematical orientations of two 2D Vectors + */ + enum B2VectorOrientation + { + /// mathematically positive oriented + ORIENTATION_POSITIVE = 0, + + /// mathematically negative oriented + ORIENTATION_NEGATIVE, + + /// mathematically neutral, thus parallel + ORIENTATION_NEUTRAL + }; + + /** Descriptor for the mathematical continuity of two 2D Vectors + */ + enum B2VectorContinuity + { + /// none + CONTINUITY_NONE = 0, + + /// mathematically negative oriented + CONTINUITY_C1, + + /// mathematically neutral, thus parallel + CONTINUITY_C2 + }; + + /** Descriptor for possible line joins between two line segments + */ + enum B2DLineJoin + { + B2DLINEJOIN_NONE, // no rounding + B2DLINEJOIN_MIDDLE, // calc middle value between joints + B2DLINEJOIN_BEVEL, // join edges with line + B2DLINEJOIN_MITER, // extend till cut + B2DLINEJOIN_ROUND // create arc + }; + +} // end of namespace basegfx + +#endif /* _BGFX_VECTOR_B2ENUMS_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b2isize.hxx b/include/basegfx/vector/b2isize.hxx new file mode 100644 index 000000000000..4a2fe2228661 --- /dev/null +++ b/include/basegfx/vector/b2isize.hxx @@ -0,0 +1,36 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B2ISIZE_HXX +#define _BGFX_VECTOR_B2ISIZE_HXX + +#include <basegfx/vector/b2ivector.hxx> + +namespace basegfx +{ + // syntactic sugar: a B2IVector exactly models a Size object, + // thus, for interface clarity, we provide an alias name + + /// Alias name for interface clarity (not everybody is aware of the identity) + typedef B2IVector B2ISize; +} + +#endif /* _BGFX_VECTOR_B2ISIZE_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b2ivector.hxx b/include/basegfx/vector/b2ivector.hxx new file mode 100644 index 000000000000..63ce2ae28fba --- /dev/null +++ b/include/basegfx/vector/b2ivector.hxx @@ -0,0 +1,146 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B2IVECTOR_HXX +#define _BGFX_VECTOR_B2IVECTOR_HXX + +#include <basegfx/tuple/b2ituple.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclaration + class B2DHomMatrix; + + /** Base Point class with two sal_Int32 values + + This class derives all operators and common handling for + a 2D data class from B2ITuple. All necessary extensions + which are special for 2D Vectors are added here. + + @see B2ITuple + */ + class BASEGFX_DLLPUBLIC B2IVector : public ::basegfx::B2ITuple + { + public: + /** Create a 2D Vector + + The vector is initialized to (0, 0) + */ + B2IVector() + : B2ITuple() + {} + + /** Create a 2D Vector + + @param nX + This parameter is used to initialize the X-coordinate + of the 2D Vector. + + @param nY + This parameter is used to initialize the Y-coordinate + of the 2D Vector. + */ + B2IVector(sal_Int32 nX, sal_Int32 nY) + : B2ITuple(nX, nY) + {} + + /** Create a copy of a 2D Vector + + @param rVec + The 2D Vector which will be copied. + */ + B2IVector(const B2IVector& rVec) + : B2ITuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B2ITuple-based classes + */ + B2IVector(const ::basegfx::B2ITuple& rTuple) + : B2ITuple(rTuple) + {} + + ~B2IVector() + {} + + /** *=operator to allow usage from B2IVector, too + */ + B2IVector& operator*=( const B2IVector& rPnt ) + { + mnX *= rPnt.mnX; + mnY *= rPnt.mnY; + return *this; + } + + /** *=operator to allow usage from B2IVector, too + */ + B2IVector& operator*=(sal_Int32 t) + { + mnX *= t; + mnY *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B2ITuple calculations + */ + B2IVector& operator=( const ::basegfx::B2ITuple& rVec ); + + /** Set the length of this 2D Vector + + @param fLen + The to be achieved length of the 2D Vector + */ + B2IVector& setLength(double fLen); + + /** Calculate the Scalar with another 2D Vector + + @param rVec + The second 2D Vector + + @return + The Scalar value of the two involved 2D Vectors + */ + double scalar( const B2IVector& rVec ) const; + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + B2IVector& operator*=( const B2DHomMatrix& rMat ); + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + BASEGFX_DLLPUBLIC B2IVector operator*( const B2DHomMatrix& rMat, const B2IVector& rVec ); + +} // end of namespace basegfx + +#endif /* _BGFX_VECTOR_B2IVECTOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b3dvector.hxx b/include/basegfx/vector/b3dvector.hxx new file mode 100644 index 000000000000..99f23bc7b6d3 --- /dev/null +++ b/include/basegfx/vector/b3dvector.hxx @@ -0,0 +1,322 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B3DVECTOR_HXX +#define _BGFX_VECTOR_B3DVECTOR_HXX + +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/basegfxdllapi.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predeclaration + class B3DHomMatrix; + + /** Base Point class with three double values + + This class derives all operators and common handling for + a 3D data class from B3DTuple. All necessary extensions + which are special for 3D Vectors are added here. + + @see B3DTuple + */ + class BASEGFX_DLLPUBLIC B3DVector : public ::basegfx::B3DTuple + { + public: + /** Create a 3D Vector + + The vector is initialized to (0.0, 0.0, 0.0) + */ + B3DVector() + : B3DTuple() + {} + + /** Create a 3D Vector + + @param fX + This parameter is used to initialize the X-coordinate + of the 3D Vector. + + @param fY + This parameter is used to initialize the Y-coordinate + of the 3D Vector. + + @param fZ + This parameter is used to initialize the Z-coordinate + of the 3D Vector. + */ + B3DVector(double fX, double fY, double fZ) + : B3DTuple(fX, fY, fZ) + {} + + /** Create a copy of a 3D Vector + + @param rVec + The 3D Vector which will be copied. + */ + B3DVector(const B3DVector& rVec) + : B3DTuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B3DTuple-based classes + */ + B3DVector(const ::basegfx::B3DTuple& rTuple) + : B3DTuple(rTuple) + {} + + ~B3DVector() + {} + + /** *=operator to allow usage from B3DVector, too + */ + B3DVector& operator*=( const B3DVector& rPnt ) + { + mfX *= rPnt.mfX; + mfY *= rPnt.mfY; + mfZ *= rPnt.mfZ; + return *this; + } + + /** *=operator to allow usage from B3DVector, too + */ + B3DVector& operator*=(double t) + { + mfX *= t; + mfY *= t; + mfZ *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B3DTuple calculations + */ + B3DVector& operator=( const ::basegfx::B3DTuple& rVec ) + { + mfX = rVec.getX(); + mfY = rVec.getY(); + mfZ = rVec.getZ(); + return *this; + } + + /** Calculate the length of this 3D Vector + + @return The Length of the 3D Vector + */ + double getLength(void) const + { + double fLen(scalar(*this)); + if((0.0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Calculate the length in the XY-Plane for this 3D Vector + + @return The XY-Plane Length of the 3D Vector + */ + double getXYLength(void) const + { + double fLen((mfX * mfX) + (mfY * mfY)); + if((0.0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Calculate the length in the XZ-Plane for this 3D Vector + + @return The XZ-Plane Length of the 3D Vector + */ + double getXZLength(void) const + { + double fLen((mfX * mfX) + (mfZ * mfZ)); // #i73040# + if((0.0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Calculate the length in the YZ-Plane for this 3D Vector + + @return The YZ-Plane Length of the 3D Vector + */ + double getYZLength(void) const + { + double fLen((mfY * mfY) + (mfZ * mfZ)); + if((0.0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Set the length of this 3D Vector + + @param fLen + The to be achieved length of the 3D Vector + */ + B3DVector& setLength(double fLen) + { + double fLenNow(scalar(*this)); + + if(!::basegfx::fTools::equalZero(fLenNow)) + { + const double fOne(1.0); + + if(!::basegfx::fTools::equal(fOne, fLenNow)) + { + fLen /= sqrt(fLenNow); + } + + mfX *= fLen; + mfY *= fLen; + mfZ *= fLen; + } + + return *this; + } + + /** Normalize this 3D Vector + + The length of the 3D Vector is set to 1.0 + */ + B3DVector& normalize(); + + /** Test if this 3D Vector is normalized + + @return + true if lenth of vector is equal to 1.0 + false else + */ + bool isNormalized() const + { + const double fOne(1.0); + const double fScalar(scalar(*this)); + + return (::basegfx::fTools::equal(fOne, fScalar)); + } + + /** get a 3D Vector which is perpendicular to this and a given 3D Vector + + @attention This only works if this and the given 3D Vector are + both normalized. + + @param rNormalizedVec + A normalized 3D Vector. + + @return + A 3D Vector perpendicular to this and the given one + */ + B3DVector getPerpendicular(const B3DVector& rNormalizedVec) const; + + /** Calculate the Scalar product + + This method calculates the Scalar product between this + and the given 3D Vector. + + @param rVec + A second 3D Vector. + + @return + The Scalar Product of two 3D Vectors + */ + double scalar(const B3DVector& rVec) const + { + return ((mfX * rVec.mfX) + (mfY * rVec.mfY) + (mfZ * rVec.mfZ)); + } + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + B3DVector& operator*=( const B3DHomMatrix& rMat ); + + static const B3DVector& getEmptyVector() + { + return (const B3DVector&) ::basegfx::B3DTuple::getEmptyTuple(); + } + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + /** get a 3D Vector which is in 2D (ignoring + the Z-Coordinate) perpendicular to a given 3D Vector + + @attention This only works if the given 3D Vector is normalized. + + @param rNormalizedVec + A normalized 3D Vector. + + @return + A 3D Vector perpendicular to the given one in X,Y (2D). + */ + inline B3DVector getPerpendicular2D( const B3DVector& rNormalizedVec ) + { + B3DVector aPerpendicular(-rNormalizedVec.getY(), rNormalizedVec.getX(), rNormalizedVec.getZ()); + return aPerpendicular; + } + + /** Test two vectors which need not to be normalized for parallelism + + @param rVecA + The first 3D Vector + + @param rVecB + The second 3D Vector + + @return + bool if the two values are parallel. Also true if + one of the vectors is empty. + */ + BASEGFX_DLLPUBLIC bool areParallel( const B3DVector& rVecA, const B3DVector& rVecB ); + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + BASEGFX_DLLPUBLIC B3DVector operator*( const B3DHomMatrix& rMat, const B3DVector& rVec ); + + /** Calculate the Cross Product of two 3D Vectors + + @param rVecA + A first 3D Vector. + + @param rVecB + A second 3D Vector. + + @return + The Cross Product of both 3D Vectors + */ + inline B3DVector cross(const B3DVector& rVecA, const B3DVector& rVecB) + { + B3DVector aVec( + rVecA.getY() * rVecB.getZ() - rVecA.getZ() * rVecB.getY(), + rVecA.getZ() * rVecB.getX() - rVecA.getX() * rVecB.getZ(), + rVecA.getX() * rVecB.getY() - rVecA.getY() * rVecB.getX()); + return aVec; + } +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_VECTOR_B3DVECTOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/basegfx/vector/b3ivector.hxx b/include/basegfx/vector/b3ivector.hxx new file mode 100644 index 000000000000..8248ade15cb0 --- /dev/null +++ b/include/basegfx/vector/b3ivector.hxx @@ -0,0 +1,249 @@ +/* -*- 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 . + */ + +#ifndef _BGFX_VECTOR_B3IVECTOR_HXX +#define _BGFX_VECTOR_B3IVECTOR_HXX + +#include <basegfx/tuple/b3ituple.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + // predeclaration + class B3DHomMatrix; + + /** Base Point class with three sal_Int32 values + + This class derives all operators and common handling for + a 3D data class from B3ITuple. All necessary extensions + which are special for 3D Vectors are added here. + + @see B3ITuple + */ + class BASEGFX_DLLPUBLIC B3IVector : public ::basegfx::B3ITuple + { + public: + /** Create a 3D Vector + + The vector is initialized to (0, 0, 0) + */ + B3IVector() + : B3ITuple() + {} + + /** Create a 3D Vector + + @param nX + This parameter is used to initialize the X-coordinate + of the 3D Vector. + + @param nY + This parameter is used to initialize the Y-coordinate + of the 3D Vector. + + @param nZ + This parameter is used to initialize the Z-coordinate + of the 3D Vector. + */ + B3IVector(sal_Int32 nX, sal_Int32 nY, sal_Int32 nZ) + : B3ITuple(nX, nY, nZ) + {} + + /** Create a copy of a 3D Vector + + @param rVec + The 3D Vector which will be copied. + */ + B3IVector(const B3IVector& rVec) + : B3ITuple(rVec) + {} + + /** constructor with tuple to allow copy-constructing + from B3ITuple-based classes + */ + B3IVector(const ::basegfx::B3ITuple& rTuple) + : B3ITuple(rTuple) + {} + + ~B3IVector() + {} + + /** *=operator to allow usage from B3IVector, too + */ + B3IVector& operator*=( const B3IVector& rPnt ) + { + mnX *= rPnt.mnX; + mnY *= rPnt.mnY; + mnZ *= rPnt.mnZ; + return *this; + } + + /** *=operator to allow usage from B3IVector, too + */ + B3IVector& operator*=(sal_Int32 t) + { + mnX *= t; + mnY *= t; + mnZ *= t; + return *this; + } + + /** assignment operator to allow assigning the results + of B3ITuple calculations + */ + B3IVector& operator=( const ::basegfx::B3ITuple& rVec ) + { + mnX = rVec.getX(); + mnY = rVec.getY(); + mnZ = rVec.getZ(); + return *this; + } + + /** Calculate the length of this 3D Vector + + @return The Length of the 3D Vector + */ + double getLength(void) const + { + double fLen(scalar(*this)); + if((0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Calculate the length in the XY-Plane for this 3D Vector + + @return The XY-Plane Length of the 3D Vector + */ + double getXYLength(void) const + { + double fLen((mnX * mnX) + (mnY * mnY)); + if((0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Calculate the length in the XZ-Plane for this 3D Vector + + @return The XZ-Plane Length of the 3D Vector + */ + double getXZLength(void) const + { + double fLen((mnX * mnZ) + (mnY * mnZ)); + if((0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Calculate the length in the YZ-Plane for this 3D Vector + + @return The YZ-Plane Length of the 3D Vector + */ + double getYZLength(void) const + { + double fLen((mnY * mnY) + (mnZ * mnZ)); + if((0 == fLen) || (1.0 == fLen)) + return fLen; + return sqrt(fLen); + } + + /** Set the length of this 3D Vector + + @param fLen + The to be achieved length of the 3D Vector + */ + B3IVector& setLength(double fLen) + { + double fLenNow(scalar(*this)); + + if(!::basegfx::fTools::equalZero(fLenNow)) + { + const double fOne(1.0); + + if(!::basegfx::fTools::equal(fOne, fLenNow)) + { + fLen /= sqrt(fLenNow); + } + + mnX = fround(mnX*fLen); + mnY = fround(mnY*fLen); + mnZ = fround(mnZ*fLen); + } + + return *this; + } + + /** Calculate the Scalar product + + This method calculates the Scalar product between this + and the given 3D Vector. + + @param rVec + A second 3D Vector. + + @return + The Scalar Product of two 3D Vectors + */ + double scalar(const B3IVector& rVec) const + { + return ((mnX * rVec.mnX) + (mnY * rVec.mnY) + (mnZ * rVec.mnZ)); + } + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + B3IVector& operator*=( const B3DHomMatrix& rMat ); + }; + + // external operators + ////////////////////////////////////////////////////////////////////////// + + /** Transform vector by given transformation matrix. + + Since this is a vector, translational components of the + matrix are disregarded. + */ + BASEGFX_DLLPUBLIC B3IVector operator*( const B3DHomMatrix& rMat, const B3IVector& rVec ); + + /** Calculate the Cross Product of two 3D Vectors + + @param rVecA + A first 3D Vector. + + @param rVecB + A second 3D Vector. + + @return + The Cross Product of both 3D Vectors + */ + inline B3IVector cross(const B3IVector& rVecA, const B3IVector& rVecB) + { + B3IVector aVec( + rVecA.getY() * rVecB.getZ() - rVecA.getZ() * rVecB.getY(), + rVecA.getZ() * rVecB.getX() - rVecA.getX() * rVecB.getZ(), + rVecA.getX() * rVecB.getY() - rVecA.getY() * rVecB.getX()); + return aVec; + } +} // end of namespace basegfx + +#endif /* _BGFX_VECTOR_B3DVECTOR_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |