diff options
Diffstat (limited to 'include/tools/poly.hxx')
-rw-r--r-- | include/tools/poly.hxx | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/include/tools/poly.hxx b/include/tools/poly.hxx new file mode 100644 index 000000000..765865b5a --- /dev/null +++ b/include/tools/poly.hxx @@ -0,0 +1,271 @@ +/* -*- 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_TOOLS_POLY_HXX +#define INCLUDED_TOOLS_POLY_HXX + +#include <tools/toolsdllapi.h> +#include <tools/gen.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <o3tl/cow_wrapper.hxx> + +#include <vector> + +#define POLY_APPEND (0xFFFF) +#define POLYPOLY_APPEND (0xFFFF) + +enum class PolyOptimizeFlags { + NONE = 0x0000, + CLOSE = 0x0001, + NO_SAME = 0x0002, + EDGES = 0x0004, +}; +namespace o3tl +{ + template<> struct typed_flags<PolyOptimizeFlags> : is_typed_flags<PolyOptimizeFlags, 0x0007> {}; +} + +enum class PolyStyle +{ + Arc = 1, + Pie = 2, + Chord = 3 +}; + +enum class PolyFlags : sal_uInt8 +{ + Normal, // start-/endpoint of a curve or a line + Smooth, // smooth transition between curves + Control, // control handles of a Bezier curve + Symmetric // smooth and symmetrical transition between curves +}; + +class SvStream; +class ImplPolygon; +struct ImplPolyPolygon; + +namespace basegfx +{ + class B2DPolygon; + class B2DPolyPolygon; +} + +namespace tools { + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Polygon +{ +public: + typedef o3tl::cow_wrapper<ImplPolygon> ImplType; +private: + ImplType mpImplPolygon; + +public: + static void ImplReduceEdges( tools::Polygon& rPoly, const double& rArea, sal_uInt16 nPercent ); + void ImplRead( SvStream& rIStream ); + void ImplWrite( SvStream& rOStream ) const; + +public: + Polygon(); + Polygon( sal_uInt16 nSize ); + Polygon( sal_uInt16 nPoints, const Point* pPtAry, + const PolyFlags* pFlagAry = nullptr ); + Polygon( const tools::Rectangle& rRect ); + Polygon( const tools::Rectangle& rRect, + sal_uInt32 nHorzRound, sal_uInt32 nVertRound ); + Polygon( const Point& rCenter, + long nRadX, long nRadY ); + Polygon( const tools::Rectangle& rBound, + const Point& rStart, const Point& rEnd, + PolyStyle ePolyStyle = PolyStyle::Arc, + bool bWholeCircle = false ); + Polygon( const Point& rBezPt1, const Point& rCtrlPt1, + const Point& rBezPt2, const Point& rCtrlPt2, + sal_uInt16 nPoints ); + + Polygon( const tools::Polygon& rPoly ); + Polygon( tools::Polygon&& rPoly) noexcept; + ~Polygon(); + + void SetPoint( const Point& rPt, sal_uInt16 nPos ); + const Point& GetPoint( sal_uInt16 nPos ) const; + + void SetFlags( sal_uInt16 nPos, PolyFlags eFlags ); + PolyFlags GetFlags( sal_uInt16 nPos ) const; + bool HasFlags() const; + + bool IsRect() const; + + void SetSize( sal_uInt16 nNewSize ); + sal_uInt16 GetSize() const; + + void Clear(); + + tools::Rectangle GetBoundRect() const; + bool IsInside( const Point& rPt ) const; + double CalcDistance( sal_uInt16 nPt1, sal_uInt16 nPt2 ) const; + void Clip( const tools::Rectangle& rRect ); + void Optimize( PolyOptimizeFlags nOptimizeFlags ); + + /** Adaptive subdivision of polygons with curves + + This method adaptively subdivides bezier arcs within the + polygon to straight line segments and returns the resulting + polygon. + + @param rResult + The resulting subdivided polygon + + @param d + This parameter controls the amount of subdivision. The + original curve is guaranteed to not differ by more than this + amount per bezier segment from the subdivided + lines. Concretely, if the polygon is in device coordinates and + d equals 1.0, then the difference between the subdivided and + the original polygon is guaranteed to be smaller than one + pixel. + */ + void AdaptiveSubdivide( tools::Polygon& rResult, const double d = 1.0 ) const; + static Polygon SubdivideBezier( const Polygon& rPoly ); + + void Move( long nHorzMove, long nVertMove ); + void Translate( const Point& rTrans ); + void Scale( double fScaleX, double fScaleY ); + void Rotate( const Point& rCenter, double fSin, double fCos ); + void Rotate( const Point& rCenter, sal_uInt16 nAngle10 ); + + void Insert( sal_uInt16 nPos, const Point& rPt ); + void Insert( sal_uInt16 nPos, const tools::Polygon& rPoly ); + + const Point& operator[]( sal_uInt16 nPos ) const { return GetPoint( nPos ); } + Point& operator[]( sal_uInt16 nPos ); + + tools::Polygon& operator=( const tools::Polygon& rPoly ); + tools::Polygon& operator=( tools::Polygon&& rPoly ) noexcept; + bool operator==( const tools::Polygon& rPoly ) const; + bool operator!=( const tools::Polygon& rPoly ) const + { return !(Polygon::operator==( rPoly )); } + bool IsEqual( const tools::Polygon& rPoly ) const; + + // streaming a Polygon does ignore PolyFlags, so use the Write Or Read + // method to take care of PolyFlags + TOOLS_DLLPUBLIC friend SvStream& ReadPolygon( SvStream& rIStream, tools::Polygon& rPoly ); + TOOLS_DLLPUBLIC friend SvStream& WritePolygon( SvStream& rOStream, const tools::Polygon& rPoly ); + + void Read( SvStream& rIStream ); + void Write( SvStream& rOStream ) const; + + Point * GetPointAry(); + const Point* GetConstPointAry() const; + const PolyFlags* GetConstFlagAry() const; + + // convert to ::basegfx::B2DPolygon and return + ::basegfx::B2DPolygon getB2DPolygon() const; + + // constructor to convert from ::basegfx::B2DPolygon + // #i76339# made explicit + explicit Polygon(const ::basegfx::B2DPolygon& rPolygon); +}; + + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC PolyPolygon +{ +private: + o3tl::cow_wrapper<ImplPolyPolygon> mpImplPolyPolygon; + + enum class PolyClipOp { + INTERSECT, + UNION + }; + TOOLS_DLLPRIVATE void ImplDoOperation( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult, PolyClipOp nOperation ) const; + +public: + PolyPolygon( sal_uInt16 nInitSize = 16 ); + PolyPolygon( const tools::Polygon& rPoly ); + PolyPolygon( const tools::PolyPolygon& rPolyPoly ); + PolyPolygon( tools::PolyPolygon&& rPolyPoly ) noexcept; + ~PolyPolygon(); + + void Insert( const tools::Polygon& rPoly, sal_uInt16 nPos = POLYPOLY_APPEND ); + void Remove( sal_uInt16 nPos ); + void Replace( const Polygon& rPoly, sal_uInt16 nPos ); + const tools::Polygon& GetObject( sal_uInt16 nPos ) const; + + bool IsRect() const; + + void Clear(); + + sal_uInt16 Count() const; + tools::Rectangle GetBoundRect() const; + void Clip( const tools::Rectangle& rRect ); + void Optimize( PolyOptimizeFlags nOptimizeFlags ); + + /** Adaptive subdivision of polygons with curves + + This method adaptively subdivides bezier arcs within the + polygon to straight line segments and returns the resulting + polygon. + + @param rResult + The resulting subdivided polygon + + If the polygon is in device coordinates, then the difference between the subdivided and + the original polygon is guaranteed to be smaller than one + pixel. + */ + void AdaptiveSubdivide( tools::PolyPolygon& rResult ) const; + static tools::PolyPolygon SubdivideBezier( const tools::PolyPolygon& rPolyPoly ); + + void GetIntersection( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const; + void GetUnion( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const; + + void Move( long nHorzMove, long nVertMove ); + void Translate( const Point& rTrans ); + void Scale( double fScaleX, double fScaleY ); + void Rotate( const Point& rCenter, double fSin, double fCos ); + void Rotate( const Point& rCenter, sal_uInt16 nAngle10 ); + + const tools::Polygon& operator[]( sal_uInt16 nPos ) const { return GetObject( nPos ); } + tools::Polygon& operator[]( sal_uInt16 nPos ); + + tools::PolyPolygon& operator=( const tools::PolyPolygon& rPolyPoly ); + tools::PolyPolygon& operator=( tools::PolyPolygon&& rPolyPoly ) noexcept; + bool operator==( const tools::PolyPolygon& rPolyPoly ) const; + bool operator!=( const tools::PolyPolygon& rPolyPoly ) const + { return !(PolyPolygon::operator==( rPolyPoly )); } + + TOOLS_DLLPUBLIC friend SvStream& ReadPolyPolygon( SvStream& rIStream, tools::PolyPolygon& rPolyPoly ); + TOOLS_DLLPUBLIC friend SvStream& WritePolyPolygon( SvStream& rOStream, const tools::PolyPolygon& rPolyPoly ); + + void Read( SvStream& rIStream ); + void Write( SvStream& rOStream ) const; + + // convert to ::basegfx::B2DPolyPolygon and return + ::basegfx::B2DPolyPolygon getB2DPolyPolygon() const; + + // constructor to convert from ::basegfx::B2DPolyPolygon + // #i76339# made explicit + explicit PolyPolygon(const ::basegfx::B2DPolyPolygon& rPolyPolygon); +}; + +} /* namespace tools */ + +typedef std::vector< tools::PolyPolygon > PolyPolyVector; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |