1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #pragma once
21 
22 #include <basegfx/point/b2dpoint.hxx>
23 #include <basegfx/polygon/b3dpolypolygon.hxx>
24 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
25 #include <vector>
26 #include <basegfx/basegfxdllapi.h>
27 #include <o3tl/sorted_vector.hxx>
28 
29 namespace com::sun::star::drawing { struct PolyPolygonBezierCoords; }
30 
31 namespace basegfx
32 {
33     class B2DPolyPolygon;
34     class B2DRange;
35 }
36 
37 namespace basegfx::utils
38 {
39         // B2DPolyPolygon tools
40 
41         // Check and evtl. correct orientations of all contained Polygons so that
42         // the orientations of contained polygons will variate to express areas and
43         // holes
44         BASEGFX_DLLPUBLIC B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate);
45 
46         // make sure polygon with index 0L is not a hole. This may evtl. change the
47         // sequence of polygons, but allows to use polygon with index 0L to
48         // get the correct normal for the whole polyPolygon
49         BASEGFX_DLLPUBLIC B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate);
50 
51         // Subdivide all contained curves. Use distanceBound value if given.
52         BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound, int nRecurseLimit = 30);
53 
54         // Subdivide all contained curves. Use distanceBound value if given. Else, a convenient one
55         // is created.
56         BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound = 0.0);
57 
58         // isInside test for B2dPoint. On border is not inside as long as not true is given
59         // in bWithBorder flag. It is assumed that the orientations of the given polygon are correct.
60         BASEGFX_DLLPUBLIC bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false);
61 
62         /** Get the range of a polyPolygon
63 
64             For detailed description look at getRange(const B2DPolygon&).
65             This method just expands by the range of every sub-Polygon.
66 
67             @param rCandidate
68             The B2DPolyPolygon possibly containing bezier segments
69 
70             @return
71             The outer range of the polygon
72         */
73         BASEGFX_DLLPUBLIC B2DRange getRange(const B2DPolyPolygon& rCandidate);
74 
75         // get signed area of polygon
76         BASEGFX_DLLPUBLIC double getSignedArea(const B2DPolyPolygon& rCandidate);
77 
78         // get area of polygon
79         BASEGFX_DLLPUBLIC double getArea(const B2DPolyPolygon& rCandidate);
80 
81         /** Apply given LineDashing to given polyPolygon
82 
83             For a description see applyLineDashing in b2dpolygontoos.hxx
84         */
85         BASEGFX_DLLPUBLIC void applyLineDashing(
86             const B2DPolyPolygon& rCandidate,
87             const ::std::vector<double>& rDotDashArray,
88             B2DPolyPolygon* pLineTarget,
89             double fFullDashDotLen = 0.0);
90 
91         // test if point is inside epsilon-range around the given PolyPolygon. Can be used
92         // for HitTesting. The epsilon-range is defined to be the tube around the PolyPolygon
93         // with distance fDistance and rounded edges (start and end point).
94         BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance);
95 
96         /** Helper class to transport PointIndices to a PolyPolygon,
97             with an operator< for convenient sorting in a std::set usage
98          */
99         class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC PointIndex
100         {
101         private:
102             sal_uInt32 mnPolygonIndex;
103             sal_uInt32 mnPointIndex;
104 
105         public:
PointIndex(sal_uInt32 nPolygonIndex,sal_uInt32 nPointIndex)106             PointIndex(sal_uInt32 nPolygonIndex, sal_uInt32 nPointIndex)
107             :   mnPolygonIndex(nPolygonIndex),
108                 mnPointIndex(nPointIndex)
109             {}
110 
getPolygonIndex() const111             sal_uInt32 getPolygonIndex() const { return mnPolygonIndex; }
getPointIndex() const112             sal_uInt32 getPointIndex() const { return mnPointIndex; }
113             bool operator<(const PointIndex& rComp) const;
114         };
115 
116         /** the PointIndexSet itself; it allows to define a 'selection'of
117             points in a tools::PolyPolygon by giving the polygon and point index.
118             Adding points double makes no sense, hence the std::set
119          */
120         typedef o3tl::sorted_vector< PointIndex > PointIndexSet;
121 
122         /** Read poly-polygon from SVG.
123 
124             This function imports a poly-polygon from an SVG-D
125             attribute.
126 
127             @param o_rPolyPoly
128             The output poly-polygon
129 
130             @param rSvgDAttribute
131             A valid SVG-D attribute string
132 
133             @param bHandleRelativeNextPointCompatible
134             If set to true, the old error that after a relative 'z' command
135             the current point was not reset to the first point of the current
136             polygon is kept; this is needed to read odf files.
137             If false, pure svg is used; this is needed for svg import.
138 
139             @param pHelpPointIndexSet
140             If given, all points created in the target PolyPolygon
141             which are only helper points are added here using their
142             point indices; this are currently points created from
143             import of the 'a' and 'A' svg:d statements which create
144             bezier curve info as representation and maybe points
145             which are no 'real' svg:d points, but helper points. It
146             is necessary to identify these e.g. when markers need to
147             be created in the svg import
148 
149             @return true, if the string was successfully parsed
150          */
151         BASEGFX_DLLPUBLIC bool importFromSvgD(
152             B2DPolyPolygon& o_rPolyPoly,
153             std::u16string_view rSvgDAttribute,
154             bool bHandleRelativeNextPointCompatible,
155             PointIndexSet* pHelpPointIndexSet);
156 
157         // grow for polyPolygon. Move all geometry in each point in the direction of the normal in that point
158         // with the given amount. Value may be negative.
159         BASEGFX_DLLPUBLIC B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue);
160 
161         // force all sub-polygons to a point count of nSegments
162         BASEGFX_DLLPUBLIC B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments);
163 
164         // create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same
165         // organisation, e.g. same amount of polygons
166         BASEGFX_DLLPUBLIC B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t);
167 
168         // create 3d tools::PolyPolygon from given 2d PolyPolygon. The given fZCoordinate is used to expand the
169         // third coordinate.
170         BASEGFX_DLLPUBLIC B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate = 0.0);
171 
172         // create 2d tools::PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given
173         // matrix and the resulting x,y is used to form the new polygon.
174         BASEGFX_DLLPUBLIC B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat);
175 
176         // for each contained edge in each contained polygon calculate the smallest distance. Return the index to the smallest
177         // edge in rEdgeIndex and the index to the polygon in rPolygonIndex. The relative position on the edge is returned in rCut.
178         // If nothing was found (e.g. empty input plygon), DBL_MAX is returned.
179         BASEGFX_DLLPUBLIC double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut);
180 
181         // distort PolyPolygon. rOriginal describes the original range, where the given points describe the distorted
182         // corresponding points.
183         BASEGFX_DLLPUBLIC B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight);
184 
185         // expand all segments (which are not yet) to curve segments. This is done with setting the control
186         // vectors on the 1/3 resp. 2/3 distances on each segment.
187         BASEGFX_DLLPUBLIC B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate);
188 
189         /** Predicate whether a given poly-polygon is a rectangle.
190 
191             @param rPoly
192             tools::PolyPolygon to check
193 
194             @return true, if the poly-polygon describes a rectangle
195             (contains exactly one polygon, polygon is closed, and the
196             points are either cw or ccw enumerations of a rectangle's
197             vertices). Note that intermediate points and duplicate
198             points are ignored.
199          */
200         BASEGFX_DLLPUBLIC bool isRectangle( const B2DPolyPolygon& rPoly );
201 
202         /** Export poly-polygon to SVG.
203 
204             This function exports a poly-polygon into an SVG-D
205             statement. Currently, output of relative point sequences
206             is not yet supported (might cause slightly larger output)
207 
208             @param rPolyPoly
209             The poly-polygon to export
210 
211             @param bUseRelativeCoordinates
212             When true, all coordinate values are exported as relative
213             to the current position. This tends to save some space,
214             since fewer digits needs to be written.
215 
216             @param bDetectQuadraticBeziers
217             When true, the export tries to detect cubic bezier
218             segments in the input polygon, which can be represented by
219             quadratic bezier segments. Note that the generated string
220             causes versions prior to OOo2.0 to crash.
221 
222             @param bHandleRelativeNextPointCompatible
223             If set to true, the old error that after a relative 'z' command
224             the current point was not reset to the first point of the current
225             polygon is kept; this is needed to read odf files.
226             If false, pure svg is used; this is needed for svg import.
227 
228             @param bOOXMLMotionPath
229             If set to true, export string format that is acceptable for
230             for animation motion path for PowerPoint: always space delimited,
231             never neglect command char, always end with E, and do not export
232             H or V.
233 
234             @return the generated SVG-D statement (the XML d attribute
235             value alone, without any "<path ...>" or "d="...")
236          */
237         BASEGFX_DLLPUBLIC OUString exportToSvgD(
238             const B2DPolyPolygon& rPolyPoly,
239             bool bUseRelativeCoordinates,
240             bool bDetectQuadraticBeziers,
241             bool bHandleRelativeNextPointCompatible,
242             bool bOOXMLMotionPath = false);
243 
244         // #i76891# Try to remove existing curve segments if they are simply edges
245         BASEGFX_DLLPUBLIC B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate);
246 
247         /** Creates polypolygon for seven-segment display number
248 
249             This function takes an integer number between 0 and 9 and
250             convert it into the well-known seven-segment display
251             number (like most digital clocks show their numbers). The
252             digit will exactly fit the unit rectangle. The polypolygon
253             will be a line polygon, i.e. if you need the segment parts
254             to have width, use createAreaGeometry() on the result.
255 
256             @param cNumber
257             Number from '0' to '9' as ASCII char, or '-', 'E' and '.'
258             to convert to 7 segment code
259 
260             @param bLitSegments
261             When true, return a polygon containing the segments that
262             are 'lit' for the given number. Return un-lit segments
263             otherwise.
264          */
265         B2DPolyPolygon createSevenSegmentPolyPolygon(char cNumber, bool bLitSegments);
266 
267         /** snap some polygon coordinates to discrete coordinates
268 
269             This method allows to snap some polygon points to discrete (integer) values
270             which equals e.g. a snap to discrete coordinates. It will snap points of
271             horizontal and vertical edges
272 
273             @param rCandidate
274             The source polygon
275 
276             @return
277             The modified version of the source polygon
278         */
279         BASEGFX_DLLPUBLIC B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate);
280 
281         /// converters for css::drawing::PointSequence
282         BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
283             const css::drawing::PointSequenceSequence& rPointSequenceSequenceSource);
284         BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPointSequenceSequence(
285             const B2DPolyPolygon& rPolyPolygon,
286             css::drawing::PointSequenceSequence& rPointSequenceSequenceRetval);
287 
288         /// converters for css::drawing::PolyPolygonBezierCoords (curved polygons)
289         BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
290             const css::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource);
291         BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
292             const B2DPolyPolygon& rPolyPolygon,
293             css::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval);
294 
295 } // end of namespace basegfx::utils
296 
297 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
298