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 .
20 #ifndef INCLUDED_SVX_SVDTRANS_HXX
21 #define INCLUDED_SVX_SVDTRANS_HXX
23 #include <rtl/ustring.hxx>
24 #include <sal/log.hxx>
25 #include <svx/svxdllapi.h>
26 #include <tools/fract.hxx>
27 #include <tools/gen.hxx>
28 #include <tools/poly.hxx>
29 #include <vcl/field.hxx>
30 #include <vcl/mapmod.hxx>
32 // The DrawingEngine's angles are specified in 1/100th degrees
33 // We need to convert these angles to radians, in order to be able
34 // to process them with trigonometric functions.
35 // This is done, using the constant nPi180.
38 // nAngle ... is an angle in 1/100 Deg
40 // Which is converted, by this:
41 // double nSin=sin(nAngle*nPi180);
43 // To convert it back, we use division.
44 const double nPi
=3.14159265358979323846;
45 const double nPi180
=0.000174532925199432957692222; // If we have too few digits, we get tan(4500*nPi180)!=1.0
47 // That maximum shear angle
48 #define SDRMAXSHEAR 8900
54 inline long Round(double a
) { return a
>0.0 ? (long)(a
+0.5) : -(long)((-a
)+0.5); }
57 inline void MoveRect(tools::Rectangle
& rRect
, const Size
& S
) { rRect
.Move(S
.Width(),S
.Height()); }
58 inline void MovePoint(Point
& rPnt
, const Size
& S
) { rPnt
.X()+=S
.Width(); rPnt
.Y()+=S
.Height(); }
59 inline void MovePoly(tools::Polygon
& rPoly
, const Size
& S
) { rPoly
.Move(S
.Width(),S
.Height()); }
60 void MoveXPoly(XPolygon
& rPoly
, const Size
& S
);
62 SVX_DLLPUBLIC
void ResizeRect(tools::Rectangle
& rRect
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
);
63 inline void ResizePoint(Point
& rPnt
, const Point
& rRef
, const Fraction
& xFract
, const Fraction
& yFract
);
64 void ResizePoly(tools::Polygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
);
65 void ResizeXPoly(XPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
);
67 inline void RotatePoint(Point
& rPnt
, const Point
& rRef
, double sn
, double cs
);
68 SVX_DLLPUBLIC
void RotatePoly(tools::Polygon
& rPoly
, const Point
& rRef
, double sn
, double cs
);
69 void RotateXPoly(XPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
);
70 void RotateXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
);
72 void MirrorPoint(Point
& rPnt
, const Point
& rRef1
, const Point
& rRef2
);
73 void MirrorXPoly(XPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
);
75 inline void ShearPoint(Point
& rPnt
, const Point
& rRef
, double tn
, bool bVShear
= false);
76 SVX_DLLPUBLIC
void ShearPoly(tools::Polygon
& rPoly
, const Point
& rRef
, double tn
);
77 void ShearXPoly(XPolygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
= false);
80 * rPnt.X/rPnt.Y is set to rCenter.X or rCenter.Y!
81 * We then only need to rotate rPnt by rCenter.
83 * @return the returned angle is in rad
85 inline double GetCrookAngle(Point
& rPnt
, const Point
& rCenter
, const Point
& rRad
, bool bVertical
);
88 * The following methods accept a point of an XPolygon, whereas the neighbouring
89 * control points of the actual point are passed in pC1/pC2.
90 * Via rSin/rCos, sin(nAngle) and cos(nAngle) are returned.
92 * @return the returned angle is in rad
94 double CrookRotateXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
95 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
);
96 double CrookSlantXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
97 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
);
98 double CrookStretchXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
99 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
,
100 const tools::Rectangle
& rRefRect
);
102 void CrookRotatePoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
103 void CrookSlantPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
104 void CrookStretchPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const tools::Rectangle
& rRefRect
);
106 void CrookRotatePoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
107 void CrookSlantPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
);
108 void CrookStretchPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const tools::Rectangle
& rRefRect
);
110 /**************************************************************************************************/
112 /**************************************************************************************************/
114 inline void ResizePoint(Point
& rPnt
, const Point
& rRef
, const Fraction
& xFract
, const Fraction
& yFract
)
116 double nxFract
= xFract
.IsValid() ? static_cast<double>(xFract
) : 1.0;
117 double nyFract
= yFract
.IsValid() ? static_cast<double>(yFract
) : 1.0;
118 rPnt
.X() = rRef
.X() + svx::Round( (rPnt
.X() - rRef
.X()) * nxFract
);
119 rPnt
.Y() = rRef
.Y() + svx::Round( (rPnt
.Y() - rRef
.Y()) * nyFract
);
122 inline void RotatePoint(Point
& rPnt
, const Point
& rRef
, double sn
, double cs
)
124 long dx
=rPnt
.X()-rRef
.X();
125 long dy
=rPnt
.Y()-rRef
.Y();
126 rPnt
.X()=svx::Round(rRef
.X()+dx
*cs
+dy
*sn
);
127 rPnt
.Y()=svx::Round(rRef
.Y()+dy
*cs
-dx
*sn
);
130 inline void ShearPoint(Point
& rPnt
, const Point
& rRef
, double tn
, bool bVShear
)
132 if (!bVShear
) { // Horizontal
133 if (rPnt
.Y()!=rRef
.Y()) { // else not needed
134 rPnt
.X()-=svx::Round((rPnt
.Y()-rRef
.Y())*tn
);
136 } else { // or else vertical
137 if (rPnt
.X()!=rRef
.X()) { // else not needed
138 rPnt
.Y()-=svx::Round((rPnt
.X()-rRef
.X())*tn
);
143 inline double GetCrookAngle(Point
& rPnt
, const Point
& rCenter
, const Point
& rRad
, bool bVertical
)
147 long dy
=rPnt
.Y()-rCenter
.Y();
148 nAngle
=(double)dy
/(double)rRad
.Y();
149 rPnt
.Y()=rCenter
.Y();
151 long dx
=rCenter
.X()-rPnt
.X();
152 nAngle
=(double)dx
/(double)rRad
.X();
153 rPnt
.X()=rCenter
.X();
158 /**************************************************************************************************/
159 /**************************************************************************************************/
162 * The Y axis points down!
163 * The function negates the Y axis, when calculating the angle, such
164 * that GetAngle(Point(0,-1))=90 deg.
165 * GetAngle(Point(0,0)) returns 0.
167 * @return the returned value is in the range of -180.00..179.99 deg
168 * and is in 1/100 deg units
170 SVX_DLLPUBLIC
long GetAngle(const Point
& rPnt
);
172 long NormAngle180(long a
); /// Normalize angle to -180.00..179.99
174 SVX_DLLPUBLIC
long NormAngle360(long a
); /// Normalize angle to 0.00..359.99
176 sal_uInt16
GetAngleSector(long nAngle
); /// Determine sector within the cartesian coordinate system
179 * Calculates the length of (0,0) via a^2 + b^2 = c^2
180 * In order to avoid overflows, we ignore some decimal places.
182 long GetLen(const Point
& rPnt
);
185 * The transformation of a rectangle into a polygon, by
186 * using angle parameters from GeoStat. ------------
187 * The point of reference is always the Point 0, meaning /1 2/
188 * the upper left corner of the initial rectangle. / /
189 * When calculating the polygon, the order is first / /
190 * shear and then the rotation. / /
193 * A) Initial rectangle aRect B) After applying Shear /0 3/ Rot|
194 * +------------------+ -------------------- ------------------
195 * |0 1| \0 1\ C) After applying Rotate
199 * +------------------+ | --------------------
202 * When converting the polygon back into a rect, the order is necessarily the
204 * - Calculating the rotation angle: angle of the line 0-1 in figure C) to the horizontal
205 * - Turning the sheared rect back (we get figure B)
206 * - Determining the width of the rect = length of the line 0-1 in figure B)
207 * - Determining the height of the rect = vertical distance between the points 0 and 3
209 * - Determining the shear angle from the line 0-3 to the perpendicular line.
211 * We need to keep in mind that the polygon can be mirrored when it was
212 * transformed in the mean time (e.g. mirror or resize with negative factor).
213 * In that case, we first need to normalize, by swapping points (0 with 3 and 1
214 * with 2), so that it has the right orientation.
216 * Note: a positive shear angle means a shear with a positive visible curvature
217 * on the screen. Mathematically, that would be a negative curvature, as the
218 * Y axis runs from top to bottom on the screen.
219 * Rotation angle: positive means a visible left rotation.
222 class GeoStat
{ // Geometric state for a rect
226 double nTan
; // tan(nShearAngle)
227 double nSin
; // sin(nRotationAngle)
228 double nCos
; // cos(nRotationAngle)
230 GeoStat(): nRotationAngle(0),nShearAngle(0),nTan(0.0),nSin(0.0),nCos(1.0) {}
235 tools::Polygon
Rect2Poly(const tools::Rectangle
& rRect
, const GeoStat
& rGeo
);
236 void Poly2Rect(const tools::Polygon
& rPol
, tools::Rectangle
& rRect
, GeoStat
& rGeo
);
238 SVX_DLLPUBLIC
void OrthoDistance8(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
);
239 SVX_DLLPUBLIC
void OrthoDistance4(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
);
241 // Multiplication and subsequent division
242 // Calculation and intermediate values are in BigInt
243 SVX_DLLPUBLIC
long BigMulDiv(long nVal
, long nMul
, long nDiv
);
249 FrPair(const Fraction
& rBoth
) : aX(rBoth
),aY(rBoth
) {}
250 FrPair(const Fraction
& rX
, const Fraction
& rY
) : aX(rX
),aY(rY
) {}
251 FrPair(long nMul
, long nDiv
) : aX(nMul
,nDiv
),aY(nMul
,nDiv
) {}
252 FrPair(long xMul
, long xDiv
, long yMul
, long yDiv
): aX(xMul
,xDiv
),aY(yMul
,yDiv
) {}
253 const Fraction
& X() const { return aX
; }
254 const Fraction
& Y() const { return aY
; }
255 Fraction
& X() { return aX
; }
256 Fraction
& Y() { return aY
; }
259 // To convert units of measurement
260 SVX_DLLPUBLIC FrPair
GetMapFactor(MapUnit eS
, MapUnit eD
);
261 FrPair
GetMapFactor(FieldUnit eS
, FieldUnit eD
);
263 inline bool IsMetric(MapUnit eU
) {
264 return (eU
==MapUnit::Map100thMM
|| eU
==MapUnit::Map10thMM
|| eU
==MapUnit::MapMM
|| eU
==MapUnit::MapCM
);
267 inline bool IsInch(MapUnit eU
) {
268 return (eU
==MapUnit::Map1000thInch
|| eU
==MapUnit::Map100thInch
|| eU
==MapUnit::Map10thInch
|| eU
==MapUnit::MapInch
||
269 eU
==MapUnit::MapPoint
|| eU
==MapUnit::MapTwip
);
272 inline bool IsMetric(FieldUnit eU
) {
273 return (eU
==FUNIT_MM
|| eU
==FUNIT_CM
|| eU
==FUNIT_M
|| eU
==FUNIT_KM
|| eU
==FUNIT_100TH_MM
);
276 inline bool IsInch(FieldUnit eU
) {
277 return (eU
==FUNIT_TWIP
|| eU
==FUNIT_POINT
|| eU
==FUNIT_PICA
||
278 eU
==FUNIT_INCH
|| eU
==FUNIT_FOOT
|| eU
==FUNIT_MILE
);
281 class SVX_DLLPUBLIC SdrFormatter
{
289 SVX_DLLPRIVATE
void Undirty();
291 SdrFormatter(MapUnit eSrc
, MapUnit eDst
)
300 void TakeStr(long nVal
, OUString
& rStr
) const;
301 static void TakeUnitStr(MapUnit eUnit
, OUString
& rStr
);
302 static void TakeUnitStr(FieldUnit eUnit
, OUString
& rStr
);
303 static OUString
GetUnitStr(FieldUnit eUnit
) { OUString aStr
; TakeUnitStr(eUnit
,aStr
); return aStr
; }
307 #endif // INCLUDED_SVX_SVDTRANS_HXX
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */