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