1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdtrans.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <svx/svdtrans.hxx>
36 #include <svx/xpoly.hxx>
38 #include <vcl/virdev.hxx>
39 #include <tools/bigint.hxx>
40 #include <tools/debug.hxx>
41 #include <svtools/syslocale.hxx>
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
45 void MoveXPoly(XPolygon
& rPoly
, const Size
& S
)
47 rPoly
.Move(S
.Width(),S
.Height());
50 void MoveXPoly(XPolyPolygon
& rPoly
, const Size
& S
)
52 rPoly
.Move(S
.Width(),S
.Height());
55 ////////////////////////////////////////////////////////////////////////////////////////////////////
57 void ResizeRect(Rectangle
& rRect
, const Point
& rRef
, const Fraction
& rxFact
, const Fraction
& ryFact
, FASTBOOL bNoJustify
)
59 Fraction
xFact(rxFact
);
60 Fraction
yFact(ryFact
);
61 //long nHgt=rRect.Bottom()-rRect.Top();
64 if (xFact
.GetDenominator()==0) {
65 long nWdt
=rRect
.Right()-rRect
.Left();
66 if (xFact
.GetNumerator()>=0) { // DivZero abfangen
67 xFact
=Fraction(xFact
.GetNumerator(),1);
68 if (nWdt
==0) rRect
.Right()++;
70 xFact
=Fraction(xFact
.GetNumerator(),-1);
71 if (nWdt
==0) rRect
.Left()--;
74 rRect
.Left() =rRef
.X()+Round(((double)(rRect
.Left() -rRef
.X())*xFact
.GetNumerator())/xFact
.GetDenominator());
75 rRect
.Right() =rRef
.X()+Round(((double)(rRect
.Right() -rRef
.X())*xFact
.GetNumerator())/xFact
.GetDenominator());
78 if (yFact
.GetDenominator()==0) {
79 long nHgt
=rRect
.Bottom()-rRect
.Top();
80 if (yFact
.GetNumerator()>=0) { // DivZero abfangen
81 yFact
=Fraction(yFact
.GetNumerator(),1);
82 if (nHgt
==0) rRect
.Bottom()++;
84 yFact
=Fraction(yFact
.GetNumerator(),-1);
85 if (nHgt
==0) rRect
.Top()--;
88 yFact
=Fraction(yFact
.GetNumerator(),1); // DivZero abfangen
90 rRect
.Top() =rRef
.Y()+Round(((double)(rRect
.Top() -rRef
.Y())*yFact
.GetNumerator())/yFact
.GetDenominator());
91 rRect
.Bottom()=rRef
.Y()+Round(((double)(rRect
.Bottom()-rRef
.Y())*yFact
.GetNumerator())/yFact
.GetDenominator());
93 if (!bNoJustify
) rRect
.Justify();
97 void ResizePoly(Polygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
99 USHORT nAnz
=rPoly
.GetSize();
100 for (USHORT i
=0; i
<nAnz
; i
++) {
101 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
105 void ResizeXPoly(XPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
107 USHORT nAnz
=rPoly
.GetPointCount();
108 for (USHORT i
=0; i
<nAnz
; i
++) {
109 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
113 void ResizePoly(PolyPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
115 USHORT nAnz
=rPoly
.Count();
116 for (USHORT i
=0; i
<nAnz
; i
++) {
117 ResizePoly(rPoly
[i
],rRef
,xFact
,yFact
);
121 void ResizeXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
123 USHORT nAnz
=rPoly
.Count();
124 for (USHORT i
=0; i
<nAnz
; i
++) {
125 ResizeXPoly(rPoly
[i
],rRef
,xFact
,yFact
);
129 ////////////////////////////////////////////////////////////////////////////////////////////////////
131 void RotatePoly(Polygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
133 USHORT nAnz
=rPoly
.GetSize();
134 for (USHORT i
=0; i
<nAnz
; i
++) {
135 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
139 void RotateXPoly(XPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
141 USHORT nAnz
=rPoly
.GetPointCount();
142 for (USHORT i
=0; i
<nAnz
; i
++) {
143 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
147 void RotatePoly(PolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
149 USHORT nAnz
=rPoly
.Count();
150 for (USHORT i
=0; i
<nAnz
; i
++) {
151 RotatePoly(rPoly
[i
],rRef
,sn
,cs
);
155 void RotateXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
157 USHORT nAnz
=rPoly
.Count();
158 for (USHORT i
=0; i
<nAnz
; i
++) {
159 RotateXPoly(rPoly
[i
],rRef
,sn
,cs
);
163 ////////////////////////////////////////////////////////////////////////////////////////////////////
165 void MirrorRect(Rectangle
& rRect
, const Point
& /*rRef1*/, const Point
& /*rRef2*/, FASTBOOL bNoJustify
)
167 // !!! fehlende Implementation !!!
168 if (!bNoJustify
) rRect
.Justify();
171 void MirrorPoint(Point
& rPnt
, const Point
& rRef1
, const Point
& rRef2
)
173 long mx
=rRef2
.X()-rRef1
.X();
174 long my
=rRef2
.Y()-rRef1
.Y();
175 if (mx
==0) { // Achse senkrecht
176 long dx
=rRef1
.X()-rPnt
.X();
178 } else if (my
==0) { // Achse waagerecht
179 long dy
=rRef1
.Y()-rPnt
.Y();
181 } else if (mx
==my
) { // Achse diagonal '\'
182 long dx1
=rPnt
.X()-rRef1
.X();
183 long dy1
=rPnt
.Y()-rRef1
.Y();
184 rPnt
.X()=rRef1
.X()+dy1
;
185 rPnt
.Y()=rRef1
.Y()+dx1
;
186 } else if (mx
==-my
) { // Achse diagonal '/'
187 long dx1
=rPnt
.X()-rRef1
.X();
188 long dy1
=rPnt
.Y()-rRef1
.Y();
189 rPnt
.X()=rRef1
.X()-dy1
;
190 rPnt
.Y()=rRef1
.Y()-dx1
;
191 } else { // beliebige Achse
192 // mal optimieren !!!
193 // Lot auf der Spiegelachse faellen oder so
194 long nRefWink
=GetAngle(rRef2
-rRef1
);
196 long nPntWink
=GetAngle(rPnt
);
197 long nWink
=2*(nRefWink
-nPntWink
);
198 double a
=nWink
*nPi180
;
201 RotatePoint(rPnt
,Point(),nSin
,nCos
);
206 void MirrorPoly(Polygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
208 USHORT nAnz
=rPoly
.GetSize();
209 for (USHORT i
=0; i
<nAnz
; i
++) {
210 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
214 void MirrorXPoly(XPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
216 USHORT nAnz
=rPoly
.GetPointCount();
217 for (USHORT i
=0; i
<nAnz
; i
++) {
218 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
222 void MirrorPoly(PolyPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
224 USHORT nAnz
=rPoly
.Count();
225 for (USHORT i
=0; i
<nAnz
; i
++) {
226 MirrorPoly(rPoly
[i
],rRef1
,rRef2
);
230 void MirrorXPoly(XPolyPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
232 USHORT nAnz
=rPoly
.Count();
233 for (USHORT i
=0; i
<nAnz
; i
++) {
234 MirrorXPoly(rPoly
[i
],rRef1
,rRef2
);
238 ////////////////////////////////////////////////////////////////////////////////////////////////////
240 void ShearPoly(Polygon
& rPoly
, const Point
& rRef
, double tn
, FASTBOOL bVShear
)
242 USHORT nAnz
=rPoly
.GetSize();
243 for (USHORT i
=0; i
<nAnz
; i
++) {
244 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
248 void ShearXPoly(XPolygon
& rPoly
, const Point
& rRef
, double tn
, FASTBOOL bVShear
)
250 USHORT nAnz
=rPoly
.GetPointCount();
251 for (USHORT i
=0; i
<nAnz
; i
++) {
252 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
256 void ShearPoly(PolyPolygon
& rPoly
, const Point
& rRef
, double tn
, FASTBOOL bVShear
)
258 USHORT nAnz
=rPoly
.Count();
259 for (USHORT i
=0; i
<nAnz
; i
++) {
260 ShearPoly(rPoly
[i
],rRef
,tn
,bVShear
);
264 void ShearXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double tn
, FASTBOOL bVShear
)
266 USHORT nAnz
=rPoly
.Count();
267 for (USHORT i
=0; i
<nAnz
; i
++) {
268 ShearXPoly(rPoly
[i
],rRef
,tn
,bVShear
);
272 ////////////////////////////////////////////////////////////////////////////////////////////////////
274 // @@@@ @@@@@ @@@@ @@@@ @@ @@
275 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
276 // @@ @@ @@ @@ @@ @@ @@ @@ @@
277 // @@ @@@@@ @@ @@ @@ @@ @@@@
278 // @@ @@ @@ @@ @@ @@ @@ @@ @@
279 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
280 // @@@@ @@ @@ @@@@ @@@@ @@ @@
282 ////////////////////////////////////////////////////////////////////////////////////////////////////
284 double CrookRotateXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
285 const Point
& rRad
, double& rSin
, double& rCos
, FASTBOOL bVert
)
287 FASTBOOL bC1
=pC1
!=NULL
;
288 FASTBOOL bC2
=pC2
!=NULL
;
293 double nWink
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
294 double sn
=sin(nWink
);
295 double cs
=cos(nWink
);
296 RotatePoint(rPnt
,rCenter
,sn
,cs
);
299 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
301 // Resize, entsprechend der Entfernung vom Zentrum
302 pC1
->Y()=Round(((double)pC1
->Y()) /rRad
.X()*(cx
-pC1
->X()));
305 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
307 // Resize, entsprechend der Entfernung vom Zentrum
308 long nPntRad
=cy
-pC1
->Y();
309 double nFact
=(double)nPntRad
/(double)rRad
.Y();
310 pC1
->X()=Round((double)pC1
->X()*nFact
);
313 RotatePoint(*pC1
,rCenter
,sn
,cs
);
317 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
319 // Resize, entsprechend der Entfernung vom Zentrum
320 pC2
->Y()=Round(((double)pC2
->Y()) /rRad
.X()*(rCenter
.X()-pC2
->X()));
323 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
325 // Resize, entsprechend der Entfernung vom Zentrum
326 long nPntRad
=rCenter
.Y()-pC2
->Y();
327 double nFact
=(double)nPntRad
/(double)rRad
.Y();
328 pC2
->X()=Round((double)pC2
->X()*nFact
);
331 RotatePoint(*pC2
,rCenter
,sn
,cs
);
338 double CrookSlantXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
339 const Point
& rRad
, double& rSin
, double& rCos
, FASTBOOL bVert
)
341 FASTBOOL bC1
=pC1
!=NULL
;
342 FASTBOOL bC2
=pC2
!=NULL
;
349 long nStart
=rCenter
.X()-rRad
.X();
353 dxC1
=pC1
->X()-nStart
;
357 dxC2
=pC2
->X()-nStart
;
361 long nStart
=rCenter
.Y()-rRad
.Y();
365 dyC1
=pC1
->Y()-nStart
;
369 dyC2
=pC2
->Y()-nStart
;
373 double nWink
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
374 double sn
=sin(nWink
);
375 double cs
=cos(nWink
);
376 RotatePoint(rPnt
,rCenter
,sn
,cs
);
377 if (bC1
) { if (bVert
) pC1
->Y()-=y0
-rCenter
.Y(); else pC1
->X()-=x0
-rCenter
.X(); RotatePoint(*pC1
,rCenter
,sn
,cs
); }
378 if (bC2
) { if (bVert
) pC2
->Y()-=y0
-rCenter
.Y(); else pC2
->X()-=x0
-rCenter
.X(); RotatePoint(*pC2
,rCenter
,sn
,cs
); }
381 if (bC1
) pC1
->X()+=dxC1
;
382 if (bC2
) pC2
->X()+=dxC2
;
385 if (bC1
) pC1
->Y()+=dyC1
;
386 if (bC2
) pC2
->Y()+=dyC2
;
393 double CrookStretchXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
394 const Point
& rRad
, double& rSin
, double& rCos
, FASTBOOL bVert
,
395 const Rectangle rRefRect
)
397 //FASTBOOL bC1=pC1!=NULL;
398 //FASTBOOL bC2=pC2!=NULL;
401 CrookSlantXPoint(rPnt
,pC1
,pC2
,rCenter
,rRad
,rSin
,rCos
,bVert
);
404 //long nBase=rCenter.Y()-rRad.Y();
405 long nTop
=rRefRect
.Top();
406 long nBtm
=rRefRect
.Bottom();
409 //FASTBOOL bOben=rRad.Y()<0;
410 double a
=((double)(y0
-nTop
))/nHgt
;
412 rPnt
.Y()=y0
+Round(a
);
416 ////////////////////////////////////////////////////////////////////////////////////////////////////
418 void CrookRotatePoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, FASTBOOL bVert
)
421 USHORT nPointAnz
=rPoly
.GetPointCount();
423 while (i
<nPointAnz
) {
424 Point
* pPnt
=&rPoly
[i
];
427 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // Kontrollpunkt links
433 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // Kontrollpunkt rechts
437 CrookRotateXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
441 void CrookSlantPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, FASTBOOL bVert
)
444 USHORT nPointAnz
=rPoly
.GetPointCount();
446 while (i
<nPointAnz
) {
447 Point
* pPnt
=&rPoly
[i
];
450 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // Kontrollpunkt links
456 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // Kontrollpunkt rechts
460 CrookSlantXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
464 void CrookStretchPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, FASTBOOL bVert
, const Rectangle rRefRect
)
467 USHORT nPointAnz
=rPoly
.GetPointCount();
469 while (i
<nPointAnz
) {
470 Point
* pPnt
=&rPoly
[i
];
473 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // Kontrollpunkt links
479 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // Kontrollpunkt rechts
483 CrookStretchXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
,rRefRect
);
487 ////////////////////////////////////////////////////////////////////////////////////////////////////
489 void CrookRotatePoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, FASTBOOL bVert
)
491 USHORT nPolyAnz
=rPoly
.Count();
492 for (USHORT nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
493 CrookRotatePoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
497 void CrookSlantPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, FASTBOOL bVert
)
499 USHORT nPolyAnz
=rPoly
.Count();
500 for (USHORT nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
501 CrookSlantPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
505 void CrookStretchPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, FASTBOOL bVert
, const Rectangle rRefRect
)
507 USHORT nPolyAnz
=rPoly
.Count();
508 for (USHORT nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
509 CrookStretchPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
,rRefRect
);
513 ////////////////////////////////////////////////////////////////////////////////////////////////////
515 long GetAngle(const Point
& rPnt
)
519 if (rPnt
.X()<0) a
=-18000;
520 } else if (rPnt
.X()==0) {
521 if (rPnt
.Y()>0) a
=-9000;
524 a
=Round((atan2((double)-rPnt
.Y(),(double)rPnt
.X())/nPi180
));
529 long NormAngle180(long a
)
531 while (a
<18000) a
+=36000;
532 while (a
>=18000) a
-=36000;
536 long NormAngle360(long a
)
538 while (a
<0) a
+=36000;
539 while (a
>=36000) a
-=36000;
543 USHORT
GetAngleSector(long nWink
)
545 while (nWink
<0) nWink
+=36000;
546 while (nWink
>=36000) nWink
-=36000;
547 if (nWink
< 9000) return 0;
548 if (nWink
<18000) return 1;
549 if (nWink
<27000) return 2;
553 long GetLen(const Point
& rPnt
)
555 long x
=Abs(rPnt
.X());
556 long y
=Abs(rPnt
.Y());
557 if (x
+y
<0x8000) { // weil 7FFF * 7FFF * 2 = 7FFE0002
561 x
=Round(sqrt((double)x
));
571 return 0x7FFFFFFF; // Ueberlauf, mehr is nich!
578 ////////////////////////////////////////////////////////////////////////////////////////////////////
580 void GeoStat::RecalcSinCos()
586 double a
=nDrehWink
*nPi180
;
592 void GeoStat::RecalcTan()
597 double a
=nShearWink
*nPi180
;
602 ////////////////////////////////////////////////////////////////////////////////////////////////////
604 Polygon
Rect2Poly(const Rectangle
& rRect
, const GeoStat
& rGeo
)
607 aPol
[0]=rRect
.TopLeft();
608 aPol
[1]=rRect
.TopRight();
609 aPol
[2]=rRect
.BottomRight();
610 aPol
[3]=rRect
.BottomLeft();
611 aPol
[4]=rRect
.TopLeft();
612 if (rGeo
.nShearWink
!=0) ShearPoly(aPol
,rRect
.TopLeft(),rGeo
.nTan
);
613 if (rGeo
.nDrehWink
!=0) RotatePoly(aPol
,rRect
.TopLeft(),rGeo
.nSin
,rGeo
.nCos
);
617 void Poly2Rect(const Polygon
& rPol
, Rectangle
& rRect
, GeoStat
& rGeo
)
619 rGeo
.nDrehWink
=GetAngle(rPol
[1]-rPol
[0]);
620 rGeo
.nDrehWink
=NormAngle360(rGeo
.nDrehWink
);
621 // Drehung ist damit im Kasten
624 Point
aPt1(rPol
[1]-rPol
[0]);
625 if (rGeo
.nDrehWink
!=0) RotatePoint(aPt1
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin fuer Rueckdrehung
629 Point
aPt3(rPol
[3]-rPol
[0]);
630 if (rGeo
.nDrehWink
!=0) RotatePoint(aPt3
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin fuer Rueckdrehung
635 // #i74358# the axes are not orthogonal, so for getting the correct height,
636 // calculate the length of aPt3
638 // #i74358# this change was wrong, in the field of the old geometry stuff
639 // it is not an error. The new height always is the same as before; shear
640 // does not change object height at all. This is different from the interactions,
641 // but obviously wanted in the old versions.
643 // nHgt = static_cast< long >(sqrt(static_cast< double >(aPt3.X() * aPt3.X() + aPt3.Y() * aPt3.Y())));
646 long nShW
=GetAngle(aPt3
);
647 nShW
-=27000; // ShearWink wird zur Senkrechten gemessen
648 nShW
=-nShW
; // Negieren, denn '+' ist Rechtskursivierung
650 FASTBOOL bMirr
=aPt3
.Y()<0;
651 if (bMirr
) { // "Punktetausch" bei Spiegelung
656 nShW
=NormAngle180(nShW
);
657 if (nShW
<-9000 || nShW
>9000) {
658 nShW
=NormAngle180(nShW
+18000);
660 if (nShW
<-SDRMAXSHEAR
) nShW
=-SDRMAXSHEAR
; // ShearWinkel begrenzen auf +/- 89.00 deg
661 if (nShW
>SDRMAXSHEAR
) nShW
=SDRMAXSHEAR
;
662 rGeo
.nShearWink
=nShW
;
667 rRect
=Rectangle(aPt0
,aRU
);
670 ////////////////////////////////////////////////////////////////////////////////////////////////////
672 void OrthoDistance8(const Point
& rPt0
, Point
& rPt
, FASTBOOL bBigOrtho
)
674 long dx
=rPt
.X()-rPt0
.X();
675 long dy
=rPt
.Y()-rPt0
.Y();
678 if (dx
==0 || dy
==0 || dxa
==dya
) return;
679 if (dxa
>=dya
*2) { rPt
.Y()=rPt0
.Y(); return; }
680 if (dya
>=dxa
*2) { rPt
.X()=rPt0
.X(); return; }
681 if ((dxa
<dya
) != bBigOrtho
) {
682 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
684 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
688 void OrthoDistance4(const Point
& rPt0
, Point
& rPt
, FASTBOOL bBigOrtho
)
690 long dx
=rPt
.X()-rPt0
.X();
691 long dy
=rPt
.Y()-rPt0
.Y();
694 if ((dxa
<dya
) != bBigOrtho
) {
695 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
697 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
701 ////////////////////////////////////////////////////////////////////////////////////////////////////
703 long BigMulDiv(long nVal
, long nMul
, long nDiv
)
707 if (aVal
.IsNeg()!=(nDiv
<0)) {
708 aVal
-=nDiv
/2; // fuer korrektes Runden
710 aVal
+=nDiv
/2; // fuer korrektes Runden
720 void Kuerzen(Fraction
& rF
, unsigned nDigits
)
722 INT32 nMul
=rF
.GetNumerator();
723 INT32 nDiv
=rF
.GetDenominator();
725 if (nMul
<0) { nMul
=-nMul
; bNeg
=!bNeg
; }
726 if (nDiv
<0) { nDiv
=-nDiv
; bNeg
=!bNeg
; }
727 if (nMul
==0 || nDiv
==0) return;
729 a
=UINT32(nMul
); unsigned nMulZ
=0; // Fuehrende Nullen zaehlen
730 while (a
<0x00800000) { nMulZ
+=8; a
<<=8; }
731 while (a
<0x80000000) { nMulZ
++; a
<<=1; }
732 a
=UINT32(nDiv
); unsigned nDivZ
=0; // Fuehrende Nullen zaehlen
733 while (a
<0x00800000) { nDivZ
+=8; a
<<=8; }
734 while (a
<0x80000000) { nDivZ
++; a
<<=1; }
735 // Anzahl der verwendeten Digits bestimmen
736 int nMulDigits
=32-nMulZ
;
737 int nDivDigits
=32-nDivZ
;
738 // Nun bestimmen, wieviele Stellen hinten weg koennen
739 int nMulWeg
=nMulDigits
-nDigits
; if (nMulWeg
<0) nMulWeg
=0;
740 int nDivWeg
=nDivDigits
-nDigits
; if (nDivWeg
<0) nDivWeg
=0;
741 int nWeg
=Min(nMulWeg
,nDivWeg
);
744 if (nMul
==0 || nDiv
==0) {
745 DBG_WARNING("Oups, beim kuerzen einer Fraction hat sich Joe verrechnet.");
748 if (bNeg
) nMul
=-nMul
;
749 rF
=Fraction(nMul
,nDiv
);
752 ////////////////////////////////////////////////////////////////////////////////////////////////////
753 // Wieviele eU-Einheiten passen in einen mm bzw. Inch?
754 // Oder wie gross ist ein eU in mm bzw. Inch, und davon der Kehrwert
756 FrPair
GetInchOrMM(MapUnit eU
)
759 case MAP_1000TH_INCH
: return FrPair(1000,1);
760 case MAP_100TH_INCH
: return FrPair( 100,1);
761 case MAP_10TH_INCH
: return FrPair( 10,1);
762 case MAP_INCH
: return FrPair( 1,1);
763 case MAP_POINT
: return FrPair( 72,1);
764 case MAP_TWIP
: return FrPair(1440,1);
765 case MAP_100TH_MM
: return FrPair( 100,1);
766 case MAP_10TH_MM
: return FrPair( 10,1);
767 case MAP_MM
: return FrPair( 1,1);
768 case MAP_CM
: return FrPair( 1,10);
771 aVD
.SetMapMode(MapMode(MAP_100TH_MM
));
772 Point
aP(aVD
.PixelToLogic(Point(64,64))); // 64 Pixel fuer bessere Genauigkeit
773 return FrPair(6400,aP
.X(),6400,aP
.Y());
775 case MAP_APPFONT
: case MAP_SYSFONT
: {
777 aVD
.SetMapMode(MapMode(eU
));
778 Point
aP(aVD
.LogicToPixel(Point(32,32))); // 32 Einheiten fuer bessere Genauigkeit
779 aVD
.SetMapMode(MapMode(MAP_100TH_MM
));
780 aP
=aVD
.PixelToLogic(aP
);
781 return FrPair(3200,aP
.X(),3200,aP
.Y());
785 return Fraction(1,1);
788 FrPair
GetInchOrMM(FieldUnit eU
)
791 case FUNIT_INCH
: return FrPair( 1,1);
792 case FUNIT_POINT
: return FrPair( 72,1);
793 case FUNIT_TWIP
: return FrPair(1440,1);
794 case FUNIT_100TH_MM
: return FrPair( 100,1);
795 case FUNIT_MM
: return FrPair( 1,1);
796 case FUNIT_CM
: return FrPair( 1,10);
797 case FUNIT_M
: return FrPair( 1,1000);
798 case FUNIT_KM
: return FrPair( 1,1000000);
799 case FUNIT_PICA
: return FrPair( 6,1);
800 case FUNIT_FOOT
: return FrPair( 1,12);
801 case FUNIT_MILE
: return FrPair( 1,63360);
804 return Fraction(1,1);
807 // Den Faktor berechnen, der anzuwenden ist um n Einheiten von eS nach
808 // eD umzurechnen. Z.B. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
810 FrPair
GetMapFactor(MapUnit eS
, MapUnit eD
)
812 if (eS
==eD
) return FrPair(1,1,1,1);
813 FrPair
aS(GetInchOrMM(eS
));
814 FrPair
aD(GetInchOrMM(eD
));
815 FASTBOOL bSInch
=IsInch(eS
);
816 FASTBOOL bDInch
=IsInch(eD
);
817 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
818 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
819 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
823 FrPair
GetMapFactor(MapUnit eS
, FieldUnit eD
)
825 FrPair
aS(GetInchOrMM(eS
));
826 FrPair
aD(GetInchOrMM(eD
));
827 FASTBOOL bSInch
=IsInch(eS
);
828 FASTBOOL bDInch
=IsInch(eD
);
829 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
830 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
831 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
835 FrPair
GetMapFactor(FieldUnit eS
, MapUnit eD
)
837 FrPair
aS(GetInchOrMM(eS
));
838 FrPair
aD(GetInchOrMM(eD
));
839 FASTBOOL bSInch
=IsInch(eS
);
840 FASTBOOL bDInch
=IsInch(eD
);
841 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
842 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
843 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
847 FrPair
GetMapFactor(FieldUnit eS
, FieldUnit eD
)
849 if (eS
==eD
) return FrPair(1,1,1,1);
850 FrPair
aS(GetInchOrMM(eS
));
851 FrPair
aD(GetInchOrMM(eD
));
852 FASTBOOL bSInch
=IsInch(eS
);
853 FASTBOOL bDInch
=IsInch(eD
);
854 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
855 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
856 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
860 ////////////////////////////////////////////////////////////////////////////////////////////////////
862 // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm
863 // 1 furlong = 10 chains = 7.920" = 201.168,0mm
864 // 1 chain = 4 poles = 792" = 20.116,8mm
865 // 1 pole = 5 1/2 yd = 198" = 5.029,2mm
866 // 1 yd = 3 ft = 36" = 914,4mm
867 // 1 ft = 12 " = 1" = 304,8mm
869 void GetMeterOrInch(MapUnit eMU
, short& rnKomma
, long& rnMul
, long& rnDiv
, FASTBOOL
& rbMetr
, FASTBOOL
& rbInch
)
873 FASTBOOL bMetr
=FALSE
,bInch
=FALSE
;
876 case MAP_100TH_MM
: bMetr
=TRUE
; nKomma
=5; break;
877 case MAP_10TH_MM
: bMetr
=TRUE
; nKomma
=4; break;
878 case MAP_MM
: bMetr
=TRUE
; nKomma
=3; break;
879 case MAP_CM
: bMetr
=TRUE
; nKomma
=2; break;
881 case MAP_1000TH_INCH
: bInch
=TRUE
; nKomma
=3; break;
882 case MAP_100TH_INCH
: bInch
=TRUE
; nKomma
=2; break;
883 case MAP_10TH_INCH
: bInch
=TRUE
; nKomma
=1; break;
884 case MAP_INCH
: bInch
=TRUE
; nKomma
=0; break;
885 case MAP_POINT
: bInch
=TRUE
; rnDiv
=72; break; // 1Pt = 1/72"
886 case MAP_TWIP
: bInch
=TRUE
; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
888 case MAP_PIXEL
: break;
889 case MAP_SYSFONT
: break;
890 case MAP_APPFONT
: break;
891 case MAP_RELATIVE
: break;
899 void GetMeterOrInch(FieldUnit eFU
, short& rnKomma
, long& rnMul
, long& rnDiv
, FASTBOOL
& rbMetr
, FASTBOOL
& rbInch
)
903 FASTBOOL bMetr
=FALSE
,bInch
=FALSE
;
905 case FUNIT_NONE
: break;
907 case FUNIT_100TH_MM
: bMetr
=TRUE
; nKomma
=5; break;
908 case FUNIT_MM
: bMetr
=TRUE
; nKomma
=3; break;
909 case FUNIT_CM
: bMetr
=TRUE
; nKomma
=2; break;
910 case FUNIT_M
: bMetr
=TRUE
; nKomma
=0; break;
911 case FUNIT_KM
: bMetr
=TRUE
; nKomma
=-3; break;
913 case FUNIT_TWIP
: bInch
=TRUE
; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
914 case FUNIT_POINT
: bInch
=TRUE
; rnDiv
=72; break; // 1Pt = 1/72"
915 case FUNIT_PICA
: bInch
=TRUE
; rnDiv
=6; break; // 1Pica = 1/6" ?
916 case FUNIT_INCH
: bInch
=TRUE
; break; // 1" = 1"
917 case FUNIT_FOOT
: bInch
=TRUE
; rnMul
=12; break; // 1Ft = 12"
918 case FUNIT_MILE
: bInch
=TRUE
; rnMul
=6336; nKomma
=-1; break; // 1mile = 63360"
920 case FUNIT_CUSTOM
: break;
921 case FUNIT_PERCENT
: nKomma
=2; break;
928 void SdrFormatter::Undirty()
930 if (aScale
.GetNumerator()==0 || aScale
.GetDenominator()==0) aScale
=Fraction(1,1);
931 FASTBOOL bSrcMetr
,bSrcInch
,bDstMetr
,bDstInch
;
932 long nMul1
,nDiv1
,nMul2
,nDiv2
;
933 short nKomma1
,nKomma2
;
934 // Zunaechst normalisieren auf m bzw. "
936 GetMeterOrInch(eSrcMU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
938 GetMeterOrInch(eSrcFU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
941 GetMeterOrInch(eDstMU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
943 GetMeterOrInch(eDstFU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
947 nKomma1
=nKomma1
-nKomma2
;
949 if (bSrcInch
&& bDstMetr
) {
953 if (bSrcMetr
&& bDstInch
) {
958 // Temporaere Fraction zum Kuerzen
959 Fraction
aTempFract(nMul1
,nDiv1
);
960 nMul1
=aTempFract
.GetNumerator();
961 nDiv1
=aTempFract
.GetDenominator();
970 void SdrFormatter::TakeStr(long nVal
, XubString
& rStr
) const
972 sal_Unicode
aNullCode('0');
981 // Hier fallen trotzdem evtl. Nachkommastellen weg, wg. MulDiv statt Real
983 SvtSysLocale aSysLoc
;
984 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
988 sal_Int16
nK(nKomma_
);
1007 nVal
= BigMulDiv(nVal
, nMul_
, nDiv_
);
1009 aStr
= UniString::CreateFromInt32(nVal
);
1011 if(nK
> 0 && aStr
.Len() <= nK
)
1013 // Komma erforderlich
1014 sal_Int16
nAnz(nK
- aStr
.Len());
1016 if(nAnz
>= 0 && rLoc
.isNumLeadingZero())
1019 for(xub_StrLen i
=0; i
<nAnz
; i
++)
1020 aStr
.Insert(aNullCode
, 0);
1022 // zuviele Nachkommastellen abhacken
1023 xub_StrLen
nNumDigits(rLoc
.getNumDigits());
1024 xub_StrLen
nWeg(nK
- nNumDigits
);
1028 // hier muesste eigentlich noch gerundet werden!
1029 aStr
.Erase(aStr
.Len() - nWeg
);
1034 // Vorkommastellen fuer spaeter merken
1035 xub_StrLen
nVorKomma(aStr
.Len() - nK
);
1039 // KommaChar einfuegen
1040 // erstmal trailing Zeros abhacken
1041 while(nK
> 0 && aStr
.GetChar(aStr
.Len() - 1) == aNullCode
)
1043 aStr
.Erase(aStr
.Len() - 1);
1049 // na, noch Nachkommastellen da?
1050 sal_Unicode
cDec(rLoc
.getNumDecimalSep().GetChar(0));
1051 aStr
.Insert(cDec
, nVorKomma
);
1055 // ggf. Trennpunkte bei jedem Tausender einfuegen
1058 String
aThoSep( rLoc
.getNumThousandSep() );
1059 if ( aThoSep
.Len() > 0 )
1061 sal_Unicode
cTho( aThoSep
.GetChar(0) );
1062 sal_Int32
i(nVorKomma
- 3);
1066 rStr
.Insert(cTho
, (xub_StrLen
)i
);
1075 if(bNeg
&& (aStr
.Len() > 1 || aStr
.GetChar(0) != aNullCode
))
1077 rStr
.Insert(sal_Unicode('-'), 0);
1083 void SdrFormatter::TakeUnitStr(MapUnit eUnit
, XubString
& rStr
)
1090 sal_Char aText
[] = "/100mm";
1091 rStr
= UniString(aText
, sizeof(aText
-1));
1096 sal_Char aText
[] = "/10mm";
1097 rStr
= UniString(aText
, sizeof(aText
-1));
1102 sal_Char aText
[] = "mm";
1103 rStr
= UniString(aText
, sizeof(aText
-1));
1108 sal_Char aText
[] = "cm";
1109 rStr
= UniString(aText
, sizeof(aText
-1));
1114 case MAP_1000TH_INCH
:
1116 sal_Char aText
[] = "/1000\"";
1117 rStr
= UniString(aText
, sizeof(aText
-1));
1120 case MAP_100TH_INCH
:
1122 sal_Char aText
[] = "/100\"";
1123 rStr
= UniString(aText
, sizeof(aText
-1));
1126 case MAP_10TH_INCH
:
1128 sal_Char aText
[] = "/10\"";
1129 rStr
= UniString(aText
, sizeof(aText
-1));
1135 rStr
+= sal_Unicode('"');
1140 sal_Char aText
[] = "pt";
1141 rStr
= UniString(aText
, sizeof(aText
-1));
1146 sal_Char aText
[] = "twip";
1147 rStr
= UniString(aText
, sizeof(aText
-1));
1154 sal_Char aText
[] = "pixel";
1155 rStr
= UniString(aText
, sizeof(aText
-1));
1160 sal_Char aText
[] = "sysfont";
1161 rStr
= UniString(aText
, sizeof(aText
-1));
1166 sal_Char aText
[] = "appfont";
1167 rStr
= UniString(aText
, sizeof(aText
-1));
1173 rStr
+= sal_Unicode('%');
1180 void SdrFormatter::TakeUnitStr(FieldUnit eUnit
, XubString
& rStr
)
1193 case FUNIT_100TH_MM
:
1195 sal_Char aText
[] = "/100mm";
1196 rStr
= UniString(aText
, sizeof(aText
-1));
1201 sal_Char aText
[] = "mm";
1202 rStr
= UniString(aText
, sizeof(aText
-1));
1207 sal_Char aText
[] = "cm";
1208 rStr
= UniString(aText
, sizeof(aText
-1));
1214 rStr
+= sal_Unicode('m');
1219 sal_Char aText
[] = "km";
1220 rStr
= UniString(aText
, sizeof(aText
-1));
1227 sal_Char aText
[] = "twip";
1228 rStr
= UniString(aText
, sizeof(aText
-1));
1233 sal_Char aText
[] = "pt";
1234 rStr
= UniString(aText
, sizeof(aText
-1));
1239 sal_Char aText
[] = "pica";
1240 rStr
= UniString(aText
, sizeof(aText
-1));
1246 rStr
+= sal_Unicode('"');
1251 sal_Char aText
[] = "ft";
1252 rStr
= UniString(aText
, sizeof(aText
-1));
1257 sal_Char aText
[] = "mile(s)";
1258 rStr
= UniString(aText
, sizeof(aText
-1));
1266 rStr
+= sal_Unicode('%');
1272 ////////////////////////////////////////////////////////////////////////////////////////////////////