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