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