xref: /trunk/main/svx/inc/svx/svdtrans.hxx (revision 3334a7e6)
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