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