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
);
40 if (!xFact
.IsValid()) {
41 SAL_WARN( "svx.svdraw", "invalid fraction xFract, using Fraction(1,1)" );
42 xFact
= Fraction(1,1);
43 long nWdt
= rRect
.Right() - rRect
.Left();
44 if (nWdt
== 0) rRect
.Right()++;
46 rRect
.Left() = rRef
.X() + Round( (rRect
.Left() - rRef
.X()) * double(xFact
) );
47 rRect
.Right() = rRef
.X() + Round( (rRect
.Right() - rRef
.X()) * double(xFact
) );
49 if (!yFact
.IsValid()) {
50 SAL_WARN( "svx.svdraw", "invalid fraction yFract, using Fraction(1,1)" );
51 yFact
= Fraction(1,1);
52 long nHgt
= rRect
.Bottom() - rRect
.Top();
53 if (nHgt
== 0) rRect
.Bottom()++;
55 rRect
.Top() = rRef
.Y() + Round( (rRect
.Top() - rRef
.Y()) * double(yFact
) );
56 rRect
.Bottom() = rRef
.Y() + Round( (rRect
.Bottom() - rRef
.Y()) * double(yFact
) );
58 if (!bNoJustify
) rRect
.Justify();
62 void ResizePoly(Polygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
64 sal_uInt16 nCount
=rPoly
.GetSize();
65 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
66 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
70 void ResizeXPoly(XPolygon
& rPoly
, const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
72 sal_uInt16 nCount
=rPoly
.GetPointCount();
73 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
74 ResizePoint(rPoly
[i
],rRef
,xFact
,yFact
);
78 void RotatePoly(Polygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
80 sal_uInt16 nCount
=rPoly
.GetSize();
81 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
82 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
86 void RotateXPoly(XPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
88 sal_uInt16 nCount
=rPoly
.GetPointCount();
89 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
90 RotatePoint(rPoly
[i
],rRef
,sn
,cs
);
94 void RotateXPoly(XPolyPolygon
& rPoly
, const Point
& rRef
, double sn
, double cs
)
96 sal_uInt16 nCount
=rPoly
.Count();
97 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
98 RotateXPoly(rPoly
[i
],rRef
,sn
,cs
);
102 void MirrorPoint(Point
& rPnt
, const Point
& rRef1
, const Point
& rRef2
)
104 long mx
=rRef2
.X()-rRef1
.X();
105 long my
=rRef2
.Y()-rRef1
.Y();
106 if (mx
==0) { // vertical axis
107 long dx
=rRef1
.X()-rPnt
.X();
109 } else if (my
==0) { // horizontal axis
110 long dy
=rRef1
.Y()-rPnt
.Y();
112 } else if (mx
==my
) { // diagonal axis '\'
113 long dx1
=rPnt
.X()-rRef1
.X();
114 long dy1
=rPnt
.Y()-rRef1
.Y();
115 rPnt
.X()=rRef1
.X()+dy1
;
116 rPnt
.Y()=rRef1
.Y()+dx1
;
117 } else if (mx
==-my
) { // diagonal axis '/'
118 long dx1
=rPnt
.X()-rRef1
.X();
119 long dy1
=rPnt
.Y()-rRef1
.Y();
120 rPnt
.X()=rRef1
.X()-dy1
;
121 rPnt
.Y()=rRef1
.Y()-dx1
;
122 } else { // arbitrary axis
123 // TODO: Optimize this! Raise perpendicular on the mirroring axis..?
124 long nRefWink
=GetAngle(rRef2
-rRef1
);
126 long nPntWink
=GetAngle(rPnt
);
127 long nAngle
=2*(nRefWink
-nPntWink
);
128 double a
=nAngle
*nPi180
;
131 RotatePoint(rPnt
,Point(),nSin
,nCos
);
136 void MirrorPoly(Polygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
138 sal_uInt16 nCount
=rPoly
.GetSize();
139 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
140 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
144 void MirrorXPoly(XPolygon
& rPoly
, const Point
& rRef1
, const Point
& rRef2
)
146 sal_uInt16 nCount
=rPoly
.GetPointCount();
147 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
148 MirrorPoint(rPoly
[i
],rRef1
,rRef2
);
152 void ShearPoly(Polygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
)
154 sal_uInt16 nCount
=rPoly
.GetSize();
155 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
156 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
160 void ShearXPoly(XPolygon
& rPoly
, const Point
& rRef
, double tn
, bool bVShear
)
162 sal_uInt16 nCount
=rPoly
.GetPointCount();
163 for (sal_uInt16 i
=0; i
<nCount
; i
++) {
164 ShearPoint(rPoly
[i
],rRef
,tn
,bVShear
);
168 double CrookRotateXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
169 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
)
177 double nAngle
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
178 double sn
=sin(nAngle
);
179 double cs
=cos(nAngle
);
180 RotatePoint(rPnt
,rCenter
,sn
,cs
);
183 // move into the direction of the center, as a basic position for the rotation
185 // resize, account for the distance from the center
186 pC1
->Y()=Round(((double)pC1
->Y()) /rRad
.X()*(cx
-pC1
->X()));
189 // move into the direction of the center, as a basic position for the rotation
191 // resize, account for the distance from the center
192 long nPntRad
=cy
-pC1
->Y();
193 double nFact
=(double)nPntRad
/(double)rRad
.Y();
194 pC1
->X()=Round((double)pC1
->X()*nFact
);
197 RotatePoint(*pC1
,rCenter
,sn
,cs
);
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 pC2
->Y()=Round(((double)pC2
->Y()) /rRad
.X()*(rCenter
.X()-pC2
->X()));
207 // move into the direction of the center, as a basic position for the rotation
209 // resize, account for the distance from the center
210 long nPntRad
=rCenter
.Y()-pC2
->Y();
211 double nFact
=(double)nPntRad
/(double)rRad
.Y();
212 pC2
->X()=Round((double)pC2
->X()*nFact
);
215 RotatePoint(*pC2
,rCenter
,sn
,cs
);
222 double CrookSlantXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
223 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
)
233 long nStart
=rCenter
.X()-rRad
.X();
237 dxC1
=pC1
->X()-nStart
;
241 dxC2
=pC2
->X()-nStart
;
245 long nStart
=rCenter
.Y()-rRad
.Y();
249 dyC1
=pC1
->Y()-nStart
;
253 dyC2
=pC2
->Y()-nStart
;
257 double nAngle
=GetCrookAngle(rPnt
,rCenter
,rRad
,bVert
);
258 double sn
=sin(nAngle
);
259 double cs
=cos(nAngle
);
260 RotatePoint(rPnt
,rCenter
,sn
,cs
);
261 if (bC1
) { if (bVert
) pC1
->Y()-=y0
-rCenter
.Y(); else pC1
->X()-=x0
-rCenter
.X(); RotatePoint(*pC1
,rCenter
,sn
,cs
); }
262 if (bC2
) { if (bVert
) pC2
->Y()-=y0
-rCenter
.Y(); else pC2
->X()-=x0
-rCenter
.X(); RotatePoint(*pC2
,rCenter
,sn
,cs
); }
265 if (bC1
) pC1
->X()+=dxC1
;
266 if (bC2
) pC2
->X()+=dxC2
;
269 if (bC1
) pC1
->Y()+=dyC1
;
270 if (bC2
) pC2
->Y()+=dyC2
;
277 double CrookStretchXPoint(Point
& rPnt
, Point
* pC1
, Point
* pC2
, const Point
& rCenter
,
278 const Point
& rRad
, double& rSin
, double& rCos
, bool bVert
,
279 const Rectangle
& rRefRect
)
282 CrookSlantXPoint(rPnt
,pC1
,pC2
,rCenter
,rRad
,rSin
,rCos
,bVert
);
285 long nTop
=rRefRect
.Top();
286 long nBtm
=rRefRect
.Bottom();
289 double a
=((double)(y0
-nTop
))/nHgt
;
291 rPnt
.Y()=y0
+Round(a
);
297 void CrookRotatePoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
300 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
302 while (i
<nPointAnz
) {
303 Point
* pPnt
=&rPoly
[i
];
306 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
312 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
316 CrookRotateXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
320 void CrookSlantPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
323 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
325 while (i
<nPointAnz
) {
326 Point
* pPnt
=&rPoly
[i
];
329 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
335 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
339 CrookSlantXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
);
343 void CrookStretchPoly(XPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const Rectangle
& rRefRect
)
346 sal_uInt16 nPointAnz
=rPoly
.GetPointCount();
348 while (i
<nPointAnz
) {
349 Point
* pPnt
=&rPoly
[i
];
352 if (i
+1<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the left
358 if (i
<nPointAnz
&& rPoly
.IsControl(i
)) { // control point to the right
362 CrookStretchXPoint(*pPnt
,pC1
,pC2
,rCenter
,rRad
,nSin
,nCos
,bVert
,rRefRect
);
368 void CrookRotatePoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
370 sal_uInt16 nPolyCount
=rPoly
.Count();
371 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyCount
; nPolyNum
++) {
372 CrookRotatePoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
376 void CrookSlantPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
)
378 sal_uInt16 nPolyCount
=rPoly
.Count();
379 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyCount
; nPolyNum
++) {
380 CrookSlantPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
);
384 void CrookStretchPoly(XPolyPolygon
& rPoly
, const Point
& rCenter
, const Point
& rRad
, bool bVert
, const Rectangle
& rRefRect
)
386 sal_uInt16 nPolyCount
=rPoly
.Count();
387 for (sal_uInt16 nPolyNum
=0; nPolyNum
<nPolyCount
; nPolyNum
++) {
388 CrookStretchPoly(rPoly
[nPolyNum
],rCenter
,rRad
,bVert
,rRefRect
);
394 long GetAngle(const Point
& rPnt
)
398 if (rPnt
.X()<0) a
=-18000;
399 } else if (rPnt
.X()==0) {
400 if (rPnt
.Y()>0) a
=-9000;
403 a
=Round((atan2((double)-rPnt
.Y(),(double)rPnt
.X())/nPi180
));
408 long NormAngle180(long a
)
410 while (a
<18000) a
+=36000;
411 while (a
>=18000) a
-=36000;
415 long NormAngle360(long a
)
417 while (a
<0) a
+=36000;
418 while (a
>=36000) a
-=36000;
422 sal_uInt16
GetAngleSector(long nAngle
)
424 while (nAngle
<0) nAngle
+=36000;
425 while (nAngle
>=36000) nAngle
-=36000;
426 if (nAngle
< 9000) return 0;
427 if (nAngle
<18000) return 1;
428 if (nAngle
<27000) return 2;
432 long GetLen(const Point
& rPnt
)
434 long x
=std::abs(rPnt
.X());
435 long y
=std::abs(rPnt
.Y());
436 if (x
+y
<0x8000) { // because 7FFF * 7FFF * 2 = 7FFE0002
440 x
=Round(sqrt((double)x
));
450 return 0x7FFFFFFF; // we can't go any further, for fear of an overrun!
459 void GeoStat::RecalcSinCos()
461 if (nRotationAngle
==0) {
465 double a
=nRotationAngle
*nPi180
;
471 void GeoStat::RecalcTan()
473 if (nShearAngle
==0) {
476 double a
=nShearAngle
*nPi180
;
483 Polygon
Rect2Poly(const Rectangle
& rRect
, const GeoStat
& rGeo
)
486 aPol
[0]=rRect
.TopLeft();
487 aPol
[1]=rRect
.TopRight();
488 aPol
[2]=rRect
.BottomRight();
489 aPol
[3]=rRect
.BottomLeft();
490 aPol
[4]=rRect
.TopLeft();
491 if (rGeo
.nShearAngle
!=0) ShearPoly(aPol
,rRect
.TopLeft(),rGeo
.nTan
);
492 if (rGeo
.nRotationAngle
!=0) RotatePoly(aPol
,rRect
.TopLeft(),rGeo
.nSin
,rGeo
.nCos
);
496 void Poly2Rect(const Polygon
& rPol
, Rectangle
& rRect
, GeoStat
& rGeo
)
498 rGeo
.nRotationAngle
=GetAngle(rPol
[1]-rPol
[0]);
499 rGeo
.nRotationAngle
=NormAngle360(rGeo
.nRotationAngle
);
500 // rotation successful
503 Point
aPt1(rPol
[1]-rPol
[0]);
504 if (rGeo
.nRotationAngle
!=0) RotatePoint(aPt1
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin to reverse rotation
508 Point
aPt3(rPol
[3]-rPol
[0]);
509 if (rGeo
.nRotationAngle
!=0) RotatePoint(aPt3
,Point(0,0),-rGeo
.nSin
,rGeo
.nCos
); // -Sin to reverse rotation
513 long nShW
=GetAngle(aPt3
);
514 nShW
-=27000; // ShearWink is measured against a vertical line
515 nShW
=-nShW
; // Negieren, denn '+' ist Rechtskursivierung
517 bool bMirr
=aPt3
.Y()<0;
518 if (bMirr
) { // "exchange of points" when mirroring
523 nShW
=NormAngle180(nShW
);
524 if (nShW
<-9000 || nShW
>9000) {
525 nShW
=NormAngle180(nShW
+18000);
527 if (nShW
<-SDRMAXSHEAR
) nShW
=-SDRMAXSHEAR
; // limit ShearWinkel (shear angle) to +/- 89.00 deg
528 if (nShW
>SDRMAXSHEAR
) nShW
=SDRMAXSHEAR
;
529 rGeo
.nShearAngle
=nShW
;
534 rRect
=Rectangle(aPt0
,aRU
);
539 void OrthoDistance8(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
)
541 long dx
=rPt
.X()-rPt0
.X();
542 long dy
=rPt
.Y()-rPt0
.Y();
543 long dxa
=std::abs(dx
);
544 long dya
=std::abs(dy
);
545 if (dx
==0 || dy
==0 || dxa
==dya
) return;
546 if (dxa
>=dya
*2) { rPt
.Y()=rPt0
.Y(); return; }
547 if (dya
>=dxa
*2) { rPt
.X()=rPt0
.X(); return; }
548 if ((dxa
<dya
) != bBigOrtho
) {
549 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
551 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
555 void OrthoDistance4(const Point
& rPt0
, Point
& rPt
, bool bBigOrtho
)
557 long dx
=rPt
.X()-rPt0
.X();
558 long dy
=rPt
.Y()-rPt0
.Y();
559 long dxa
=std::abs(dx
);
560 long dya
=std::abs(dy
);
561 if ((dxa
<dya
) != bBigOrtho
) {
562 rPt
.Y()=rPt0
.Y()+(dxa
* (dy
>=0 ? 1 : -1) );
564 rPt
.X()=rPt0
.X()+(dya
* (dx
>=0 ? 1 : -1) );
570 long BigMulDiv(long nVal
, long nMul
, long nDiv
)
574 if (aVal
.IsNeg()!=(nDiv
<0)) {
575 aVal
-=nDiv
/2; // to round correctly
577 aVal
+=nDiv
/2; // to round correctly
587 void Kuerzen(Fraction
& rF
, unsigned nDigits
)
589 sal_Int32 nMul
=rF
.GetNumerator();
590 sal_Int32 nDiv
=rF
.GetDenominator();
592 if (nMul
<0) { nMul
=-nMul
; bNeg
=!bNeg
; }
593 if (nDiv
<0) { nDiv
=-nDiv
; bNeg
=!bNeg
; }
594 if (nMul
==0 || nDiv
==0) return;
596 a
=sal_uInt32(nMul
); unsigned nMulZ
=0; // count leading zeros
597 while (a
<0x00800000) { nMulZ
+=8; a
<<=8; }
598 while (a
<0x80000000) { nMulZ
++; a
<<=1; }
599 a
=sal_uInt32(nDiv
); unsigned nDivZ
=0; // count leading zeros
600 while (a
<0x00800000) { nDivZ
+=8; a
<<=8; }
601 while (a
<0x80000000) { nDivZ
++; a
<<=1; }
602 // count the number of digits
603 int nMulDigits
=32-nMulZ
;
604 int nDivDigits
=32-nDivZ
;
605 // count how many decimal places can be removed
606 int nMulWeg
=nMulDigits
-nDigits
; if (nMulWeg
<0) nMulWeg
=0;
607 int nDivWeg
=nDivDigits
-nDigits
; if (nDivWeg
<0) nDivWeg
=0;
608 int nWeg
=std::min(nMulWeg
,nDivWeg
);
611 if (nMul
==0 || nDiv
==0) {
612 DBG_WARNING("Math error after canceling decimal places.");
615 if (bNeg
) nMul
=-nMul
;
616 rF
=Fraction(nMul
,nDiv
);
620 // How many eU units fit into a mm, respectively an inch?
621 // Or: How many mm, respectively inches, are there in an eU (and then give me the inverse)
623 FrPair
GetInchOrMM(MapUnit eU
)
626 case MAP_1000TH_INCH
: return FrPair(1000,1);
627 case MAP_100TH_INCH
: return FrPair( 100,1);
628 case MAP_10TH_INCH
: return FrPair( 10,1);
629 case MAP_INCH
: return FrPair( 1,1);
630 case MAP_POINT
: return FrPair( 72,1);
631 case MAP_TWIP
: return FrPair(1440,1);
632 case MAP_100TH_MM
: return FrPair( 100,1);
633 case MAP_10TH_MM
: return FrPair( 10,1);
634 case MAP_MM
: return FrPair( 1,1);
635 case MAP_CM
: return FrPair( 1,10);
637 ScopedVclPtrInstance
< VirtualDevice
> pVD
;
638 pVD
->SetMapMode(MapMode(MAP_100TH_MM
));
639 Point
aP(pVD
->PixelToLogic(Point(64,64))); // 64 pixels for more accuracy
640 return FrPair(6400,aP
.X(),6400,aP
.Y());
642 case MAP_APPFONT
: case MAP_SYSFONT
: {
643 ScopedVclPtrInstance
< VirtualDevice
> pVD
;
644 pVD
->SetMapMode(MapMode(eU
));
645 Point
aP(pVD
->LogicToPixel(Point(32,32))); // 32 units for more accuracy
646 pVD
->SetMapMode(MapMode(MAP_100TH_MM
));
647 aP
=pVD
->PixelToLogic(aP
);
648 return FrPair(3200,aP
.X(),3200,aP
.Y());
652 return Fraction(1,1);
655 FrPair
GetInchOrMM(FieldUnit eU
)
658 case FUNIT_INCH
: return FrPair( 1,1);
659 case FUNIT_POINT
: return FrPair( 72,1);
660 case FUNIT_TWIP
: return FrPair(1440,1);
661 case FUNIT_100TH_MM
: return FrPair( 100,1);
662 case FUNIT_MM
: return FrPair( 1,1);
663 case FUNIT_CM
: return FrPair( 1,10);
664 case FUNIT_M
: return FrPair( 1,1000);
665 case FUNIT_KM
: return FrPair( 1,1000000);
666 case FUNIT_PICA
: return FrPair( 6,1);
667 case FUNIT_FOOT
: return FrPair( 1,12);
668 case FUNIT_MILE
: return FrPair( 1,63360);
671 return Fraction(1,1);
674 // Calculate the factor that we need to convert units from eS to eD.
675 // e. g. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
677 FrPair
GetMapFactor(MapUnit eS
, MapUnit eD
)
679 if (eS
==eD
) return FrPair(1,1,1,1);
680 FrPair
aS(GetInchOrMM(eS
));
681 FrPair
aD(GetInchOrMM(eD
));
682 bool bSInch
=IsInch(eS
);
683 bool bDInch
=IsInch(eD
);
684 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
685 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
686 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
690 FrPair
GetMapFactor(FieldUnit eS
, FieldUnit eD
)
692 if (eS
==eD
) return FrPair(1,1,1,1);
693 FrPair
aS(GetInchOrMM(eS
));
694 FrPair
aD(GetInchOrMM(eD
));
695 bool bSInch
=IsInch(eS
);
696 bool bDInch
=IsInch(eD
);
697 FrPair
aRet(aD
.X()/aS
.X(),aD
.Y()/aS
.Y());
698 if (bSInch
&& !bDInch
) { aRet
.X()*=Fraction(127,5); aRet
.Y()*=Fraction(127,5); }
699 if (!bSInch
&& bDInch
) { aRet
.X()*=Fraction(5,127); aRet
.Y()*=Fraction(5,127); }
705 // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm
706 // 1 furlong = 10 chains = 7.920" = 201.168,0mm
707 // 1 chain = 4 poles = 792" = 20.116,8mm
708 // 1 pole = 5 1/2 yd = 198" = 5.029,2mm
709 // 1 yd = 3 ft = 36" = 914,4mm
710 // 1 ft = 12 " = 1" = 304,8mm
712 void GetMeterOrInch(MapUnit eMU
, short& rnKomma
, long& rnMul
, long& rnDiv
, bool& rbMetr
, bool& rbInch
)
716 bool bMetr
= false, bInch
= false;
719 case MAP_100TH_MM
: bMetr
= true; nKomma
=5; break;
720 case MAP_10TH_MM
: bMetr
= true; nKomma
=4; break;
721 case MAP_MM
: bMetr
= true; nKomma
=3; break;
722 case MAP_CM
: bMetr
= true; nKomma
=2; break;
724 case MAP_1000TH_INCH
: bInch
= true; nKomma
=3; break;
725 case MAP_100TH_INCH
: bInch
= true; nKomma
=2; break;
726 case MAP_10TH_INCH
: bInch
= true; nKomma
=1; break;
727 case MAP_INCH
: bInch
= true; nKomma
=0; break;
728 case MAP_POINT
: bInch
= true; rnDiv
=72; break; // 1Pt = 1/72"
729 case MAP_TWIP
: bInch
= true; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
731 case MAP_PIXEL
: break;
732 case MAP_SYSFONT
: break;
733 case MAP_APPFONT
: break;
734 case MAP_RELATIVE
: break;
742 void GetMeterOrInch(FieldUnit eFU
, short& rnKomma
, long& rnMul
, long& rnDiv
, bool& rbMetr
, bool& rbInch
)
746 bool bMetr
= false, bInch
= false;
748 case FUNIT_NONE
: break;
750 case FUNIT_100TH_MM
: bMetr
= true; nKomma
=5; break;
751 case FUNIT_MM
: bMetr
= true; nKomma
=3; break;
752 case FUNIT_CM
: bMetr
= true; nKomma
=2; break;
753 case FUNIT_M
: bMetr
= true; nKomma
=0; break;
754 case FUNIT_KM
: bMetr
= true; nKomma
=-3; break;
756 case FUNIT_TWIP
: bInch
= true; rnDiv
=144; nKomma
=1; break; // 1Twip = 1/1440"
757 case FUNIT_POINT
: bInch
= true; rnDiv
=72; break; // 1Pt = 1/72"
758 case FUNIT_PICA
: bInch
= true; rnDiv
=6; break; // 1Pica = 1/6" ?
759 case FUNIT_INCH
: bInch
= true; break; // 1" = 1"
760 case FUNIT_FOOT
: bInch
= true; rnMul
=12; break; // 1Ft = 12"
761 case FUNIT_MILE
: bInch
= true; rnMul
=6336; nKomma
=-1; break; // 1mile = 63360"
763 case FUNIT_CUSTOM
: break;
764 case FUNIT_PERCENT
: nKomma
=2; break;
765 // TODO: Add code to handle the following (added to remove warning)
766 case FUNIT_CHAR
: break;
767 case FUNIT_LINE
: break;
768 case FUNIT_PIXEL
: break;
769 case FUNIT_DEGREE
: break;
770 case FUNIT_SECOND
: break;
771 case FUNIT_MILLISECOND
: break;
778 void SdrFormatter::Undirty()
780 bool bSrcMetr
,bSrcInch
,bDstMetr
,bDstInch
;
781 long nMul1
,nDiv1
,nMul2
,nDiv2
;
782 short nKomma1
,nKomma2
;
783 // first: normalize to m or in
785 GetMeterOrInch(eSrcMU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
787 GetMeterOrInch(eSrcFU
,nKomma1
,nMul1
,nDiv1
,bSrcMetr
,bSrcInch
);
790 GetMeterOrInch(eDstMU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
792 GetMeterOrInch(eDstFU
,nKomma2
,nMul2
,nDiv2
,bDstMetr
,bDstInch
);
796 nKomma1
=nKomma1
-nKomma2
;
798 if (bSrcInch
&& bDstMetr
) {
802 if (bSrcMetr
&& bDstInch
) {
807 // temporary fraction for canceling
808 Fraction
aTempFract(nMul1
,nDiv1
);
809 nMul1
=aTempFract
.GetNumerator();
810 nDiv1
=aTempFract
.GetDenominator();
819 void SdrFormatter::TakeStr(long nVal
, OUString
& rStr
) const
821 OUString
aNullCode("0");
829 // we may lose some decimal places here, because of MulDiv instead of Real
831 SvtSysLocale aSysLoc
;
832 const LocaleDataWrapper
& rLoc
= aSysLoc
.GetLocaleData();
836 sal_Int16
nC(nKomma_
);
854 nVal
= BigMulDiv(nVal
, nMul_
, nDiv_
);
856 OUStringBuffer aStr
= OUString::number(nVal
);
858 if(nC
> 0 && aStr
.getLength() <= nC
)
860 // decimal separator necessary
861 sal_Int32
nCount(nC
- aStr
.getLength());
863 if(nCount
>= 0 && LocaleDataWrapper::isNumLeadingZero())
866 for(sal_Int32 i
=0; i
<nCount
; i
++)
867 aStr
.insert(0, aNullCode
);
869 // remove superfluous decimal points
870 sal_Int32
nNumDigits(LocaleDataWrapper::getNumDigits());
871 sal_Int32
nWeg(nC
- nNumDigits
);
875 // TODO: we should round here
876 aStr
.remove(aStr
.getLength() - nWeg
, nWeg
);
881 // remember everything before the decimal separator for later
882 sal_Int32
nForComma(aStr
.getLength() - nC
);
886 // insert comma char (decimal separator)
887 // remove trailing zeros
888 while(nC
> 0 && aStr
[aStr
.getLength() - 1] == aNullCode
[0])
890 aStr
.remove(aStr
.getLength() - 1, 1);
896 // do we still have decimal places?
897 sal_Unicode
cDec(rLoc
.getNumDecimalSep()[0]);
898 aStr
.insert(nForComma
, cDec
);
902 // add in thousands separator (if necessary)
905 OUString
aThoSep( rLoc
.getNumThousandSep() );
906 if ( aThoSep
.getLength() > 0 )
908 sal_Unicode
cTho( aThoSep
[0] );
909 sal_Int32
i(nForComma
- 3);
913 aStr
.insert(i
, cTho
);
920 aStr
.insert(aStr
.getLength(), aNullCode
);
922 if(bNeg
&& (aStr
.getLength() > 1 || aStr
[0] != aNullCode
[0]))
927 rStr
= aStr
.makeStringAndClear();
930 void SdrFormatter::TakeUnitStr(MapUnit eUnit
, OUString
& rStr
)
957 case MAP_1000TH_INCH
:
962 case MAP_100TH_INCH
:
1013 void SdrFormatter::TakeUnitStr(FieldUnit eUnit
, OUString
& rStr
)
1026 case FUNIT_100TH_MM
:
1096 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */