1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <svx/svdtrans.hxx>
23 #include <svx/xpoly.hxx>
25 #include <vcl/virdev.hxx>
26 #include <tools/bigint.hxx>
27 #include <tools/debug.hxx>
28 #include <unotools/syslocale.hxx>
30 void MoveXPoly(XPolygon
& rPoly
, const Size
& S
)
32 rPoly
.Move(S
.Width(),S
.Height());
35 void ResizeRect(Rectangle
& rRect
, const Point
& rRef
, const Fraction
& rxFact
, const Fraction
& ryFact
, bool bNoJustify
)
37 Fraction
xFact(rxFact
);
38 Fraction
yFact(ryFact
);
41 if (xFact
.GetDenominator()==0) {
42 long nWdt
=rRect
.Right()-rRect
.Left();
43 if (xFact
.GetNumerator()>=0) { // catch divisions by zero
44 xFact
=Fraction(xFact
.GetNumerator(),1);
45 if (nWdt
==0) rRect
.Right()++;
47 xFact
=Fraction(xFact
.GetNumerator(),-1);
48 if (nWdt
==0) rRect
.Left()--;
51 rRect
.Left() =rRef
.X()+Round(((double)(rRect
.Left() -rRef
.X())*xFact
.GetNumerator())/xFact
.GetDenominator());
52 rRect
.Right() =rRef
.X()+Round(((double)(rRect
.Right() -rRef
.X())*xFact
.GetNumerator())/xFact
.GetDenominator());
55 if (yFact
.GetDenominator()==0) {
56 long nHgt
=rRect
.Bottom()-rRect
.Top();
57 if (yFact
.GetNumerator()>=0) { // catch divisions by zero
58 yFact
=Fraction(yFact
.GetNumerator(),1);
59 if (nHgt
==0) rRect
.Bottom()++;
61 yFact
=Fraction(yFact
.GetNumerator(),-1);
62 if (nHgt
==0) rRect
.Top()--;
65 yFact
=Fraction(yFact
.GetNumerator(),1); // catch divisions by zero
67 rRect
.Top() =rRef
.Y()+Round(((double)(rRect
.Top() -rRef
.Y())*yFact
.GetNumerator())/yFact
.GetDenominator());
68 rRect
.Bottom()=rRef
.Y()+Round(((double)(rRect
.Bottom()-rRef
.Y())*yFact
.GetNumerator())/yFact
.GetDenominator());
70 if (!bNoJustify
) rRect
.Justify();
74 void ResizePoly(Polygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
76 sal_uInt16 nAnz
=rPoly
.GetSize();
77 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
78 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
82 void ResizeXPoly(XPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
84 sal_uInt16 nAnz
=rPoly
.GetPointCount();
85 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
86 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
90 void RotatePoly(Polygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
92 sal_uInt16 nAnz
=rPoly
.GetSize();
93 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
94 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
98 void RotateXPoly(XPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
100 sal_uInt16 nAnz
=rPoly
.GetPointCount();
101 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
102 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
106 void RotateXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
108 sal_uInt16 nAnz
=rPoly
.Count();
109 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
110 RotateXPoly(rPoly
[i
],rRef
,sn
,cs
);
114 void MirrorPoint(Point
& rPnt
, const Point
& rRef1
, const Point
& rRef2
)
116 long mx
=rRef2
.X()-rRef1
.X();
117 long my
=rRef2
.Y()-rRef1
.Y();
118 if (mx
==0) { // vertical axis
119 long dx
=rRef1
.X()-rPnt
.X();
121 } else if (my
==0) { // horizontal axis
122 long dy
=rRef1
.Y()-rPnt
.Y();
124 } else if (mx
==my
) { // diagonal axis '\'
125 long dx1
=rPnt
.X()-rRef1
.X();
126 long dy1
=rPnt
.Y()-rRef1
.Y();
127 rPnt
.X()=rRef1
.X()+dy1
;
128 rPnt
.Y()=rRef1
.Y()+dx1
;
129 } else if (mx
==-my
) { // diagonal axis '/'
130 long dx1
=rPnt
.X()-rRef1
.X();
131 long dy1
=rPnt
.Y()-rRef1
.Y();
132 rPnt
.X()=rRef1
.X()-dy1
;
133 rPnt
.Y()=rRef1
.Y()-dx1
;
134 } else { // arbitrary axis
135 // TODO: Optimize this! Raise perpendicular on the mirroring axis..?
136 long nRefWink
=GetAngle(rRef2
-rRef1
);
138 long nPntWink
=GetAngle(rPnt
);
139 long nWink
=2*(nRefWink
-nPntWink
);
140 double a
=nWink
*nPi180
;
143 RotatePoint(rPnt
,Point(),nSin
,nCos
);
148 void MirrorPoly(Polygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
150 sal_uInt16 nAnz
=rPoly
.GetSize();
151 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
152 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
156 void MirrorXPoly(XPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
158 sal_uInt16 nAnz
=rPoly
.GetPointCount();
159 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
160 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
164 void ShearPoly(Polygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
)
166 sal_uInt16 nAnz
=rPoly
.GetSize();
167 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
168 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
172 void ShearXPoly(XPolygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
)
174 sal_uInt16 nAnz
=rPoly
.GetPointCount();
175 for (sal_uInt16 i
=0; i
<nAnz
; i
++) {
176 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
180 double CrookRotateXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
181 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
)
189 double nWink
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
190 double sn
=sin(nWink
);
191 double cs
=cos(nWink
);
192 RotatePoint(rPnt
,rCenter
,sn
,cs
);
195 // move into the direction of the center, as a basic position for the rotation
197 // resize, account for the distance from the center
198 pC1
->Y()=Round(((double)pC1
->Y()) /rRad
.X()*(cx
-pC1
->X()));
201 // move into the direction of the center, as a basic position for the rotation
203 // resize, account for the distance from the center
204 long nPntRad
=cy
-pC1
->Y();
205 double nFact
=(double)nPntRad
/(double)rRad
.Y();
206 pC1
->X()=Round((double)pC1
->X()*nFact
);
209 RotatePoint(*pC1
,rCenter
,sn
,cs
);
213 // move into the direction of the center, as a basic position for the rotation
215 // resize, account for the distance from the center
216 pC2
->Y()=Round(((double)pC2
->Y()) /rRad
.X()*(rCenter
.X()-pC2
->X()));
219 // move into the direction of the center, as a basic position for the rotation
221 // resize, account for the distance from the center
222 long nPntRad
=rCenter
.Y()-pC2
->Y();
223 double nFact
=(double)nPntRad
/(double)rRad
.Y();
224 pC2
->X()=Round((double)pC2
->X()*nFact
);
227 RotatePoint(*pC2
,rCenter
,sn
,cs
);
234 double CrookSlantXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
235 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
)
245 long nStart
=rCenter
.X()-rRad
.X();
249 dxC1
=pC1
->X()-nStart
;
253 dxC2
=pC2
->X()-nStart
;
257 long nStart
=rCenter
.Y()-rRad
.Y();
261 dyC1
=pC1
->Y()-nStart
;
265 dyC2
=pC2
->Y()-nStart
;
269 double nWink
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
270 double sn
=sin(nWink
);
271 double cs
=cos(nWink
);
272 RotatePoint(rPnt
,rCenter
,sn
,cs
);
273 if (bC1
) { if (bVert
) pC1
->Y()-=y0
-rCenter
.Y(); else pC1
->X()-=x0
-rCenter
.X(); RotatePoint(*pC1
,rCenter
,sn
,cs
); }
274 if (bC2
) { if (bVert
) pC2
->Y()-=y0
-rCenter
.Y(); else pC2
->X()-=x0
-rCenter
.X(); RotatePoint(*pC2
,rCenter
,sn
,cs
); }
277 if (bC1
) pC1
->X()+=dxC1
;
278 if (bC2
) pC2
->X()+=dxC2
;
281 if (bC1
) pC1
->Y()+=dyC1
;
282 if (bC2
) pC2
->Y()+=dyC2
;
289 double CrookStretchXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
290 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
,
291 const Rectangle rRefRect
)
294 CrookSlantXPoint(rPnt
,pC1
,pC2
,rCenter
,rRad
,rSin
,rCos
,bVert
);
297 long nTop
=rRefRect
.Top();
298 long nBtm
=rRefRect
.Bottom();
301 double a
=((double)(y0
-nTop
))/nHgt
;
303 rPnt
.Y()=y0
+Round(a
);
307 ////////////////////////////////////////////////////////////////////////////////////////////////////
309 void CrookRotatePoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
312 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
314 while (i
<nPointAnz
) {
315 Point
* pPnt
=&rPoly
[i
];
318 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
324 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
328 CrookRotateXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
332 void CrookSlantPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
335 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
337 while (i
<nPointAnz
) {
338 Point
* pPnt
=&rPoly
[i
];
341 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
347 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
351 CrookSlantXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
355 void CrookStretchPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const Rectangle rRefRect
)
358 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
360 while (i
<nPointAnz
) {
361 Point
* pPnt
=&rPoly
[i
];
364 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
370 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
374 CrookStretchXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
,rRefRect
);
378 ////////////////////////////////////////////////////////////////////////////////////////////////////
380 void CrookRotatePoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
382 sal_uInt16 nPolyAnz
=rPoly
.Count();
383 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
384 CrookRotatePoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
388 void CrookSlantPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
390 sal_uInt16 nPolyAnz
=rPoly
.Count();
391 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
392 CrookSlantPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
396 void CrookStretchPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const Rectangle rRefRect
)
398 sal_uInt16 nPolyAnz
=rPoly
.Count();
399 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyAnz
; nPolyNum
++) {
400 CrookStretchPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
,rRefRect
);
404 ////////////////////////////////////////////////////////////////////////////////////////////////////
406 long GetAngle(const Point
& rPnt
)
410 if (rPnt
.X()<0) a
=-18000;
411 } else if (rPnt
.X()==0) {
412 if (rPnt
.Y()>0) a
=-9000;
415 a
=Round((atan2((double)-rPnt
.Y(),(double)rPnt
.X())/nPi180
));
420 long NormAngle180(long a
)
422 while (a
<18000) a
+=36000;
423 while (a
>=18000) a
-=36000;
427 long NormAngle360(long a
)
429 while (a
<0) a
+=36000;
430 while (a
>=36000) a
-=36000;
434 sal_uInt16
GetAngleSector(long nWink
)
436 while (nWink
<0) nWink
+=36000;
437 while (nWink
>=36000) nWink
-=36000;
438 if (nWink
< 9000) return 0;
439 if (nWink
<18000) return 1;
440 if (nWink
<27000) return 2;
444 long GetLen(const Point
& rPnt
)
446 long x
=std::abs(rPnt
.X());
447 long y
=std::abs(rPnt
.Y());
448 if (x
+y
<0x8000) { // because 7FFF * 7FFF * 2 = 7FFE0002
452 x
=Round(sqrt((double)x
));
462 return 0x7FFFFFFF; // we can't go any further, for fear of an overrun!
469 ////////////////////////////////////////////////////////////////////////////////////////////////////
471 void GeoStat::RecalcSinCos()
477 double a
=nDrehWink
*nPi180
;
483 void GeoStat::RecalcTan()
488 double a
=nShearWink
*nPi180
;
493 ////////////////////////////////////////////////////////////////////////////////////////////////////
495 Polygon
Rect2Poly(const Rectangle
& rRect
, const GeoStat
& rGeo
)
498 aPol
[0]=rRect
.TopLeft();
499 aPol
[1]=rRect
.TopRight();
500 aPol
[2]=rRect
.BottomRight();
501 aPol
[3]=rRect
.BottomLeft();
502 aPol
[4]=rRect
.TopLeft();
503 if (rGeo
.nShearWink
!=0) ShearPoly(aPol
,rRect
.TopLeft(),rGeo
.nTan
);
504 if (rGeo
.nDrehWink
!=0) RotatePoly(aPol
,rRect
.TopLeft(),rGeo
.nSin
,rGeo
.nCos
);
508 void Poly2Rect(const Polygon
& rPol
, Rectangle
& rRect
, GeoStat
& rGeo
)
510 rGeo
.nDrehWink
=GetAngle(rPol
[1]-rPol
[0]);
511 rGeo
.nDrehWink
=NormAngle360(rGeo
.nDrehWink
);
512 // rotation successful
515 Point
aPt1(rPol
[1]-rPol
[0]);
516 if (rGeo
.nDrehWink
!=0) RotatePoint(aPt1
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin to reverse rotation
520 Point
aPt3(rPol
[3]-rPol
[0]);
521 if (rGeo
.nDrehWink
!=0) RotatePoint(aPt3
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin to reverse rotation
525 long nShW
=GetAngle(aPt3
);
526 nShW
-=27000; // ShearWink is measured against a vertical line
527 nShW
=-nShW
; // Negieren, denn '+' ist Rechtskursivierung
529 bool bMirr
=aPt3
.Y()<0;
530 if (bMirr
) { // "exchange of points" when mirroring
535 nShW
=NormAngle180(nShW
);
536 if (nShW
<-9000 || nShW
>9000) {
537 nShW
=NormAngle180(nShW
+18000);
539 if (nShW
<-SDRMAXSHEAR
) nShW
=-SDRMAXSHEAR
; // limit ShearWinkel (shear angle) to +/- 89.00 deg
540 if (nShW
>SDRMAXSHEAR
) nShW
=SDRMAXSHEAR
;
541 rGeo
.nShearWink
=nShW
;
546 rRect
=Rectangle(aPt0
,aRU
);
549 ////////////////////////////////////////////////////////////////////////////////////////////////////
551 void OrthoDistance8(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
)
553 long dx
=rPt
.X()-rPt0
.X();
554 long dy
=rPt
.Y()-rPt0
.Y();
555 long dxa
=std::abs(dx
);
556 long dya
=std::abs(dy
);
557 if (dx
==0 || dy
==0 || dxa
==dya
) return;
558 if (dxa
>=dya
*2) { rPt
.Y()=rPt0
.Y(); return; }
559 if (dya
>=dxa
*2) { rPt
.X()=rPt0
.X(); return; }
560 if ((dxa
<dya
) != bBigOrtho
) {
561 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
563 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
567 void OrthoDistance4(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
)
569 long dx
=rPt
.X()-rPt0
.X();
570 long dy
=rPt
.Y()-rPt0
.Y();
571 long dxa
=std::abs(dx
);
572 long dya
=std::abs(dy
);
573 if ((dxa
<dya
) != bBigOrtho
) {
574 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
576 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
580 ////////////////////////////////////////////////////////////////////////////////////////////////////
582 long BigMulDiv(long nVal
, long nMul
, long nDiv
)
586 if (aVal
.IsNeg()!=(nDiv
<0)) {
587 aVal
-=nDiv
/2; // to round correctly
589 aVal
+=nDiv
/2; // to round correctly
599 void Kuerzen(Fraction
& rF
, unsigned nDigits
)
601 sal_Int32 nMul
=rF
.GetNumerator();
602 sal_Int32 nDiv
=rF
.GetDenominator();
604 if (nMul
<0) { nMul
=-nMul
; bNeg
=!bNeg
; }
605 if (nDiv
<0) { nDiv
=-nDiv
; bNeg
=!bNeg
; }
606 if (nMul
==0 || nDiv
==0) return;
608 a
=sal_uInt32(nMul
); unsigned nMulZ
=0; // count leading zeros
609 while (a
<0x00800000) { nMulZ
+=8; a
<<=8; }
610 while (a
<0x80000000) { nMulZ
++; a
<<=1; }
611 a
=sal_uInt32(nDiv
); unsigned nDivZ
=0; // count leading zeros
612 while (a
<0x00800000) { nDivZ
+=8; a
<<=8; }
613 while (a
<0x80000000) { nDivZ
++; a
<<=1; }
614 // count the number of digits
615 int nMulDigits
=32-nMulZ
;
616 int nDivDigits
=32-nDivZ
;
617 // count how many decimal places can be removed
618 int nMulWeg
=nMulDigits
-nDigits
; if (nMulWeg
<0) nMulWeg
=0;
619 int nDivWeg
=nDivDigits
-nDigits
; if (nDivWeg
<0) nDivWeg
=0;
620 int nWeg
=std::min(nMulWeg
,nDivWeg
);
623 if (nMul
==0 || nDiv
==0) {
624 DBG_WARNING("Math error after canceling decimal places.");
627 if (bNeg
) nMul
=-nMul
;
628 rF
=Fraction(nMul
,nDiv
);
631 ////////////////////////////////////////////////////////////////////////////////////////////////////
632 // How many eU units fit into a mm, respectively an inch?
633 // Or: How many mm, respectively inches, are there in an eU (and then give me the inverse)
635 FrPair
GetInchOrMM(MapUnit eU
)
638 case MAP_1000TH_INCH
: return FrPair(1000,1);
639 case MAP_100TH_INCH
: return FrPair( 100,1);
640 case MAP_10TH_INCH
: return FrPair( 10,1);
641 case MAP_INCH
: return FrPair( 1,1);
642 case MAP_POINT
: return FrPair( 72,1);
643 case MAP_TWIP
: return FrPair(1440,1);
644 case MAP_100TH_MM
: return FrPair( 100,1);
645 case MAP_10TH_MM
: return FrPair( 10,1);
646 case MAP_MM
: return FrPair( 1,1);
647 case MAP_CM
: return FrPair( 1,10);
650 aVD
.SetMapMode(MapMode(MAP_100TH_MM
));
651 Point
aP(aVD
.PixelToLogic(Point(64,64))); // 64 pixels for more accuracy
652 return FrPair(6400,aP
.X(),6400,aP
.Y());
654 case MAP_APPFONT
: case MAP_SYSFONT
: {
656 aVD
.SetMapMode(MapMode(eU
));
657 Point
aP(aVD
.LogicToPixel(Point(32,32))); // 32 units for more accuracy
658 aVD
.SetMapMode(MapMode(MAP_100TH_MM
));
659 aP
=aVD
.PixelToLogic(aP
);
660 return FrPair(3200,aP
.X(),3200,aP
.Y());
664 return Fraction(1,1);
667 FrPair
GetInchOrMM(FieldUnit eU
)
670 case FUNIT_INCH
: return FrPair( 1,1);
671 case FUNIT_POINT
: return FrPair( 72,1);
672 case FUNIT_TWIP
: return FrPair(1440,1);
673 case FUNIT_100TH_MM
: return FrPair( 100,1);
674 case FUNIT_MM
: return FrPair( 1,1);
675 case FUNIT_CM
: return FrPair( 1,10);
676 case FUNIT_M
: return FrPair( 1,1000);
677 case FUNIT_KM
: return FrPair( 1,1000000);
678 case FUNIT_PICA
: return FrPair( 6,1);
679 case FUNIT_FOOT
: return FrPair( 1,12);
680 case FUNIT_MILE
: return FrPair( 1,63360);
683 return Fraction(1,1);
686 // Calculate the factor that we need to convert units from eS to eD.
687 // e. g. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
689 FrPair
GetMapFactor(MapUnit eS
, MapUnit eD
)
691 if (eS
==eD
) return FrPair(1,1,1,1);
692 FrPair
aS(GetInchOrMM(eS
));
693 FrPair
aD(GetInchOrMM(eD
));
694 bool bSInch
=IsInch(eS
);
695 bool bDInch
=IsInch(eD
);
696 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
697 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
698 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
702 FrPair
GetMapFactor(FieldUnit eS
, FieldUnit eD
)
704 if (eS
==eD
) return FrPair(1,1,1,1);
705 FrPair
aS(GetInchOrMM(eS
));
706 FrPair
aD(GetInchOrMM(eD
));
707 bool bSInch
=IsInch(eS
);
708 bool bDInch
=IsInch(eD
);
709 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
710 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
711 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
715 ////////////////////////////////////////////////////////////////////////////////////////////////////
717 // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm
718 // 1 furlong = 10 chains = 7.920" = 201.168,0mm
719 // 1 chain = 4 poles = 792" = 20.116,8mm
720 // 1 pole = 5 1/2 yd = 198" = 5.029,2mm
721 // 1 yd = 3 ft = 36" = 914,4mm
722 // 1 ft = 12 " = 1" = 304,8mm
724 void GetMeterOrInch(MapUnit eMU
, short& rnKomma
, long& rnMul
, long& rnDiv
, bool& rbMetr
, bool& rbInch
)
728 bool bMetr
= false, bInch
= false;
731 case MAP_100TH_MM
: bMetr
= true; nKomma
=5; break;
732 case MAP_10TH_MM
: bMetr
= true; nKomma
=4; break;
733 case MAP_MM
: bMetr
= true; nKomma
=3; break;
734 case MAP_CM
: bMetr
= true; nKomma
=2; break;
736 case MAP_1000TH_INCH
: bInch
= true; nKomma
=3; break;
737 case MAP_100TH_INCH
: bInch
= true; nKomma
=2; break;
738 case MAP_10TH_INCH
: bInch
= true; nKomma
=1; break;
739 case MAP_INCH
: bInch
= true; nKomma
=0; break;
740 case MAP_POINT
: bInch
= true; rnDiv
=72; break; // 1Pt = 1/72"
741 case MAP_TWIP
: bInch
= true; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
743 case MAP_PIXEL
: break;
744 case MAP_SYSFONT
: break;
745 case MAP_APPFONT
: break;
746 case MAP_RELATIVE
: break;
754 void GetMeterOrInch(FieldUnit eFU
, short& rnKomma
, long& rnMul
, long& rnDiv
, bool& rbMetr
, bool& rbInch
)
758 bool bMetr
= false, bInch
= false;
760 case FUNIT_NONE
: break;
762 case FUNIT_100TH_MM
: bMetr
= true; nKomma
=5; break;
763 case FUNIT_MM
: bMetr
= true; nKomma
=3; break;
764 case FUNIT_CM
: bMetr
= true; nKomma
=2; break;
765 case FUNIT_M
: bMetr
= true; nKomma
=0; break;
766 case FUNIT_KM
: bMetr
= true; nKomma
=-3; break;
768 case FUNIT_TWIP
: bInch
= true; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
769 case FUNIT_POINT
: bInch
= true; rnDiv
=72; break; // 1Pt = 1/72"
770 case FUNIT_PICA
: bInch
= true; rnDiv
=6; break; // 1Pica = 1/6" ?
771 case FUNIT_INCH
: bInch
= true; break; // 1" = 1"
772 case FUNIT_FOOT
: bInch
= true; rnMul
=12; break; // 1Ft = 12"
773 case FUNIT_MILE
: bInch
= true; rnMul
=6336; nKomma
=-1; break; // 1mile = 63360"
775 case FUNIT_CUSTOM
: break;
776 case FUNIT_PERCENT
: nKomma
=2; break;
777 // TODO: Add code to handle the following (added to remove warning)
778 case FUNIT_CHAR
: break;
779 case FUNIT_LINE
: break;
786 void SdrFormatter::Undirty()
788 if (aScale
.GetNumerator()==0 || aScale
.GetDenominator()==0) aScale
=Fraction(1,1);
789 bool bSrcMetr
,bSrcInch
,bDstMetr
,bDstInch
;
790 long nMul1
,nDiv1
,nMul2
,nDiv2
;
791 short nKomma1
,nKomma2
;
792 // first: normalize to m or in
794 GetMeterOrInch(eSrcMU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
796 GetMeterOrInch(eSrcFU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
799 GetMeterOrInch(eDstMU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
801 GetMeterOrInch(eDstFU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
805 nKomma1
=nKomma1
-nKomma2
;
807 if (bSrcInch
&& bDstMetr
) {
811 if (bSrcMetr
&& bDstInch
) {
816 // temporary fraction for canceling
817 Fraction
aTempFract(nMul1
,nDiv1
);
818 nMul1
=aTempFract
.GetNumerator();
819 nDiv1
=aTempFract
.GetDenominator();
828 void SdrFormatter::TakeStr(long nVal
, OUString
& rStr
) const
830 OUString
aNullCode("0");
838 // we may lose some decimal places here, because of MulDiv instead of Real
840 SvtSysLocale aSysLoc
;
841 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
845 sal_Int16
nC(nKomma_
);
863 nVal
= BigMulDiv(nVal
, nMul_
, nDiv_
);
865 OUStringBuffer aStr
= OUString::valueOf(nVal
);
867 if(nC
> 0 && aStr
.getLength() <= nC
)
869 // decimal separator necessary
870 sal_Int32
nAnz(nC
- aStr
.getLength());
872 if(nAnz
>= 0 && rLoc
.isNumLeadingZero())
875 for(sal_Int32 i
=0; i
<nAnz
; i
++)
876 aStr
.insert(0, aNullCode
);
878 // remove superfluous decimal points
879 sal_Int32
nNumDigits(rLoc
.getNumDigits());
880 sal_Int32
nWeg(nC
- nNumDigits
);
884 // TODO: we should round here
885 aStr
.remove(aStr
.getLength() - nWeg
, nWeg
);
890 // remember everything before the decimal separator for later
891 sal_Int32
nForComma(aStr
.getLength() - nC
);
895 // insert comma char (decimal separator)
896 // remove trailing zeros
897 while(nC
> 0 && aStr
[aStr
.getLength() - 1] == aNullCode
[0])
899 aStr
.remove(aStr
.getLength() - 1, 1);
905 // do we still have decimal places?
906 sal_Unicode
cDec(rLoc
.getNumDecimalSep()[0]);
907 aStr
.insert(nForComma
, cDec
);
911 // add in thousands separator (if necessary)
914 OUString
aThoSep( rLoc
.getNumThousandSep() );
915 if ( aThoSep
.getLength() > 0 )
917 sal_Unicode
cTho( aThoSep
[0] );
918 sal_Int32
i(nForComma
- 3);
922 aStr
.insert(i
, cTho
);
928 if(!aStr
.getLength())
929 aStr
.insert(aStr
.getLength(), aNullCode
);
931 if(bNeg
&& (aStr
.getLength() > 1 || aStr
[0] != aNullCode
[0]))
936 rStr
= aStr
.makeStringAndClear();
939 void SdrFormatter::TakeUnitStr(MapUnit eUnit
, OUString
& rStr
)
966 case MAP_1000TH_INCH
:
971 case MAP_100TH_INCH
:
1022 void SdrFormatter::TakeUnitStr(FieldUnit eUnit
, OUString
& rStr
)
1035 case FUNIT_100TH_MM
:
1102 ////////////////////////////////////////////////////////////////////////////////////////////////////
1105 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */