1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #ifndef _SVDTRANS_HXX
23 #define _SVDTRANS_HXX
24
25 #include <tools/gen.hxx>
26 #include <tools/poly.hxx>
27 #include <tools/fract.hxx>
28
29 #ifndef _MAPMOD_HXX //autogen
30 #include <vcl/mapmod.hxx>
31 #endif
32 #include <tools/string.hxx>
33 #include "svx/svxdllapi.h"
34
35 #include <vcl/field.hxx>
36
37 // Winkelangaben der DrawingEngine sind 1/100 Degree
38 // #i19054# nowhere used, removed // const int nWinkDiv=100;
39 // Um Winkel der DrawingEngine mit den Trigonometrischen Funktionen
40 // verarbeiten zu können, müssen sie zunächst ins Bogenmaß umgerechnet
41 // werden. Dies gestaltet sich recht einfach mit der folgenden Konstanten
42 // nPi180. Sei nWink ein Winkel in 1/100 Deg so schreibt man z.B.:
43 // double nSin=sin(nWink*nPi180);
44 // Rückwandlung entsprechend durch Teilen.
45 const double nPi=3.14159265358979323846;
46 const double nPi180=0.000174532925199432957692222; // Bei zu wenig Stellen ist tan(4500*nPi180)!=1.0
47
48 // Der maximale Shearwinkel
49 #define SDRMAXSHEAR 8900
50
51 class XPolygon;
52 class XPolyPolygon;
53
Round(double a)54 inline long Round(double a) { return a>0.0 ? (long)(a+0.5) : -(long)((-a)+0.5); }
55
MoveRect(Rectangle & rRect,const Size & S)56 inline void MoveRect(Rectangle& rRect, const Size& S) { rRect.Move(S.Width(),S.Height()); }
MovePoint(Point & rPnt,const Size & S)57 inline void MovePoint(Point& rPnt, const Size& S) { rPnt.X()+=S.Width(); rPnt.Y()+=S.Height(); }
MovePoly(Polygon & rPoly,const Size & S)58 inline void MovePoly(Polygon& rPoly, const Size& S) { rPoly.Move(S.Width(),S.Height()); }
MovePoly(PolyPolygon & rPoly,const Size & S)59 inline void MovePoly(PolyPolygon& rPoly, const Size& S) { rPoly.Move(S.Width(),S.Height()); }
60 void MoveXPoly(XPolygon& rPoly, const Size& S);
61 void MoveXPoly(XPolyPolygon& rPoly, const Size& S);
62
63 SVX_DLLPUBLIC void ResizeRect(Rectangle& rRect, const Point& rRef, const Fraction& xFact, const Fraction& yFact, FASTBOOL bNoJustify=sal_False);
64 inline void ResizePoint(Point& rPnt, const Point& rRef, Fraction xFact, Fraction yFact);
65 void ResizePoly(Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
66 void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
67 void ResizePoly(PolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
68 void ResizeXPoly(XPolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
69
70 inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs);
71 SVX_DLLPUBLIC void RotatePoly(Polygon& rPoly, const Point& rRef, double sn, double cs);
72 void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs);
73 void RotatePoly(PolyPolygon& rPoly, const Point& rRef, double sn, double cs);
74 void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs);
75
76 // MirrorRect macht nur Sinn bei Spiegelachsen
77 // mit einem durch 45 Degree teilbaren Winkel!
78 void MirrorRect(Rectangle& rRect, const Point& rRef1, const Point& rRef2, FASTBOOL bNoJustify); // ni.
79 void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2);
80 void MirrorPoly(Polygon& rPoly, const Point& rRef1, const Point& rRef2);
81 void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2);
82 void MirrorPoly(PolyPolygon& rPoly, const Point& rRef1, const Point& rRef2);
83 void MirrorXPoly(XPolyPolygon& rPoly, const Point& rRef1, const Point& rRef2);
84
85 inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
86 SVX_DLLPUBLIC void ShearPoly(Polygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
87 void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
88 void ShearPoly(PolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
89 void ShearXPoly(XPolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
90
91 // rPnt.X bzw rPnt.Y wird auf rCenter.X bzw. rCenter.Y gesetzt!
92 // anschließend muss rPnt nur noch um rCenter gedreht werden.
93 // Der Rückgabewinkel ist ausnahmsweise in Rad.
94 inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, FASTBOOL bVertical);
95 // Die folgenden Methoden behandeln einen Punkt eines XPolygons, wobei die
96 // benachbarten Kontrollpunkte des eigentlichen Punktes ggf. in pC1/pC2
97 // übergeben werden. Über rSin/rCos wird gleichzeitig sin(nWink) und cos(nWink)
98 // zurückgegeben.
99 // Der Rückgabewinkel ist hier ebenfalls in Rad.
100 double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
101 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert);
102 double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
103 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert);
104 double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
105 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert,
106 const Rectangle rRefRect);
107
108 void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
109 void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
110 void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect);
111
112 void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
113 void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
114 void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect);
115
116 /**************************************************************************************************/
117 /* Inline */
118 /**************************************************************************************************/
119
ResizePoint(Point & rPnt,const Point & rRef,Fraction xFact,Fraction yFact)120 inline void ResizePoint(Point& rPnt, const Point& rRef, Fraction xFact, Fraction yFact)
121 {
122 if (xFact.GetDenominator()==0) xFact=Fraction(xFact.GetNumerator(),1); // DivZero abfangen
123 if (yFact.GetDenominator()==0) yFact=Fraction(yFact.GetNumerator(),1); // DivZero abfangen
124 rPnt.X()=rRef.X()+ Round(((double)(rPnt.X()-rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
125 rPnt.Y()=rRef.Y()+ Round(((double)(rPnt.Y()-rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
126 }
127
RotatePoint(Point & rPnt,const Point & rRef,double sn,double cs)128 inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs)
129 {
130 long dx=rPnt.X()-rRef.X();
131 long dy=rPnt.Y()-rRef.Y();
132 rPnt.X()=Round(rRef.X()+dx*cs+dy*sn);
133 rPnt.Y()=Round(rRef.Y()+dy*cs-dx*sn);
134 }
135
ShearPoint(Point & rPnt,const Point & rRef,double tn,FASTBOOL bVShear)136 inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, FASTBOOL bVShear)
137 {
138 if (!bVShear) { // Horizontal
139 if (rPnt.Y()!=rRef.Y()) { // sonst nicht nötig
140 rPnt.X()-=Round((rPnt.Y()-rRef.Y())*tn);
141 }
142 } else { // ansonsten vertikal
143 if (rPnt.X()!=rRef.X()) { // sonst nicht nötig
144 rPnt.Y()-=Round((rPnt.X()-rRef.X())*tn);
145 }
146 }
147 }
148
GetCrookAngle(Point & rPnt,const Point & rCenter,const Point & rRad,FASTBOOL bVertical)149 inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, FASTBOOL bVertical)
150 {
151 double nWink;
152 if (bVertical) {
153 long dy=rPnt.Y()-rCenter.Y();
154 nWink=(double)dy/(double)rRad.Y();
155 rPnt.Y()=rCenter.Y();
156 } else {
157 long dx=rCenter.X()-rPnt.X();
158 nWink=(double)dx/(double)rRad.X();
159 rPnt.X()=rCenter.X();
160 }
161 return nWink;
162 }
163
164 /**************************************************************************************************/
165 /**************************************************************************************************/
166
167 // Y-Achse zeigt nach unten! Die Funktion negiert bei der
168 // Winkelberechnung die Y-Achse, sodass GetAngle(Point(0,-1))=90.00deg.
169 // GetAngle(Point(0,0)) liefert 0.
170 // Der Rückgabewert liegt im Bereich -180.00..179.99 Degree und
171 // ist in 1/100 Degree angegeben.
172 SVX_DLLPUBLIC long GetAngle(const Point& rPnt);
173 long NormAngle180(long a); // Winkel normalisieren auf -180.00..179.99
174 SVX_DLLPUBLIC long NormAngle360(long a); // Winkel normalisieren auf 0.00..359.99
175 sal_uInt16 GetAngleSector(long nWink); // Sektor im kartesischen Koordinatensystem bestimmen
176 // Berechnet die Länge von (0,0) via a^2 + b^2 = c^2
177 // Zur Vermeidung von Überläufen werden ggf. einige Stellen ignoriert.
178 long GetLen(const Point& rPnt);
179
180 /*
181 Transformation eines Rechtecks in ein Polygon unter ------------
182 Anwendung der Winkelparameter aus GeoStat. /1 2/
183 Referenzpunkt ist stets der Punkt 0, also die linke / /
184 obere Ecke des Ausgangsrects. / /
185 Bei der Berechnung des Polygons ist die Reihenfolge / /
186 (erst Shear, dann Rotation vorgegeben). / / \
187 / / |
188 A) Ausgangsrechteck aRect B) Nach Anwendung von Shear /0 3/ Rot|
189 +------------------+ -------------------- ------------ ------
190 |0 1| \0 1\ C) Nach Anwendung
191 | | \ \ von Rotate
192 | | | \ \
193 |3 2| | \3 2\
194 +------------------+ | --------------------
195 |Shr |
196 Bei Rückkonvertierung des Polygons in ein Rect ist die Reihenfolge
197 zwangsläufig umgekehrt:
198 - Berechnung des Drehwinkels: Winkel der Strecke 0-1 aus Abb. C) zum Horizont
199 - Rückdrehung des geshearten Rects (man erhält Abb B))
200 - Bestimmung der Breite des Rects=Länge der Strecke 0-1 aus Abb. B)
201 - Bestimmung der Höhe des Rects=vertikaler Abstand zwischen den Punkten
202 0 und 3 aus Abb. B)
203 - Bestimmung des Shear-Winkels aus der Strecke 0-3 zur Senkrechten.
204 Es ist darauf zu achten, dass das Polygon bei einer zwischenzeitlichen
205 Transformation evtl. gespiegelt wurde (Mirror oder Resize mit neg. Faktor).
206 In diesem Fall muss zunächst eine Normalisierung durch Vertauschung der
207 Punkte (z.B. 0 mit 3 und 1 mit 2) durchgeführt werden, damit der
208 Richtungssinn im Polygon wieder stimmig ist.
209 Hinweis: Positiver Shear-Winkel bedeutet Shear mit auf dem Bildschirm
210 sichtbarer positiver Kursivierung. Mathematisch wäre dass eine negative
211 Kursivierung, da die Y-Achse auf dem Bildschirm von oben nach unten verläuft.
212 Drehwinkel: Positiv bedeutet auf dem Bildschirm sichtbare Linksdrehung.
213 */
214
215 class GeoStat { // Geometrischer Status für ein Rect
216 public:
217 long nDrehWink;
218 long nShearWink;
219 double nTan; // tan(nShearWink)
220 double nSin; // sin(nDrehWink)
221 double nCos; // cos(nDrehWink)
222 bool bMirrored; // Horizontal gespiegelt? (ni)
223 public:
GeoStat()224 GeoStat(): nDrehWink(0),nShearWink(0),nTan(0.0),nSin(0.0),nCos(1.0),bMirrored(false) {}
225 void RecalcSinCos();
226 void RecalcTan();
227 };
228
229 Polygon Rect2Poly(const Rectangle& rRect, const GeoStat& rGeo);
230 void Poly2Rect(const Polygon& rPol, Rectangle& rRect, GeoStat& rGeo);
231
232 SVX_DLLPUBLIC void OrthoDistance8(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho);
233 SVX_DLLPUBLIC void OrthoDistance4(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho);
234
235 // Multiplikation und anschließende Division.
236 // Rechnung und Zwischenergebnis sind BigInt.
237 SVX_DLLPUBLIC long BigMulDiv(long nVal, long nMul, long nDiv);
238
239
240 class FrPair {
241 Fraction aX;
242 Fraction aY;
243 public:
FrPair()244 FrPair() : aX(0,1),aY(0,1) {}
FrPair(const Fraction & rBoth)245 FrPair(const Fraction& rBoth) : aX(rBoth),aY(rBoth) {}
FrPair(const Fraction & rX,const Fraction & rY)246 FrPair(const Fraction& rX, const Fraction& rY) : aX(rX),aY(rY) {}
FrPair(long nMul,long nDiv)247 FrPair(long nMul, long nDiv) : aX(nMul,nDiv),aY(nMul,nDiv) {}
FrPair(long xMul,long xDiv,long yMul,long yDiv)248 FrPair(long xMul, long xDiv, long yMul, long yDiv): aX(xMul,xDiv),aY(yMul,yDiv) {}
X() const249 const Fraction& X() const { return aX; }
Y() const250 const Fraction& Y() const { return aY; }
X()251 Fraction& X() { return aX; }
Y()252 Fraction& Y() { return aY; }
253 };
254
255 // Für die Umrechnung von Maßeinheiten
256 SVX_DLLPUBLIC FrPair GetMapFactor(MapUnit eS, MapUnit eD);
257 FrPair GetMapFactor(MapUnit eS, FieldUnit eD);
258 FrPair GetMapFactor(FieldUnit eS, MapUnit eD);
259 FrPair GetMapFactor(FieldUnit eS, FieldUnit eD);
260
IsMetric(MapUnit eU)261 inline FASTBOOL IsMetric(MapUnit eU) {
262 return (eU==MAP_100TH_MM || eU==MAP_10TH_MM || eU==MAP_MM || eU==MAP_CM);
263 }
264
IsInch(MapUnit eU)265 inline FASTBOOL IsInch(MapUnit eU) {
266 return (eU==MAP_1000TH_INCH || eU==MAP_100TH_INCH || eU==MAP_10TH_INCH || eU==MAP_INCH ||
267 eU==MAP_POINT || eU==MAP_TWIP);
268 }
269
IsMetric(FieldUnit eU)270 inline FASTBOOL IsMetric(FieldUnit eU) {
271 return (eU==FUNIT_MM || eU==FUNIT_CM || eU==FUNIT_M || eU==FUNIT_KM || eU==FUNIT_100TH_MM);
272 }
273
IsInch(FieldUnit eU)274 inline FASTBOOL IsInch(FieldUnit eU) {
275 return (eU==FUNIT_TWIP || eU==FUNIT_POINT || eU==FUNIT_PICA ||
276 eU==FUNIT_INCH || eU==FUNIT_FOOT || eU==FUNIT_MILE);
277 }
278
279 class SVX_DLLPUBLIC SdrFormatter {
280 Fraction aScale;
281 long nMul_;
282 long nDiv_;
283 short nComma_;
284 FASTBOOL bSrcFU;
285 FASTBOOL bDstFU;
286 FASTBOOL bDirty;
287 MapUnit eSrcMU;
288 MapUnit eDstMU;
289 FieldUnit eSrcFU;
290 FieldUnit eDstFU;
291 private:
292 SVX_DLLPRIVATE void Undirty();
ForceUndirty() const293 SVX_DLLPRIVATE void ForceUndirty() const { if (bDirty) ((SdrFormatter*)this)->Undirty(); }
294 public:
SdrFormatter(MapUnit eSrc,MapUnit eDst)295 SdrFormatter(MapUnit eSrc, MapUnit eDst) { eSrcMU=eSrc; bSrcFU=sal_False; eDstMU=eDst; bDstFU=sal_False; bDirty=sal_True; }
SdrFormatter(MapUnit eSrc,FieldUnit eDst)296 SdrFormatter(MapUnit eSrc, FieldUnit eDst) { eSrcMU=eSrc; bSrcFU=sal_False; eDstFU=eDst; bDstFU=sal_True; bDirty=sal_True; }
SdrFormatter(FieldUnit eSrc,MapUnit eDst)297 SdrFormatter(FieldUnit eSrc, MapUnit eDst) { eSrcFU=eSrc; bSrcFU=sal_True; eDstMU=eDst; bDstFU=sal_False; bDirty=sal_True; }
SdrFormatter(FieldUnit eSrc,FieldUnit eDst)298 SdrFormatter(FieldUnit eSrc, FieldUnit eDst) { eSrcFU=eSrc; bSrcFU=sal_True; eDstFU=eDst; bDstFU=sal_True; bDirty=sal_True; }
SetSourceUnit(MapUnit eSrc)299 void SetSourceUnit(MapUnit eSrc) { eSrcMU=eSrc; bSrcFU=sal_False; bDirty=sal_True; }
SetSourceUnit(FieldUnit eSrc)300 void SetSourceUnit(FieldUnit eSrc) { eSrcFU=eSrc; bSrcFU=sal_True; bDirty=sal_True; }
SetDestinationUnit(MapUnit eDst)301 void SetDestinationUnit(MapUnit eDst) { eDstMU=eDst; bDstFU=sal_False; bDirty=sal_True; }
SetDestinationUnit(FieldUnit eDst)302 void SetDestinationUnit(FieldUnit eDst) { eDstFU=eDst; bDstFU=sal_True; bDirty=sal_True; }
303 void TakeStr(long nVal, XubString& rStr) const;
304 static void TakeUnitStr(MapUnit eUnit, XubString& rStr);
305 static void TakeUnitStr(FieldUnit eUnit, XubString& rStr);
GetUnitStr(MapUnit eUnit)306 static XubString GetUnitStr(MapUnit eUnit) { XubString aStr; TakeUnitStr(eUnit,aStr); return aStr; }
GetUnitStr(FieldUnit eUnit)307 static XubString GetUnitStr(FieldUnit eUnit) { XubString aStr; TakeUnitStr(eUnit,aStr); return aStr; }
308 };
309
310 #endif //_SVDTRANS_HXX
311
312 /* vim: set noet sw=4 ts=4: */
313