1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
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.
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).
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.
27 ************************************************************************/
30 #include <svx/svdtrans.hxx>
32 #include <svx/xpoly.hxx>
34 #include <vcl/virdev.hxx>
35 #include <tools/bigint.hxx>
36 #include <tools/debug.hxx>
37 #include <unotools/syslocale.hxx>
39 void MoveXPoly(XPolygon
& rPoly
, const Size
& S
)
41 rPoly
.Move(S
.Width(),S
.Height());
44 void ResizeRect(Rectangle
& rRect
, const Point
& rRef
, const Fraction
& rxFact
, const Fraction
& ryFact
, bool bNoJustify
)
46 Fraction
xFact(rxFact
);
47 Fraction
yFact(ryFact
);
50 if (xFact
.GetDenominator()==0) {
51 long nWdt
=rRect
.Right()-rRect
.Left();
52 if (xFact
.GetNumerator()>=0) { // catch divisions by zero
53 xFact
=Fraction(xFact
.GetNumerator(),1);
54 if (nWdt
==0) rRect
.Right()++;
56 xFact
=Fraction(xFact
.GetNumerator(),-1);
57 if (nWdt
==0) rRect
.Left()--;
60 rRect
.Left() =rRef
.X()+Round(((double)(rRect
.Left() -rRef
.X())*xFact
.GetNumerator())/xFact
.GetDenominator());
61 rRect
.Right() =rRef
.X()+Round(((double)(rRect
.Right() -rRef
.X())*xFact
.GetNumerator())/xFact
.GetDenominator());
64 if (yFact
.GetDenominator()==0) {
65 long nHgt
=rRect
.Bottom()-rRect
.Top();
66 if (yFact
.GetNumerator()>=0) { // catch divisions by zero
67 yFact
=Fraction(yFact
.GetNumerator(),1);
68 if (nHgt
==0) rRect
.Bottom()++;
70 yFact
=Fraction(yFact
.GetNumerator(),-1);
71 if (nHgt
==0) rRect
.Top()--;
74 yFact
=Fraction(yFact
.GetNumerator(),1); // catch divisions by zero
76 rRect
.Top() =rRef
.Y()+Round(((double)(rRect
.Top() -rRef
.Y())*yFact
.GetNumerator())/yFact
.GetDenominator());
77 rRect
.Bottom()=rRef
.Y()+Round(((double)(rRect
.Bottom()-rRef
.Y())*yFact
.GetNumerator())/yFact
.GetDenominator());
79 if (!bNoJustify
) rRect
.Justify();
83 void ResizePoly(Polygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
85 sal_uInt16 nAnz
=rPoly
.GetSize();
86 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
87 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
91 void ResizeXPoly(XPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
93 sal_uInt16 nAnz
=rPoly
.GetPointCount();
94 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
95 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
99 void RotatePoly(Polygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
101 sal_uInt16 nAnz
=rPoly
.GetSize();
102 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
103 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
107 void RotateXPoly(XPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
109 sal_uInt16 nAnz
=rPoly
.GetPointCount();
110 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
111 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
115 void RotateXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
117 sal_uInt16 nAnz
=rPoly
.Count();
118 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
119 RotateXPoly(rPoly
[i
],rRef
,sn
,cs
);
123 void MirrorPoint(Point
& rPnt
, const Point
& rRef1
, const Point
& rRef2
)
125 long mx
=rRef2
.X()-rRef1
.X();
126 long my
=rRef2
.Y()-rRef1
.Y();
127 if (mx
==0) { // vertical axis
128 long dx
=rRef1
.X()-rPnt
.X();
130 } else if (my
==0) { // horizontal axis
131 long dy
=rRef1
.Y()-rPnt
.Y();
133 } else if (mx
==my
) { // diagonal axis '\'
134 long dx1
=rPnt
.X()-rRef1
.X();
135 long dy1
=rPnt
.Y()-rRef1
.Y();
136 rPnt
.X()=rRef1
.X()+dy1
;
137 rPnt
.Y()=rRef1
.Y()+dx1
;
138 } else if (mx
==-my
) { // diagonal axis '/'
139 long dx1
=rPnt
.X()-rRef1
.X();
140 long dy1
=rPnt
.Y()-rRef1
.Y();
141 rPnt
.X()=rRef1
.X()-dy1
;
142 rPnt
.Y()=rRef1
.Y()-dx1
;
143 } else { // arbitrary axis
144 // TODO: Optimize this! Raise perpendicular on the mirroring axis..?
145 long nRefWink
=GetAngle(rRef2
-rRef1
);
147 long nPntWink
=GetAngle(rPnt
);
148 long nWink
=2*(nRefWink
-nPntWink
);
149 double a
=nWink
*nPi180
;
152 RotatePoint(rPnt
,Point(),nSin
,nCos
);
157 void MirrorPoly(Polygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
159 sal_uInt16 nAnz
=rPoly
.GetSize();
160 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
161 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
165 void MirrorXPoly(XPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
167 sal_uInt16 nAnz
=rPoly
.GetPointCount();
168 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
169 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
173 void ShearPoly(Polygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
)
175 sal_uInt16 nAnz
=rPoly
.GetSize();
176 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
177 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
181 void ShearXPoly(XPolygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
)
183 sal_uInt16 nAnz
=rPoly
.GetPointCount();
184 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
185 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
189 double CrookRotateXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
190 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
)
198 double nWink
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
199 double sn
=sin(nWink
);
200 double cs
=cos(nWink
);
201 RotatePoint(rPnt
,rCenter
,sn
,cs
);
204 // move into the direction of the center, as a basic position for the rotation
206 // resize, account for the distance from the center
207 pC1
->Y()=Round(((double)pC1
->Y()) /rRad
.X()*(cx
-pC1
->X()));
210 // move into the direction of the center, as a basic position for the rotation
212 // resize, account for the distance from the center
213 long nPntRad
=cy
-pC1
->Y();
214 double nFact
=(double)nPntRad
/(double)rRad
.Y();
215 pC1
->X()=Round((double)pC1
->X()*nFact
);
218 RotatePoint(*pC1
,rCenter
,sn
,cs
);
222 // move into the direction of the center, as a basic position for the rotation
224 // resize, account for the distance from the center
225 pC2
->Y()=Round(((double)pC2
->Y()) /rRad
.X()*(rCenter
.X()-pC2
->X()));
228 // move into the direction of the center, as a basic position for the rotation
230 // resize, account for the distance from the center
231 long nPntRad
=rCenter
.Y()-pC2
->Y();
232 double nFact
=(double)nPntRad
/(double)rRad
.Y();
233 pC2
->X()=Round((double)pC2
->X()*nFact
);
236 RotatePoint(*pC2
,rCenter
,sn
,cs
);
243 double CrookSlantXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
244 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
)
254 long nStart
=rCenter
.X()-rRad
.X();
258 dxC1
=pC1
->X()-nStart
;
262 dxC2
=pC2
->X()-nStart
;
266 long nStart
=rCenter
.Y()-rRad
.Y();
270 dyC1
=pC1
->Y()-nStart
;
274 dyC2
=pC2
->Y()-nStart
;
278 double nWink
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
279 double sn
=sin(nWink
);
280 double cs
=cos(nWink
);
281 RotatePoint(rPnt
,rCenter
,sn
,cs
);
282 if (bC1
) { if (bVert
) pC1
->Y()-=y0
-rCenter
.Y(); else pC1
->X()-=x0
-rCenter
.X(); RotatePoint(*pC1
,rCenter
,sn
,cs
); }
283 if (bC2
) { if (bVert
) pC2
->Y()-=y0
-rCenter
.Y(); else pC2
->X()-=x0
-rCenter
.X(); RotatePoint(*pC2
,rCenter
,sn
,cs
); }
286 if (bC1
) pC1
->X()+=dxC1
;
287 if (bC2
) pC2
->X()+=dxC2
;
290 if (bC1
) pC1
->Y()+=dyC1
;
291 if (bC2
) pC2
->Y()+=dyC2
;
298 double CrookStretchXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
299 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
,
300 const Rectangle rRefRect
)
303 CrookSlantXPoint(rPnt
,pC1
,pC2
,rCenter
,rRad
,rSin
,rCos
,bVert
);
306 long nTop
=rRefRect
.Top();
307 long nBtm
=rRefRect
.Bottom();
310 double a
=((double)(y0
-nTop
))/nHgt
;
312 rPnt
.Y()=y0
+Round(a
);
316 ////////////////////////////////////////////////////////////////////////////////////////////////////
318 void CrookRotatePoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
321 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
323 while (i
<nPointAnz
) {
324 Point
* pPnt
=&rPoly
[i
];
327 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
333 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
337 CrookRotateXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
341 void CrookSlantPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
344 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
346 while (i
<nPointAnz
) {
347 Point
* pPnt
=&rPoly
[i
];
350 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
356 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
360 CrookSlantXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
364 void CrookStretchPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const Rectangle rRefRect
)
367 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
369 while (i
<nPointAnz
) {
370 Point
* pPnt
=&rPoly
[i
];
373 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
379 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
383 CrookStretchXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
,rRefRect
);
387 ////////////////////////////////////////////////////////////////////////////////////////////////////
389 void CrookRotatePoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
391 sal_uInt16 nPolyAnz
=rPoly
.Count();
392 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
393 CrookRotatePoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
397 void CrookSlantPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
399 sal_uInt16 nPolyAnz
=rPoly
.Count();
400 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
401 CrookSlantPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
405 void CrookStretchPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const Rectangle rRefRect
)
407 sal_uInt16 nPolyAnz
=rPoly
.Count();
408 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
409 CrookStretchPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
,rRefRect
);
413 ////////////////////////////////////////////////////////////////////////////////////////////////////
415 long GetAngle(const Point
& rPnt
)
419 if (rPnt
.X()<0) a
=-18000;
420 } else if (rPnt
.X()==0) {
421 if (rPnt
.Y()>0) a
=-9000;
424 a
=Round((atan2((double)-rPnt
.Y(),(double)rPnt
.X())/nPi180
));
429 long NormAngle180(long a
)
431 while (a
<18000) a
+=36000;
432 while (a
>=18000) a
-=36000;
436 long NormAngle360(long a
)
438 while (a
<0) a
+=36000;
439 while (a
>=36000) a
-=36000;
443 sal_uInt16
GetAngleSector(long nWink
)
445 while (nWink
<0) nWink
+=36000;
446 while (nWink
>=36000) nWink
-=36000;
447 if (nWink
< 9000) return 0;
448 if (nWink
<18000) return 1;
449 if (nWink
<27000) return 2;
453 long GetLen(const Point
& rPnt
)
455 long x
=Abs(rPnt
.X());
456 long y
=Abs(rPnt
.Y());
457 if (x
+y
<0x8000) { // because 7FFF * 7FFF * 2 = 7FFE0002
461 x
=Round(sqrt((double)x
));
471 return 0x7FFFFFFF; // we can't go any further, for fear of an overrun!
478 ////////////////////////////////////////////////////////////////////////////////////////////////////
480 void GeoStat::RecalcSinCos()
486 double a
=nDrehWink
*nPi180
;
492 void GeoStat::RecalcTan()
497 double a
=nShearWink
*nPi180
;
502 ////////////////////////////////////////////////////////////////////////////////////////////////////
504 Polygon
Rect2Poly(const Rectangle
& rRect
, const GeoStat
& rGeo
)
507 aPol
[0]=rRect
.TopLeft();
508 aPol
[1]=rRect
.TopRight();
509 aPol
[2]=rRect
.BottomRight();
510 aPol
[3]=rRect
.BottomLeft();
511 aPol
[4]=rRect
.TopLeft();
512 if (rGeo
.nShearWink
!=0) ShearPoly(aPol
,rRect
.TopLeft(),rGeo
.nTan
);
513 if (rGeo
.nDrehWink
!=0) RotatePoly(aPol
,rRect
.TopLeft(),rGeo
.nSin
,rGeo
.nCos
);
517 void Poly2Rect(const Polygon
& rPol
, Rectangle
& rRect
, GeoStat
& rGeo
)
519 rGeo
.nDrehWink
=GetAngle(rPol
[1]-rPol
[0]);
520 rGeo
.nDrehWink
=NormAngle360(rGeo
.nDrehWink
);
521 // rotation successful
524 Point
aPt1(rPol
[1]-rPol
[0]);
525 if (rGeo
.nDrehWink
!=0) RotatePoint(aPt1
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin to reverse rotation
529 Point
aPt3(rPol
[3]-rPol
[0]);
530 if (rGeo
.nDrehWink
!=0) RotatePoint(aPt3
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin to reverse rotation
534 long nShW
=GetAngle(aPt3
);
535 nShW
-=27000; // ShearWink is measured against a vertical line
536 nShW
=-nShW
; // Negieren, denn '+' ist Rechtskursivierung
538 bool bMirr
=aPt3
.Y()<0;
539 if (bMirr
) { // "exchange of points" when mirroring
544 nShW
=NormAngle180(nShW
);
545 if (nShW
<-9000 || nShW
>9000) {
546 nShW
=NormAngle180(nShW
+18000);
548 if (nShW
<-SDRMAXSHEAR
) nShW
=-SDRMAXSHEAR
; // limit ShearWinkel (shear angle) to +/- 89.00 deg
549 if (nShW
>SDRMAXSHEAR
) nShW
=SDRMAXSHEAR
;
550 rGeo
.nShearWink
=nShW
;
555 rRect
=Rectangle(aPt0
,aRU
);
558 ////////////////////////////////////////////////////////////////////////////////////////////////////
560 void OrthoDistance8(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
)
562 long dx
=rPt
.X()-rPt0
.X();
563 long dy
=rPt
.Y()-rPt0
.Y();
566 if (dx
==0 || dy
==0 || dxa
==dya
) return;
567 if (dxa
>=dya
*2) { rPt
.Y()=rPt0
.Y(); return; }
568 if (dya
>=dxa
*2) { rPt
.X()=rPt0
.X(); return; }
569 if ((dxa
<dya
) != bBigOrtho
) {
570 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
572 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
576 void OrthoDistance4(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
)
578 long dx
=rPt
.X()-rPt0
.X();
579 long dy
=rPt
.Y()-rPt0
.Y();
582 if ((dxa
<dya
) != bBigOrtho
) {
583 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
585 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
589 ////////////////////////////////////////////////////////////////////////////////////////////////////
591 long BigMulDiv(long nVal
, long nMul
, long nDiv
)
595 if (aVal
.IsNeg()!=(nDiv
<0)) {
596 aVal
-=nDiv
/2; // to round correctly
598 aVal
+=nDiv
/2; // to round correctly
608 void Kuerzen(Fraction
& rF
, unsigned nDigits
)
610 sal_Int32 nMul
=rF
.GetNumerator();
611 sal_Int32 nDiv
=rF
.GetDenominator();
613 if (nMul
<0) { nMul
=-nMul
; bNeg
=!bNeg
; }
614 if (nDiv
<0) { nDiv
=-nDiv
; bNeg
=!bNeg
; }
615 if (nMul
==0 || nDiv
==0) return;
617 a
=sal_uInt32(nMul
); unsigned nMulZ
=0; // count leading zeros
618 while (a
<0x00800000) { nMulZ
+=8; a
<<=8; }
619 while (a
<0x80000000) { nMulZ
++; a
<<=1; }
620 a
=sal_uInt32(nDiv
); unsigned nDivZ
=0; // count leading zeros
621 while (a
<0x00800000) { nDivZ
+=8; a
<<=8; }
622 while (a
<0x80000000) { nDivZ
++; a
<<=1; }
623 // count the number of digits
624 int nMulDigits
=32-nMulZ
;
625 int nDivDigits
=32-nDivZ
;
626 // count how many decimal places can be removed
627 int nMulWeg
=nMulDigits
-nDigits
; if (nMulWeg
<0) nMulWeg
=0;
628 int nDivWeg
=nDivDigits
-nDigits
; if (nDivWeg
<0) nDivWeg
=0;
629 int nWeg
=Min(nMulWeg
,nDivWeg
);
632 if (nMul
==0 || nDiv
==0) {
633 DBG_WARNING("Math error after canceling decimal places.");
636 if (bNeg
) nMul
=-nMul
;
637 rF
=Fraction(nMul
,nDiv
);
640 ////////////////////////////////////////////////////////////////////////////////////////////////////
641 // How many eU units fit into a mm, respectively an inch?
642 // Or: How many mm, respectively inches, are there in an eU (and then give me the inverse)
644 FrPair
GetInchOrMM(MapUnit eU
)
647 case MAP_1000TH_INCH
: return FrPair(1000,1);
648 case MAP_100TH_INCH
: return FrPair( 100,1);
649 case MAP_10TH_INCH
: return FrPair( 10,1);
650 case MAP_INCH
: return FrPair( 1,1);
651 case MAP_POINT
: return FrPair( 72,1);
652 case MAP_TWIP
: return FrPair(1440,1);
653 case MAP_100TH_MM
: return FrPair( 100,1);
654 case MAP_10TH_MM
: return FrPair( 10,1);
655 case MAP_MM
: return FrPair( 1,1);
656 case MAP_CM
: return FrPair( 1,10);
659 aVD
.SetMapMode(MapMode(MAP_100TH_MM
));
660 Point
aP(aVD
.PixelToLogic(Point(64,64))); // 64 pixels for more accuracy
661 return FrPair(6400,aP
.X(),6400,aP
.Y());
663 case MAP_APPFONT
: case MAP_SYSFONT
: {
665 aVD
.SetMapMode(MapMode(eU
));
666 Point
aP(aVD
.LogicToPixel(Point(32,32))); // 32 units for more accuracy
667 aVD
.SetMapMode(MapMode(MAP_100TH_MM
));
668 aP
=aVD
.PixelToLogic(aP
);
669 return FrPair(3200,aP
.X(),3200,aP
.Y());
673 return Fraction(1,1);
676 FrPair
GetInchOrMM(FieldUnit eU
)
679 case FUNIT_INCH
: return FrPair( 1,1);
680 case FUNIT_POINT
: return FrPair( 72,1);
681 case FUNIT_TWIP
: return FrPair(1440,1);
682 case FUNIT_100TH_MM
: return FrPair( 100,1);
683 case FUNIT_MM
: return FrPair( 1,1);
684 case FUNIT_CM
: return FrPair( 1,10);
685 case FUNIT_M
: return FrPair( 1,1000);
686 case FUNIT_KM
: return FrPair( 1,1000000);
687 case FUNIT_PICA
: return FrPair( 6,1);
688 case FUNIT_FOOT
: return FrPair( 1,12);
689 case FUNIT_MILE
: return FrPair( 1,63360);
692 return Fraction(1,1);
695 // Calculate the factor that we need to convert units from eS to eD.
696 // e. g. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
698 FrPair
GetMapFactor(MapUnit eS
, MapUnit eD
)
700 if (eS
==eD
) return FrPair(1,1,1,1);
701 FrPair
aS(GetInchOrMM(eS
));
702 FrPair
aD(GetInchOrMM(eD
));
703 bool bSInch
=IsInch(eS
);
704 bool bDInch
=IsInch(eD
);
705 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
706 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
707 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
711 FrPair
GetMapFactor(FieldUnit eS
, FieldUnit eD
)
713 if (eS
==eD
) return FrPair(1,1,1,1);
714 FrPair
aS(GetInchOrMM(eS
));
715 FrPair
aD(GetInchOrMM(eD
));
716 bool bSInch
=IsInch(eS
);
717 bool bDInch
=IsInch(eD
);
718 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
719 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
720 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
724 ////////////////////////////////////////////////////////////////////////////////////////////////////
726 // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm
727 // 1 furlong = 10 chains = 7.920" = 201.168,0mm
728 // 1 chain = 4 poles = 792" = 20.116,8mm
729 // 1 pole = 5 1/2 yd = 198" = 5.029,2mm
730 // 1 yd = 3 ft = 36" = 914,4mm
731 // 1 ft = 12 " = 1" = 304,8mm
733 void GetMeterOrInch(MapUnit eMU
, short& rnKomma
, long& rnMul
, long& rnDiv
, bool& rbMetr
, bool& rbInch
)
737 bool bMetr
= false, bInch
= false;
740 case MAP_100TH_MM
: bMetr
= true; nKomma
=5; break;
741 case MAP_10TH_MM
: bMetr
= true; nKomma
=4; break;
742 case MAP_MM
: bMetr
= true; nKomma
=3; break;
743 case MAP_CM
: bMetr
= true; nKomma
=2; break;
745 case MAP_1000TH_INCH
: bInch
= true; nKomma
=3; break;
746 case MAP_100TH_INCH
: bInch
= true; nKomma
=2; break;
747 case MAP_10TH_INCH
: bInch
= true; nKomma
=1; break;
748 case MAP_INCH
: bInch
= true; nKomma
=0; break;
749 case MAP_POINT
: bInch
= true; rnDiv
=72; break; // 1Pt = 1/72"
750 case MAP_TWIP
: bInch
= true; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
752 case MAP_PIXEL
: break;
753 case MAP_SYSFONT
: break;
754 case MAP_APPFONT
: break;
755 case MAP_RELATIVE
: break;
763 void GetMeterOrInch(FieldUnit eFU
, short& rnKomma
, long& rnMul
, long& rnDiv
, bool& rbMetr
, bool& rbInch
)
767 bool bMetr
= false, bInch
= false;
769 case FUNIT_NONE
: break;
771 case FUNIT_100TH_MM
: bMetr
= true; nKomma
=5; break;
772 case FUNIT_MM
: bMetr
= true; nKomma
=3; break;
773 case FUNIT_CM
: bMetr
= true; nKomma
=2; break;
774 case FUNIT_M
: bMetr
= true; nKomma
=0; break;
775 case FUNIT_KM
: bMetr
= true; nKomma
=-3; break;
777 case FUNIT_TWIP
: bInch
= true; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
778 case FUNIT_POINT
: bInch
= true; rnDiv
=72; break; // 1Pt = 1/72"
779 case FUNIT_PICA
: bInch
= true; rnDiv
=6; break; // 1Pica = 1/6" ?
780 case FUNIT_INCH
: bInch
= true; break; // 1" = 1"
781 case FUNIT_FOOT
: bInch
= true; rnMul
=12; break; // 1Ft = 12"
782 case FUNIT_MILE
: bInch
= true; rnMul
=6336; nKomma
=-1; break; // 1mile = 63360"
784 case FUNIT_CUSTOM
: break;
785 case FUNIT_PERCENT
: nKomma
=2; break;
786 // TODO: Add code to handle the following (added to remove warning)
787 case FUNIT_CHAR
: break;
788 case FUNIT_LINE
: break;
795 void SdrFormatter::Undirty()
797 if (aScale
.GetNumerator()==0 || aScale
.GetDenominator()==0) aScale
=Fraction(1,1);
798 bool bSrcMetr
,bSrcInch
,bDstMetr
,bDstInch
;
799 long nMul1
,nDiv1
,nMul2
,nDiv2
;
800 short nKomma1
,nKomma2
;
801 // first: normalize to m or in
803 GetMeterOrInch(eSrcMU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
805 GetMeterOrInch(eSrcFU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
808 GetMeterOrInch(eDstMU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
810 GetMeterOrInch(eDstFU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
814 nKomma1
=nKomma1
-nKomma2
;
816 if (bSrcInch
&& bDstMetr
) {
820 if (bSrcMetr
&& bDstInch
) {
825 // temporary fraction for canceling
826 Fraction
aTempFract(nMul1
,nDiv1
);
827 nMul1
=aTempFract
.GetNumerator();
828 nDiv1
=aTempFract
.GetDenominator();
837 void SdrFormatter::TakeStr(long nVal
, XubString
& rStr
) const
839 sal_Unicode
aNullCode('0');
848 // we may lose some decimal places here, because of MulDiv instead of Real
849 sal_Bool
bNeg(nVal
< 0);
850 SvtSysLocale aSysLoc
;
851 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
855 sal_Int16
nK(nKomma_
);
874 nVal
= BigMulDiv(nVal
, nMul_
, nDiv_
);
876 aStr
= UniString::CreateFromInt32(nVal
);
878 if(nK
> 0 && aStr
.Len() <= nK
)
880 // decimal separator necessary
881 sal_Int16
nAnz(nK
- aStr
.Len());
883 if(nAnz
>= 0 && rLoc
.isNumLeadingZero())
886 for(xub_StrLen i
=0; i
<nAnz
; i
++)
887 aStr
.Insert(aNullCode
, 0);
889 // remove superfluous decimal points
890 xub_StrLen
nNumDigits(rLoc
.getNumDigits());
891 xub_StrLen
nWeg(nK
- nNumDigits
);
895 // TODO: we should round here
896 aStr
.Erase(aStr
.Len() - nWeg
);
901 // remember everything before the decimal separator for later
902 xub_StrLen
nVorKomma(aStr
.Len() - nK
);
906 // insert KommaChar (decimal separator)
907 // remove trailing zeros
908 while(nK
> 0 && aStr
.GetChar(aStr
.Len() - 1) == aNullCode
)
910 aStr
.Erase(aStr
.Len() - 1);
916 // do we still have decimal places?
917 sal_Unicode
cDec(rLoc
.getNumDecimalSep().GetChar(0));
918 aStr
.Insert(cDec
, nVorKomma
);
922 // add in thousands separator (if necessary)
925 String
aThoSep( rLoc
.getNumThousandSep() );
926 if ( aThoSep
.Len() > 0 )
928 sal_Unicode
cTho( aThoSep
.GetChar(0) );
929 sal_Int32
i(nVorKomma
- 3);
933 rStr
.Insert(cTho
, (xub_StrLen
)i
);
942 if(bNeg
&& (aStr
.Len() > 1 || aStr
.GetChar(0) != aNullCode
))
944 rStr
.Insert(sal_Unicode('-'), 0);
950 void SdrFormatter::TakeUnitStr(MapUnit eUnit
, XubString
& rStr
)
957 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("/100mm"));
962 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("/10mm"));
967 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("mm"));
972 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("cm"));
977 case MAP_1000TH_INCH
:
979 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("/1000\""));
982 case MAP_100TH_INCH
:
984 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("/100\""));
989 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("/10\""));
995 rStr
+= sal_Unicode('"');
1000 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("pt"));
1005 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("twip"));
1012 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("pixel"));
1017 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("sysfont"));
1022 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("appfont"));
1028 rStr
+= sal_Unicode('%');
1035 void SdrFormatter::TakeUnitStr(FieldUnit eUnit
, XubString
& rStr
)
1048 case FUNIT_100TH_MM
:
1050 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("/100mm"));
1055 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("mm"));
1060 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("cm"));
1066 rStr
+= sal_Unicode('m');
1071 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("km"));
1078 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("twip"));
1083 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("pt"));
1088 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("pica"));
1094 rStr
+= sal_Unicode('"');
1099 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("ft"));
1104 rStr
= UniString(RTL_CONSTASCII_USTRINGPARAM("mile(s)"));
1112 rStr
+= sal_Unicode('%');
1118 ////////////////////////////////////////////////////////////////////////////////////////////////////
1121 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */