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