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
23
24 #ifndef _SVDTRANS_HXX
25 #define _SVDTRANS_HXX
26
27 #include <tools/gen.hxx>
28 #include <tools/poly.hxx>
29 #include <tools/fract.hxx>
30
31 #ifndef _MAPMOD_HXX //autogen
32 #include <vcl/mapmod.hxx>
33 #endif
34 #include <tools/string.hxx>
35 #include "svx/svxdllapi.h"
36
37 #include <vcl/field.hxx>
38
39 ////////////////////////////////////////////////////////////////////////////////////////////////////
40
41 // Winkelangaben der DrawingEngine sind 1/100 Degree
42 // #i19054# nowhere used, removed // const int nWinkDiv=100;
43 // Um Winkel der DrawingEngine mit den Trigonometrischen Funktionen
44 // verarbeiten zu koennen, muessen sie zunaest ins Bogenmass umgerechnet
45 // werden. Dies gestaltet sich recht einfach mit der folgenden Konstanten
46 // nPi180. Sei nWink ein Winkel in 1/100 Deg so schreibt man z.B.:
47 // double nSin=sin(nWink*nPi180);
48 // Rueckwandlung entsprechend durch Teilen.
49 const double nPi=3.14159265358979323846;
50 const double nPi180=0.000174532925199432957692222; // Bei zuweing Stellen ist tan(4500*nPi180)!=1.0
51
52 // Der maximale Shearwinkel
53 #define SDRMAXSHEAR 8900
54
55 class XPolygon;
56 class XPolyPolygon;
57
Round(double a)58 inline long Round(double a) { return a>0.0 ? (long)(a+0.5) : -(long)((-a)+0.5); }
59
MoveRect(Rectangle & rRect,const Size & S)60 inline void MoveRect(Rectangle& rRect, const Size& S) { rRect.Move(S.Width(),S.Height()); }
MovePoint(Point & rPnt,const Size & S)61 inline void MovePoint(Point& rPnt, const Size& S) { rPnt.X()+=S.Width(); rPnt.Y()+=S.Height(); }
MovePoly(Polygon & rPoly,const Size & S)62 inline void MovePoly(Polygon& rPoly, const Size& S) { rPoly.Move(S.Width(),S.Height()); }
MovePoly(PolyPolygon & rPoly,const Size & S)63 inline void MovePoly(PolyPolygon& rPoly, const Size& S) { rPoly.Move(S.Width(),S.Height()); }
64 void MoveXPoly(XPolygon& rPoly, const Size& S);
65 void MoveXPoly(XPolyPolygon& rPoly, const Size& S);
66
67 SVX_DLLPUBLIC void ResizeRect(Rectangle& rRect, const Point& rRef, const Fraction& xFact, const Fraction& yFact, FASTBOOL bNoJustify=sal_False);
68 inline void ResizePoint(Point& rPnt, const Point& rRef, Fraction xFact, Fraction yFact);
69 void ResizePoly(Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
70 void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
71 void ResizePoly(PolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
72 void ResizeXPoly(XPolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact);
73
74 inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs);
75 SVX_DLLPUBLIC void RotatePoly(Polygon& rPoly, const Point& rRef, double sn, double cs);
76 void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs);
77 void RotatePoly(PolyPolygon& rPoly, const Point& rRef, double sn, double cs);
78 void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs);
79
80 // MirrorRect macht nur Sinn bei Spiegelachsen
81 // mit einem durch 45 Degree teilbaren Winkel!
82 void MirrorRect(Rectangle& rRect, const Point& rRef1, const Point& rRef2, FASTBOOL bNoJustify); // ni.
83 void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2);
84 void MirrorPoly(Polygon& rPoly, const Point& rRef1, const Point& rRef2);
85 void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2);
86 void MirrorPoly(PolyPolygon& rPoly, const Point& rRef1, const Point& rRef2);
87 void MirrorXPoly(XPolyPolygon& rPoly, const Point& rRef1, const Point& rRef2);
88
89 inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
90 SVX_DLLPUBLIC void ShearPoly(Polygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
91 void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
92 void ShearPoly(PolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
93 void ShearXPoly(XPolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear=sal_False);
94
95 // rPnt.X bzw rPnt.Y wird auf rCenter.X bzw. rCenter.Y gesetzt!
96 // anschliessend muss rPnt nur noch um rCenter gedreht werden.
97 // Der Rueckgabewinkel ist ausnahmsweise in Rad.
98 inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, FASTBOOL bVertical);
99 // Die folgenden Methoden behandeln einen Punkt eines XPolygons, wobei die
100 // benachbarten Kontrollpunkte des eigentlichen Punktes ggf. in pC1/pC2
101 // uebergeben werden. Ueber rSin/rCos wird gleichzeitig sin(nWink) und cos(nWink)
102 // zurueckgegeben.
103 // Der Rueckgabewinkel ist hier ebenfalls in Rad.
104 double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
105 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert);
106 double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
107 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert);
108 double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
109 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert,
110 const Rectangle rRefRect);
111
112 void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
113 void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
114 void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect);
115
116 void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
117 void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert);
118 void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect);
119
120 /**************************************************************************************************/
121 /* Inline */
122 /**************************************************************************************************/
123
ResizePoint(Point & rPnt,const Point & rRef,Fraction xFact,Fraction yFact)124 inline void ResizePoint(Point& rPnt, const Point& rRef, Fraction xFact, Fraction yFact)
125 {
126 if (xFact.GetDenominator()==0) xFact=Fraction(xFact.GetNumerator(),1); // DivZero abfangen
127 if (yFact.GetDenominator()==0) yFact=Fraction(yFact.GetNumerator(),1); // DivZero abfangen
128 rPnt.X()=rRef.X()+ Round(((double)(rPnt.X()-rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
129 rPnt.Y()=rRef.Y()+ Round(((double)(rPnt.Y()-rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
130 }
131
RotatePoint(Point & rPnt,const Point & rRef,double sn,double cs)132 inline void RotatePoint(Point& rPnt, const Point& rRef, double sn, double cs)
133 {
134 long dx=rPnt.X()-rRef.X();
135 long dy=rPnt.Y()-rRef.Y();
136 rPnt.X()=Round(rRef.X()+dx*cs+dy*sn);
137 rPnt.Y()=Round(rRef.Y()+dy*cs-dx*sn);
138 }
139
ShearPoint(Point & rPnt,const Point & rRef,double tn,FASTBOOL bVShear)140 inline void ShearPoint(Point& rPnt, const Point& rRef, double tn, FASTBOOL bVShear)
141 {
142 if (!bVShear) { // Horizontal
143 if (rPnt.Y()!=rRef.Y()) { // sonst nicht noetig
144 rPnt.X()-=Round((rPnt.Y()-rRef.Y())*tn);
145 }
146 } else { // ansonsten vertikal
147 if (rPnt.X()!=rRef.X()) { // sonst nicht noetig
148 rPnt.Y()-=Round((rPnt.X()-rRef.X())*tn);
149 }
150 }
151 }
152
GetCrookAngle(Point & rPnt,const Point & rCenter,const Point & rRad,FASTBOOL bVertical)153 inline double GetCrookAngle(Point& rPnt, const Point& rCenter, const Point& rRad, FASTBOOL bVertical)
154 {
155 double nWink;
156 if (bVertical) {
157 long dy=rPnt.Y()-rCenter.Y();
158 nWink=(double)dy/(double)rRad.Y();
159 rPnt.Y()=rCenter.Y();
160 } else {
161 long dx=rCenter.X()-rPnt.X();
162 nWink=(double)dx/(double)rRad.X();
163 rPnt.X()=rCenter.X();
164 }
165 return nWink;
166 }
167
168 /**************************************************************************************************/
169 /**************************************************************************************************/
170
171 // Y-Achse zeigt nach unten! Die Funktion negiert bei der
172 // Winkelberechnung die Y-Achse, sodass GetAngle(Point(0,-1))=90.00deg.
173 // GetAngle(Point(0,0)) liefert 0.
174 // Der Rueckgabewert liegt im Bereich -180.00..179.99 Degree und
175 // ist in 1/100 Degree angegeben.
176 SVX_DLLPUBLIC long GetAngle(const Point& rPnt);
177 long NormAngle180(long a); // Winkel normalisieren auf -180.00..179.99
178 SVX_DLLPUBLIC long NormAngle360(long a); // Winkel normalisieren auf 0.00..359.99
179 sal_uInt16 GetAngleSector(long nWink); // Sektor im kartesischen Koordinatensystem bestimmen
180 // Berechnet die Laenge von (0,0) via a^2 + b^2 = c^2
181 // Zur Vermeidung von Ueberlaeufen werden ggf. einige Stellen ignoriert.
182 long GetLen(const Point& rPnt);
183
184 /*
185 Transformation eines Rechtecks in ein Polygon unter ------------
186 Anwendung der Winkelparameter aus GeoStat. /1 2/
187 Referenzpunkt ist stets der Punkt 0, also die linke / /
188 obere Ecke des Ausgangsrects. / /
189 Bei der Berechnung des Polygons ist die Reihenfolge / /
190 (erst Shear, dann Rotation vorgegeben). / / \
191 / / |
192 A) Ausgangsrechteck aRect B) Nach Anwendung von Shear /0 3/ Rot|
193 +------------------+ -------------------- ------------ ------
194 |0 1| \0 1\ C) Nach Anwendung
195 | | \ \ von Rotate
196 | | | \ \
197 |3 2| | \3 2\
198 +------------------+ | --------------------
199 |Shr |
200 Bei Rueckkonvertierung des Polygons in ein Rect ist die Reihenfolge
201 zwangslaeufig umgekehrt:
202 - Berechnung des Drehwinkels: Winkel der Strecke 0-1 aus Abb. C) zum Horizont
203 - Rueckdrehung des geshearten Rects (man erhaelt Abb B))
204 - Bestimmung der Breite des Rects=Laenge der Strecke 0-1 aus Abb. B)
205 - Bestimmung der Hoehe des Rects=vertikaler Abstand zwischen den Punkten
206 0 und 3 aus Abb. B)
207 - Bestimmung des Shear-Winkels aus der Strecke 0-3 zur Senkrechten.
208 Es ist darauf zu achten, dass das Polygon bei einer zwischenzeitlichen
209 Transformation evtl. gespiegelt wurde (Mirror oder Resize mit neg. Faktor).
210 In diesem Fall muss zunaecht eine Normalisierung durch Vertauschung der
211 Punkte (z.B. 0 mit 3 und 1 mit 2) durchgefuehrt werden, damit der
212 Richtungssinn im Polygon wieder stimmig ist.
213 Hinweis: Positiver Shear-Winkel bedeutet Shear mit auf dem Bildschirm
214 sichtbarer positiver Kursivierung. Mathematisch waere dass eine negative
215 Kursivierung, da die Y-Achse auf dem Bildschirm von oben nach unten verlaeuft.
216 Drehwinkel: Positiv bedeutet auf dem Bildschirm sichtbare Linksdrehung.
217 */
218
219 class GeoStat { // Geometrischer Status fuer ein Rect
220 public:
221 long nDrehWink;
222 long nShearWink;
223 double nTan; // tan(nShearWink)
224 double nSin; // sin(nDrehWink)
225 double nCos; // cos(nDrehWink)
226 bool bMirrored; // Horizontal gespiegelt? (ni)
227 public:
GeoStat()228 GeoStat(): nDrehWink(0),nShearWink(0),nTan(0.0),nSin(0.0),nCos(1.0),bMirrored(false) {}
229 void RecalcSinCos();
230 void RecalcTan();
231 };
232
233 Polygon Rect2Poly(const Rectangle& rRect, const GeoStat& rGeo);
234 void Poly2Rect(const Polygon& rPol, Rectangle& rRect, GeoStat& rGeo);
235
236 SVX_DLLPUBLIC void OrthoDistance8(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho);
237 SVX_DLLPUBLIC void OrthoDistance4(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho);
238
239 // Multiplikation und anschliessende Division.
240 // Rechnung und Zwischenergebnis sind BigInt.
241 SVX_DLLPUBLIC long BigMulDiv(long nVal, long nMul, long nDiv);
242
243 // Fehlerbehaftetes Kuerzen einer Fraction.
244 // nDigits gibt an, wieviele signifikante Stellen in
245 // Zaehler/Nenner mindestens erhalten bleiben sollen.
246 void Kuerzen(Fraction& rF, unsigned nDigits);
247
248
249 class FrPair {
250 Fraction aX;
251 Fraction aY;
252 public:
FrPair()253 FrPair() : aX(0,1),aY(0,1) {}
FrPair(const Fraction & rBoth)254 FrPair(const Fraction& rBoth) : aX(rBoth),aY(rBoth) {}
FrPair(const Fraction & rX,const Fraction & rY)255 FrPair(const Fraction& rX, const Fraction& rY) : aX(rX),aY(rY) {}
FrPair(long nMul,long nDiv)256 FrPair(long nMul, long nDiv) : aX(nMul,nDiv),aY(nMul,nDiv) {}
FrPair(long xMul,long xDiv,long yMul,long yDiv)257 FrPair(long xMul, long xDiv, long yMul, long yDiv): aX(xMul,xDiv),aY(yMul,yDiv) {}
X() const258 const Fraction& X() const { return aX; }
Y() const259 const Fraction& Y() const { return aY; }
X()260 Fraction& X() { return aX; }
Y()261 Fraction& Y() { return aY; }
262 };
263
264 // Fuer die Umrechnung von Masseinheiten
265 SVX_DLLPUBLIC FrPair GetMapFactor(MapUnit eS, MapUnit eD);
266 FrPair GetMapFactor(MapUnit eS, FieldUnit eD);
267 FrPair GetMapFactor(FieldUnit eS, MapUnit eD);
268 FrPair GetMapFactor(FieldUnit eS, FieldUnit eD);
269
IsMetric(MapUnit eU)270 inline FASTBOOL IsMetric(MapUnit eU) {
271 return (eU==MAP_100TH_MM || eU==MAP_10TH_MM || eU==MAP_MM || eU==MAP_CM);
272 }
273
IsInch(MapUnit eU)274 inline FASTBOOL IsInch(MapUnit eU) {
275 return (eU==MAP_1000TH_INCH || eU==MAP_100TH_INCH || eU==MAP_10TH_INCH || eU==MAP_INCH ||
276 eU==MAP_POINT || eU==MAP_TWIP);
277 }
278
IsMetric(FieldUnit eU)279 inline FASTBOOL IsMetric(FieldUnit eU) {
280 return (eU==FUNIT_MM || eU==FUNIT_CM || eU==FUNIT_M || eU==FUNIT_KM || eU==FUNIT_100TH_MM);
281 }
282
IsInch(FieldUnit eU)283 inline FASTBOOL IsInch(FieldUnit eU) {
284 return (eU==FUNIT_TWIP || eU==FUNIT_POINT || eU==FUNIT_PICA ||
285 eU==FUNIT_INCH || eU==FUNIT_FOOT || eU==FUNIT_MILE);
286 }
287
288 class SVX_DLLPUBLIC SdrFormatter {
289 Fraction aScale;
290 long nMul_;
291 long nDiv_;
292 short nKomma_;
293 FASTBOOL bSrcFU;
294 FASTBOOL bDstFU;
295 FASTBOOL bDirty;
296 MapUnit eSrcMU;
297 MapUnit eDstMU;
298 FieldUnit eSrcFU;
299 FieldUnit eDstFU;
300 private:
301 SVX_DLLPRIVATE void Undirty();
ForceUndirty() const302 SVX_DLLPRIVATE void ForceUndirty() const { if (bDirty) ((SdrFormatter*)this)->Undirty(); }
303 public:
SdrFormatter(MapUnit eSrc,MapUnit eDst)304 SdrFormatter(MapUnit eSrc, MapUnit eDst) { eSrcMU=eSrc; bSrcFU=sal_False; eDstMU=eDst; bDstFU=sal_False; bDirty=sal_True; }
SdrFormatter(MapUnit eSrc,FieldUnit eDst)305 SdrFormatter(MapUnit eSrc, FieldUnit eDst) { eSrcMU=eSrc; bSrcFU=sal_False; eDstFU=eDst; bDstFU=sal_True; bDirty=sal_True; }
SdrFormatter(FieldUnit eSrc,MapUnit eDst)306 SdrFormatter(FieldUnit eSrc, MapUnit eDst) { eSrcFU=eSrc; bSrcFU=sal_True; eDstMU=eDst; bDstFU=sal_False; bDirty=sal_True; }
SdrFormatter(FieldUnit eSrc,FieldUnit eDst)307 SdrFormatter(FieldUnit eSrc, FieldUnit eDst) { eSrcFU=eSrc; bSrcFU=sal_True; eDstFU=eDst; bDstFU=sal_True; bDirty=sal_True; }
SetSourceUnit(MapUnit eSrc)308 void SetSourceUnit(MapUnit eSrc) { eSrcMU=eSrc; bSrcFU=sal_False; bDirty=sal_True; }
SetSourceUnit(FieldUnit eSrc)309 void SetSourceUnit(FieldUnit eSrc) { eSrcFU=eSrc; bSrcFU=sal_True; bDirty=sal_True; }
SetDestinationUnit(MapUnit eDst)310 void SetDestinationUnit(MapUnit eDst) { eDstMU=eDst; bDstFU=sal_False; bDirty=sal_True; }
SetDestinationUnit(FieldUnit eDst)311 void SetDestinationUnit(FieldUnit eDst) { eDstFU=eDst; bDstFU=sal_True; bDirty=sal_True; }
312 void TakeStr(long nVal, XubString& rStr) const;
313 static void TakeUnitStr(MapUnit eUnit, XubString& rStr);
314 static void TakeUnitStr(FieldUnit eUnit, XubString& rStr);
GetUnitStr(MapUnit eUnit)315 static XubString GetUnitStr(MapUnit eUnit) { XubString aStr; TakeUnitStr(eUnit,aStr); return aStr; }
GetUnitStr(FieldUnit eUnit)316 static XubString GetUnitStr(FieldUnit eUnit) { XubString aStr; TakeUnitStr(eUnit,aStr); return aStr; }
317 };
318
319 ////////////////////////////////////////////////////////////////////////////////////////////////////
320
321 #endif //_SVDTRANS_HXX
322
323