1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
26 #include <sal/types.h>
27 #include <o3tl/cow_wrapper.hxx>
28 #include <basegfx/vector/b2enums.hxx>
29 #include <basegfx/utils/systemdependentdata.hxx>
30 #include <basegfx/basegfxdllapi.h>
45 class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC B2DPolygon
48 typedef o3tl::cow_wrapper
< ImplB2DPolygon
> ImplType
;
55 /// diverse constructors
57 B2DPolygon(const B2DPolygon
& rPolygon
);
58 B2DPolygon(B2DPolygon
&& rPolygon
);
59 B2DPolygon(const B2DPolygon
& rPolygon
, sal_uInt32 nIndex
, sal_uInt32 nCount
);
60 B2DPolygon(std::initializer_list
<basegfx::B2DPoint
> rPoints
);
64 /// assignment operator
65 B2DPolygon
& operator=(const B2DPolygon
& rPolygon
);
66 B2DPolygon
& operator=(B2DPolygon
&& rPolygon
);
68 /// unshare this polygon with all internally shared instances
72 bool operator==(const B2DPolygon
& rPolygon
) const;
75 sal_uInt32
count() const;
77 /// Coordinate interface
78 basegfx::B2DPoint
const & getB2DPoint(sal_uInt32 nIndex
) const;
79 void setB2DPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
81 /// Coordinate insert/append
82 void insert(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rPoint
, sal_uInt32 nCount
= 1);
83 void append(const basegfx::B2DPoint
& rPoint
, sal_uInt32 nCount
);
84 void append(const basegfx::B2DPoint
& rPoint
);
85 void reserve(sal_uInt32 nCount
);
87 /// Basic ControlPoint interface
88 basegfx::B2DPoint
getPrevControlPoint(sal_uInt32 nIndex
) const;
89 basegfx::B2DPoint
getNextControlPoint(sal_uInt32 nIndex
) const;
90 void setPrevControlPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
91 void setNextControlPoint(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rValue
);
92 void setControlPoints(sal_uInt32 nIndex
, const basegfx::B2DPoint
& rPrev
, const basegfx::B2DPoint
& rNext
);
94 /// ControlPoint resets
95 void resetPrevControlPoint(sal_uInt32 nIndex
);
96 void resetNextControlPoint(sal_uInt32 nIndex
);
97 void resetControlPoints();
99 /// Bezier segment append with control points. The current last polygon point is implicitly taken as start point.
100 void appendBezierSegment(const basegfx::B2DPoint
& rNextControlPoint
,
101 const basegfx::B2DPoint
& rPrevControlPoint
,
102 const basegfx::B2DPoint
& rPoint
);
104 /// This is a shortcut to append a quadratic bezier segment. The current last polygon point is implicitly taken as start point.
105 /// Note that the quadratic bezier control points will be converted to cubic bezier with 2 control points.
106 void appendQuadraticBezierSegment(const basegfx::B2DPoint
& rQuadControlPoint
,
107 const basegfx::B2DPoint
& rPoint
);
109 /// ControlPoint checks
110 bool areControlPointsUsed() const;
111 bool isPrevControlPointUsed(sal_uInt32 nIndex
) const;
112 bool isNextControlPointUsed(sal_uInt32 nIndex
) const;
113 B2VectorContinuity
getContinuityInPoint(sal_uInt32 nIndex
) const;
115 /** bezier segment access
117 This method also works when it is no bezier segment at all and will fill
118 the given B2DCubicBezier as needed.
119 In any case, the given B2DCubicBezier will be filled, if necessary with
120 the single start point (if no valid edge exists).
123 Index of the addressed edge's start point
126 The B2DCubicBezier to be filled. It's data WILL be changed.
128 void getBezierSegment(sal_uInt32 nIndex
, B2DCubicBezier
& rTarget
) const;
130 /** Default adaptive subdivision access
132 This method will return a default adaptive subdivision of the polygon.
133 If the polygon does not contain any bezier curve segments, it will
136 The subdivision is created on first request and buffered, so when using
137 this subdivision You have the guarantee for fast accesses for multiple
138 usages. It is intended for tooling usage for tasks which would be hard
139 to accomplish on bezier segments (e.g. isInEpsilonRange).
141 The current default subdivision uses adaptiveSubdivideByCount with 9
142 subdivisions which gives 10 edges and 11 points per segment and is
143 usually pretty usable for processing purposes. There is no parameter
144 passing here ATM but it may be changed on demand. If needed, a TYPE
145 and PARAMETER (both defaulted) may be added to allow for switching
146 between the different kinds of subdivisioned and passing them one
149 The lifetime of the buffered subdivision is based on polygon changes.
150 When changing the polygon, it will be flushed. It is buffered at the
151 refcounted implementation class, so it will survive copy by value and
152 combinations in PolyPolygons.
155 The default (and buffered) subdivision of this polygon. It may
156 be this polygon itself when it has no bezier segments. It is guaranteed
157 to have no more bezier segments
159 B2DPolygon
const & getDefaultAdaptiveSubdivision() const;
161 /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon
163 A polygon may have up to three ranges:
165 (a) the range of the polygon points
166 (b) the range of the polygon points and control points
167 (c) the outer range of the subdivided bezier curve
169 Ranges (a) and (c) are produced by tools::getRange(); resp. this
170 getB2DRange(). tools::getRangeWithControlPoints handles case (b).
172 To get range (c) a simple solution would be to subdivide the polygon
173 and use getRange() on it. Since subdivision is expensive and decreases
174 the polygon quality, i added this new method. It will use a
175 methodology suggested by HDU. First, it gets the range (a).
176 Then it iterates over the bezier segments and for each it
177 first tests if the outer range of the bezier segment is already
178 contained in the result range.
180 The subdivision itself uses getAllExtremumPositions() to only
181 calculate extremum points and to expand the result accordingly.
182 Thus it calculates maximal four extremum points on the bezier
183 segment, no split is used at all.
186 The outer range of the bezier curve/polygon
188 B2DRange
const & getB2DRange() const;
190 /** append other 2D polygons
192 The default (nIndex ==0 && nCount == 0) will append
199 The index to the first point of rPoly to append
202 The number of points to append from rPoly, starting
203 from nIndex. If zero, as much as possible is appended
205 void append(const B2DPolygon
& rPoly
, sal_uInt32 nIndex
= 0, sal_uInt32 nCount
= 0);
208 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
= 1);
213 /// closed state interface
214 bool isClosed() const;
215 void setClosed(bool bNew
);
217 /// flip polygon direction
220 /// test if Polygon has double points
221 bool hasDoublePoints() const;
223 /// remove double points, at the begin/end and follow-ups, too
224 void removeDoublePoints();
226 /// apply transformation given in matrix form
227 void transform(const basegfx::B2DHomMatrix
& rMatrix
);
229 // exclusive management op's for SystemDependentData at B2DPolygon
231 std::shared_ptr
<T
> getSystemDependentData(basegfx::SDD_Type aType
) const
233 return std::static_pointer_cast
<T
>(getSystemDependantDataInternal(aType
));
236 template<class T
, class... Args
>
237 std::shared_ptr
<T
> addOrReplaceSystemDependentData(Args
&&... args
) const
239 std::shared_ptr
<T
> r
= std::make_shared
<T
>(std::forward
<Args
>(args
)...);
241 // tdf#129845 only add to buffer if a relevant buffer time is estimated
242 if(r
->calculateCombinedHoldCyclesInSeconds() > 0)
244 basegfx::SystemDependentData_SharedPtr
r2(r
);
245 addOrReplaceSystemDependentDataInternal(r2
);
252 void addOrReplaceSystemDependentDataInternal(SystemDependentData_SharedPtr
& rData
) const;
253 SystemDependentData_SharedPtr
getSystemDependantDataInternal(basegfx::SDD_Type aType
) const;
254 const basegfx::B2DVector
& getPrevControlVector(sal_uInt32 nIndex
) const;
255 const basegfx::B2DVector
& getNextControlVector(sal_uInt32 nIndex
) const;
258 // typedef for a vector of B2DPolygons
259 typedef ::std::vector
< B2DPolygon
> B2DPolygonVector
;
261 template< typename charT
, typename traits
>
262 inline std::basic_ostream
<charT
, traits
> & operator <<(
263 std::basic_ostream
<charT
, traits
> & stream
, const B2DPolygon
& poly
)
265 stream
<< "<" << poly
.count() << ":";
266 for (sal_uInt32 i
= 0; i
< poly
.count(); i
++)
270 stream
<< poly
.getB2DPoint(i
);
277 } // end of namespace basegfx
279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */