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 .
19 #ifndef INCLUDED_TOOLS_POLY_HXX
20 #define INCLUDED_TOOLS_POLY_HXX
22 #include <rtl/ustring.hxx>
23 #include <tools/toolsdllapi.h>
24 #include <tools/gen.hxx>
25 #include <tools/degree.hxx>
26 #include <o3tl/typed_flags_set.hxx>
27 #include <o3tl/cow_wrapper.hxx>
31 #define POLY_APPEND (0xFFFF)
32 #define POLYPOLY_APPEND (0xFFFF)
34 enum class PolyOptimizeFlags
{
42 template<> struct typed_flags
<PolyOptimizeFlags
> : is_typed_flags
<PolyOptimizeFlags
, 0x0007> {};
52 enum class PolyFlags
: sal_uInt8
54 Normal
, // start-/endpoint of a curve or a line
55 Smooth
, // smooth transition between curves
56 Control
, // control handles of a Bezier curve
57 Symmetric
// smooth and symmetrical transition between curves
62 struct ImplPolyPolygon
;
72 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Polygon
75 typedef o3tl::cow_wrapper
<ImplPolygon
> ImplType
;
77 ImplType mpImplPolygon
;
80 static void ImplReduceEdges( tools::Polygon
& rPoly
, const double& rArea
, sal_uInt16 nPercent
);
81 void ImplRead( SvStream
& rIStream
);
82 void ImplWrite( SvStream
& rOStream
) const;
86 Polygon( sal_uInt16 nSize
);
87 Polygon( sal_uInt16 nPoints
, const Point
* pPtAry
,
88 const PolyFlags
* pFlagAry
= nullptr );
89 Polygon( const tools::Rectangle
& rRect
);
90 Polygon( const tools::Rectangle
& rRect
,
91 sal_uInt32 nHorzRound
, sal_uInt32 nVertRound
);
92 Polygon( const Point
& rCenter
,
93 tools::Long nRadX
, tools::Long nRadY
);
94 Polygon( const tools::Rectangle
& rBound
,
95 const Point
& rStart
, const Point
& rEnd
,
96 PolyStyle ePolyStyle
= PolyStyle::Arc
,
97 const bool bClockWiseArcDirection
= false);
98 Polygon( const Point
& rBezPt1
, const Point
& rCtrlPt1
,
99 const Point
& rBezPt2
, const Point
& rCtrlPt2
,
100 sal_uInt16 nPoints
);
102 Polygon( const tools::Polygon
& rPoly
);
103 Polygon( tools::Polygon
&& rPoly
) noexcept
;
106 void SetPoint( const Point
& rPt
, sal_uInt16 nPos
);
107 const Point
& GetPoint( sal_uInt16 nPos
) const;
109 void SetFlags( sal_uInt16 nPos
, PolyFlags eFlags
);
110 PolyFlags
GetFlags( sal_uInt16 nPos
) const;
111 bool HasFlags() const;
115 void SetSize( sal_uInt16 nNewSize
);
116 sal_uInt16
GetSize() const;
120 tools::Rectangle
GetBoundRect() const;
121 bool Contains( const Point
& rPt
) const;
122 double CalcDistance( sal_uInt16 nPt1
, sal_uInt16 nPt2
) const;
123 void Clip( const tools::Rectangle
& rRect
);
124 void Optimize( PolyOptimizeFlags nOptimizeFlags
);
126 /** Adaptive subdivision of polygons with curves
128 This method adaptively subdivides bezier arcs within the
129 polygon to straight line segments and returns the resulting
133 The resulting subdivided polygon
136 This parameter controls the amount of subdivision. The
137 original curve is guaranteed to not differ by more than this
138 amount per bezier segment from the subdivided
139 lines. Concretely, if the polygon is in device coordinates and
140 d equals 1.0, then the difference between the subdivided and
141 the original polygon is guaranteed to be smaller than one
144 void AdaptiveSubdivide( tools::Polygon
& rResult
, const double d
= 1.0 ) const;
145 static Polygon
SubdivideBezier( const Polygon
& rPoly
);
147 void Move( tools::Long nHorzMove
, tools::Long nVertMove
);
148 void Translate( const Point
& rTrans
);
149 void Scale( double fScaleX
, double fScaleY
);
150 void Rotate( const Point
& rCenter
, double fSin
, double fCos
);
151 void Rotate( const Point
& rCenter
, Degree10 nAngle10
);
153 void Insert( sal_uInt16 nPos
, const Point
& rPt
);
154 void Insert( sal_uInt16 nPos
, const tools::Polygon
& rPoly
);
156 const Point
& operator[]( sal_uInt16 nPos
) const { return GetPoint( nPos
); }
157 Point
& operator[]( sal_uInt16 nPos
);
159 tools::Polygon
& operator=( const tools::Polygon
& rPoly
);
160 tools::Polygon
& operator=( tools::Polygon
&& rPoly
) noexcept
;
161 bool operator==( const tools::Polygon
& rPoly
) const;
162 bool operator!=( const tools::Polygon
& rPoly
) const
163 { return !(Polygon::operator==( rPoly
)); }
164 bool IsEqual( const tools::Polygon
& rPoly
) const;
166 // streaming a Polygon does ignore PolyFlags, so use the Write Or Read
167 // method to take care of PolyFlags
168 TOOLS_DLLPUBLIC
friend SvStream
& ReadPolygon( SvStream
& rIStream
, tools::Polygon
& rPoly
);
169 TOOLS_DLLPUBLIC
friend SvStream
& WritePolygon( SvStream
& rOStream
, const tools::Polygon
& rPoly
);
171 void Read( SvStream
& rIStream
);
172 void Write( SvStream
& rOStream
) const;
174 Point
* GetPointAry();
175 const Point
* GetConstPointAry() const;
176 const PolyFlags
* GetConstFlagAry() const;
178 // convert to ::basegfx::B2DPolygon and return
179 ::basegfx::B2DPolygon
getB2DPolygon() const;
181 // constructor to convert from ::basegfx::B2DPolygon
182 // #i76339# made explicit
183 explicit Polygon(const ::basegfx::B2DPolygon
& rPolygon
);
187 class SAL_WARN_UNUSED TOOLS_DLLPUBLIC PolyPolygon
190 o3tl::cow_wrapper
<ImplPolyPolygon
> mpImplPolyPolygon
;
192 enum class PolyClipOp
{
196 TOOLS_DLLPRIVATE
void ImplDoOperation( const tools::PolyPolygon
& rPolyPoly
, tools::PolyPolygon
& rResult
, PolyClipOp nOperation
) const;
199 PolyPolygon( sal_uInt16 nInitSize
= 16 );
200 PolyPolygon( const tools::Polygon
& rPoly
);
201 PolyPolygon( const tools::PolyPolygon
& rPolyPoly
);
202 PolyPolygon( tools::PolyPolygon
&& rPolyPoly
) noexcept
;
205 void Insert( const tools::Polygon
& rPoly
, sal_uInt16 nPos
= POLYPOLY_APPEND
);
206 void Remove( sal_uInt16 nPos
);
207 void Replace( const Polygon
& rPoly
, sal_uInt16 nPos
);
208 const tools::Polygon
& GetObject( sal_uInt16 nPos
) const;
214 sal_uInt16
Count() const;
215 tools::Rectangle
GetBoundRect() const;
216 void Clip( const tools::Rectangle
& rRect
);
217 void Optimize( PolyOptimizeFlags nOptimizeFlags
);
219 /** Adaptive subdivision of polygons with curves
221 This method adaptively subdivides bezier arcs within the
222 polygon to straight line segments and returns the resulting
226 The resulting subdivided polygon
228 If the polygon is in device coordinates, then the difference between the subdivided and
229 the original polygon is guaranteed to be smaller than one
232 void AdaptiveSubdivide( tools::PolyPolygon
& rResult
) const;
233 static tools::PolyPolygon
SubdivideBezier( const tools::PolyPolygon
& rPolyPoly
);
235 void GetIntersection( const tools::PolyPolygon
& rPolyPoly
, tools::PolyPolygon
& rResult
) const;
236 void GetUnion( const tools::PolyPolygon
& rPolyPoly
, tools::PolyPolygon
& rResult
) const;
238 void Move( tools::Long nHorzMove
, tools::Long nVertMove
);
239 void Translate( const Point
& rTrans
);
240 void Scale( double fScaleX
, double fScaleY
);
241 void Rotate( const Point
& rCenter
, double fSin
, double fCos
);
242 void Rotate( const Point
& rCenter
, Degree10 nAngle10
);
244 const tools::Polygon
& operator[]( sal_uInt16 nPos
) const { return GetObject( nPos
); }
245 tools::Polygon
& operator[]( sal_uInt16 nPos
);
247 tools::PolyPolygon
& operator=( const tools::PolyPolygon
& rPolyPoly
);
248 tools::PolyPolygon
& operator=( tools::PolyPolygon
&& rPolyPoly
) noexcept
;
249 bool operator==( const tools::PolyPolygon
& rPolyPoly
) const;
250 bool operator!=( const tools::PolyPolygon
& rPolyPoly
) const
251 { return !(PolyPolygon::operator==( rPolyPoly
)); }
253 TOOLS_DLLPUBLIC
friend SvStream
& ReadPolyPolygon( SvStream
& rIStream
, tools::PolyPolygon
& rPolyPoly
);
254 TOOLS_DLLPUBLIC
friend SvStream
& WritePolyPolygon( SvStream
& rOStream
, const tools::PolyPolygon
& rPolyPoly
);
256 void Read( SvStream
& rIStream
);
257 void Write( SvStream
& rOStream
) const;
259 // convert to ::basegfx::B2DPolyPolygon and return
260 ::basegfx::B2DPolyPolygon
getB2DPolyPolygon() const;
262 // constructor to convert from ::basegfx::B2DPolyPolygon
263 // #i76339# made explicit
264 explicit PolyPolygon(const ::basegfx::B2DPolyPolygon
& rPolyPolygon
);
267 template< typename charT
, typename traits
>
268 inline std::basic_ostream
<charT
, traits
> & operator <<(
269 std::basic_ostream
<charT
, traits
> & stream
, const Polygon
& poly
)
271 stream
<< "<" << poly
.GetSize() << ":";
272 for (sal_uInt16 i
= 0; i
< poly
.GetSize(); i
++)
276 stream
<< poly
.GetPoint(i
);
279 if (poly
.GetFlags(i
) == PolyFlags::Normal
)
281 else if (poly
.GetFlags(i
) == PolyFlags::Smooth
)
283 else if (poly
.GetFlags(i
) == PolyFlags::Control
)
285 else if (poly
.GetFlags(i
) == PolyFlags::Symmetric
)
288 stream
<< ";f=" << aFlag
;
294 template< typename charT
, typename traits
>
295 inline std::basic_ostream
<charT
, traits
> & operator <<(
296 std::basic_ostream
<charT
, traits
> & stream
, const PolyPolygon
& poly
)
298 stream
<< "[" << poly
.Count() << ":";
299 for (sal_uInt16 i
= 0; i
< poly
.Count(); i
++)
303 stream
<< poly
.GetObject(i
);
309 } /* namespace tools */
311 typedef std::vector
< tools::PolyPolygon
> PolyPolyVector
;
315 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */