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 .
22 #include <rtl/ustring.hxx>
23 #include <svx/svxdllapi.h>
24 #include <tools/degree.hxx>
25 #include <tools/fldunit.hxx>
26 #include <tools/fract.hxx>
27 #include <tools/gen.hxx>
28 #include <tools/helpers.hxx>
29 #include <tools/mapunit.hxx>
30 #include <tools/poly.hxx>
32 // That maximum shear angle
33 inline constexpr Degree100
SDRMAXSHEAR(8900);
38 inline void MovePoly(tools::Polygon
& rPoly
, const Size
& S
) { rPoly
.Move(S
.Width(),S
.Height()); }
39 void MoveXPoly(XPolygon
& rPoly
, const Size
& S
);
41 SVXCORE_DLLPUBLIC
void ResizeRect(tools::Rectangle
& rRect
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
);
42 inline void ResizePoint(Point
& rPnt
, const Point
& rRef
, const Fraction
& xFract
, const Fraction
& yFract
);
43 void ResizePoly(tools::Polygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
);
44 void ResizeXPoly(XPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
);
46 inline void RotatePoint(Point
& rPnt
, const Point
& rRef
, double sn
, double cs
);
47 SVXCORE_DLLPUBLIC
void RotatePoly(tools::Polygon
& rPoly
, const Point
& rRef
, double sn
, double cs
);
48 void RotateXPoly(XPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
);
49 void RotateXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
);
51 void MirrorPoint(Point
& rPnt
, const Point
& rRef1
, const Point
& rRef2
);
52 void MirrorXPoly(XPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
);
54 inline void ShearPoint(Point
& rPnt
, const Point
& rRef
, double tn
, bool bVShear
= false);
55 SVXCORE_DLLPUBLIC
void ShearPoly(tools::Polygon
& rPoly
, const Point
& rRef
, double tn
);
56 void ShearXPoly(XPolygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
= false);
59 * rPnt.X/rPnt.Y is set to rCenter.X or rCenter.Y!
60 * We then only need to rotate rPnt by rCenter.
62 * @return the returned angle is in rad
64 inline double GetCrookAngle(Point
& rPnt
, const Point
& rCenter
, const Point
& rRad
, bool bVertical
);
67 * The following methods accept a point of an XPolygon, whereas the neighbouring
68 * control points of the actual point are passed in pC1/pC2.
69 * Via rSin/rCos, sin(nAngle) and cos(nAngle) are returned.
71 * @return the returned angle is in rad
73 double CrookRotateXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
74 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
);
75 double CrookSlantXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
76 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
);
77 double CrookStretchXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
78 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
,
79 const tools::Rectangle
& rRefRect
);
81 void CrookRotatePoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
82 void CrookSlantPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
83 void CrookStretchPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const tools::Rectangle
& rRefRect
);
85 void CrookRotatePoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
86 void CrookSlantPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
87 void CrookStretchPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const tools::Rectangle
& rRefRect
);
89 /**************************************************************************************************/
91 /**************************************************************************************************/
93 inline void ResizePoint(Point
& rPnt
, const Point
& rRef
, const Fraction
& xFract
, const Fraction
& yFract
)
95 double nxFract
= xFract
.IsValid() ? static_cast<double>(xFract
) : 1.0;
96 double nyFract
= yFract
.IsValid() ? static_cast<double>(yFract
) : 1.0;
97 rPnt
.setX(rRef
.X() + basegfx::fround
<tools::Long
>((rPnt
.X() - rRef
.X()) * nxFract
));
98 rPnt
.setY(rRef
.Y() + basegfx::fround
<tools::Long
>((rPnt
.Y() - rRef
.Y()) * nyFract
));
101 inline void RotatePoint(Point
& rPnt
, const Point
& rRef
, double sn
, double cs
)
103 tools::Long dx
=rPnt
.X()-rRef
.X();
104 tools::Long dy
=rPnt
.Y()-rRef
.Y();
105 rPnt
.setX(basegfx::fround
<tools::Long
>(rRef
.X() + dx
* cs
+ dy
* sn
));
106 rPnt
.setY(basegfx::fround
<tools::Long
>(rRef
.Y() + dy
* cs
- dx
* sn
));
109 inline void ShearPoint(Point
& rPnt
, const Point
& rRef
, double tn
, bool bVShear
)
111 if (!bVShear
) { // Horizontal
112 if (rPnt
.Y()!=rRef
.Y()) { // else not needed
113 rPnt
.AdjustX(basegfx::fround
<tools::Long
>((rRef
.Y() - rPnt
.Y()) * tn
));
115 } else { // or else vertical
116 if (rPnt
.X()!=rRef
.X()) { // else not needed
117 rPnt
.AdjustY(basegfx::fround
<tools::Long
>((rRef
.X() - rPnt
.X()) * tn
));
122 inline double GetCrookAngle(Point
& rPnt
, const Point
& rCenter
, const Point
& rRad
, bool bVertical
)
126 tools::Long dy
=rPnt
.Y()-rCenter
.Y();
127 nAngle
=static_cast<double>(dy
)/static_cast<double>(rRad
.Y());
128 rPnt
.setY(rCenter
.Y());
130 tools::Long dx
=rCenter
.X()-rPnt
.X();
131 nAngle
=static_cast<double>(dx
)/static_cast<double>(rRad
.X());
132 rPnt
.setX(rCenter
.X());
137 /**************************************************************************************************/
138 /**************************************************************************************************/
141 * The Y axis points down!
142 * The function negates the Y axis, when calculating the angle, such
143 * that GetAngle(Point(0,-1))=90 deg.
144 * GetAngle(Point(0,0)) returns 0.
146 * @return the returned value is in the range of -180.00..179.99 deg
147 * and is in 1/100 deg units
149 SVXCORE_DLLPUBLIC Degree100
GetAngle(const Point
& rPnt
);
151 SVXCORE_DLLPUBLIC Degree100
NormAngle18000(Degree100 a
); /// Normalize angle to -180.00..179.99
153 SVXCORE_DLLPUBLIC Degree100
NormAngle36000(Degree100 a
); /// Normalize angle to 0.00..359.99
155 sal_uInt16
GetAngleSector(Degree100 nAngle
); /// Determine sector within the cartesian coordinate system
158 * Calculates the length of (0,0) via a^2 + b^2 = c^2
159 * In order to avoid overflows, we ignore some decimal places.
161 tools::Long
GetLen(const Point
& rPnt
);
164 * The transformation of a rectangle into a polygon, by
165 * using angle parameters from GeoStat. ------------
166 * The point of reference is always the Point 0, meaning /1 2/
167 * the upper left corner of the initial rectangle. / /
168 * When calculating the polygon, the order is first / /
169 * shear and then the rotation. / /
172 * A) Initial rectangle aRect B) After applying Shear /0 3/ Rot|
173 * +------------------+ -------------------- ------------------
174 * |0 1| \0 1\ C) After applying Rotate
178 * +------------------+ | --------------------
181 * When converting the polygon back into a rect, the order is necessarily the
183 * - Calculating the rotation angle: angle of the line 0-1 in figure C) to the horizontal
184 * - Turning the sheared rect back (we get figure B)
185 * - Determining the width of the rect = length of the line 0-1 in figure B)
186 * - Determining the height of the rect = vertical distance between the points 0 and 3
188 * - Determining the shear angle from the line 0-3 to the perpendicular line.
190 * We need to keep in mind that the polygon can be mirrored when it was
191 * transformed in the meantime (e.g. mirror or resize with negative factor).
192 * In that case, we first need to normalize, by swapping points (0 with 3 and 1
193 * with 2), so that it has the right orientation.
195 * Note: a positive shear angle means a shear with a positive visible curvature
196 * on the screen. Mathematically, that would be a negative curvature, as the
197 * Y axis runs from top to bottom on the screen.
198 * Rotation angle: positive means a visible left rotation.
201 class GeoStat
{ // Geometric state for a rect
203 Degree100 m_nRotationAngle
;
204 Degree100 m_nShearAngle
;
205 double mfTanShearAngle
; // tan(nShearAngle)
206 double mfSinRotationAngle
; // sin(nRotationAngle)
207 double mfCosRotationAngle
; // cos(nRotationAngle)
209 GeoStat(): m_nRotationAngle(0),m_nShearAngle(0),mfTanShearAngle(0.0),mfSinRotationAngle(0.0),mfCosRotationAngle(1.0) {}
214 tools::Polygon
Rect2Poly(const tools::Rectangle
& rRect
, const GeoStat
& rGeo
);
218 tools::Rectangle
polygonToRectangle(const tools::Polygon
& rPolygon
, GeoStat
& rGeo
);
221 void OrthoDistance8(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
);
222 void OrthoDistance4(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
);
224 // Multiplication and subsequent division
225 // Calculation and intermediate values are in BigInt
226 SVXCORE_DLLPUBLIC
tools::Long
BigMulDiv(tools::Long nVal
, tools::Long nMul
, tools::Long nDiv
);
232 FrPair(const Fraction
& rBoth
) : m_aX(rBoth
),m_aY(rBoth
) {}
233 FrPair(const Fraction
& rX
, const Fraction
& rY
) : m_aX(rX
),m_aY(rY
) {}
234 FrPair(tools::Long nMul
, tools::Long nDiv
) : m_aX(nMul
,nDiv
),m_aY(nMul
,nDiv
) {}
235 FrPair(tools::Long xMul
, tools::Long xDiv
, tools::Long yMul
, tools::Long yDiv
): m_aX(xMul
,xDiv
),m_aY(yMul
,yDiv
) {}
236 const Fraction
& X() const { return m_aX
; }
237 const Fraction
& Y() const { return m_aY
; }
238 Fraction
& X() { return m_aX
; }
239 Fraction
& Y() { return m_aY
; }
242 // To convert units of measurement
243 SVXCORE_DLLPUBLIC FrPair
GetMapFactor(MapUnit eS
, MapUnit eD
);
244 FrPair
GetMapFactor(FieldUnit eS
, FieldUnit eD
);
246 inline bool IsMetric(MapUnit eU
) {
247 return (eU
==MapUnit::Map100thMM
|| eU
==MapUnit::Map10thMM
|| eU
==MapUnit::MapMM
|| eU
==MapUnit::MapCM
);
250 inline bool IsInch(MapUnit eU
) {
251 return (eU
==MapUnit::Map1000thInch
|| eU
==MapUnit::Map100thInch
|| eU
==MapUnit::Map10thInch
|| eU
==MapUnit::MapInch
||
252 eU
==MapUnit::MapPoint
|| eU
==MapUnit::MapTwip
);
255 inline bool IsMetric(FieldUnit eU
) {
256 return (eU
== FieldUnit::MM
|| eU
== FieldUnit::CM
|| eU
== FieldUnit::M
257 || eU
== FieldUnit::KM
|| eU
== FieldUnit::MM_100TH
);
260 inline bool IsInch(FieldUnit eU
) {
261 return (eU
== FieldUnit::TWIP
|| eU
== FieldUnit::POINT
262 || eU
== FieldUnit::PICA
|| eU
== FieldUnit::INCH
263 || eU
== FieldUnit::FOOT
|| eU
== FieldUnit::MILE
);
266 class SVXCORE_DLLPUBLIC SdrFormatter
{
274 SVX_DLLPRIVATE
void Undirty();
276 SdrFormatter(MapUnit eSrc
, MapUnit eDst
)
285 OUString
GetStr(tools::Long nVal
) const;
286 static OUString
GetUnitStr(MapUnit eUnit
);
287 static OUString
GetUnitStr(FieldUnit eUnit
);
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */