xref: /trunk/main/svx/source/svdraw/svdtrans.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include <svx/svdtrans.hxx>
32 #include <math.h>
33 #include <svx/xpoly.hxx>
34 
35 #include <vcl/virdev.hxx>
36 #include <tools/bigint.hxx>
37 #include <tools/debug.hxx>
38 #include <unotools/syslocale.hxx>
39 
40 ////////////////////////////////////////////////////////////////////////////////////////////////////
41 
42 void MoveXPoly(XPolygon& rPoly, const Size& S)
43 {
44     rPoly.Move(S.Width(),S.Height());
45 }
46 
47 void MoveXPoly(XPolyPolygon& rPoly, const Size& S)
48 {
49     rPoly.Move(S.Width(),S.Height());
50 }
51 
52 ////////////////////////////////////////////////////////////////////////////////////////////////////
53 
54 void ResizeRect(Rectangle& rRect, const Point& rRef, const Fraction& rxFact, const Fraction& ryFact, FASTBOOL bNoJustify)
55 {
56     Fraction xFact(rxFact);
57     Fraction yFact(ryFact);
58     //long nHgt=rRect.Bottom()-rRect.Top();
59 
60     {
61         if (xFact.GetDenominator()==0) {
62             long nWdt=rRect.Right()-rRect.Left();
63             if (xFact.GetNumerator()>=0) { // DivZero abfangen
64                 xFact=Fraction(xFact.GetNumerator(),1);
65                 if (nWdt==0) rRect.Right()++;
66             } else {
67                 xFact=Fraction(xFact.GetNumerator(),-1);
68                 if (nWdt==0) rRect.Left()--;
69             }
70         }
71         rRect.Left()  =rRef.X()+Round(((double)(rRect.Left()  -rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
72         rRect.Right() =rRef.X()+Round(((double)(rRect.Right() -rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
73     }
74     {
75         if (yFact.GetDenominator()==0) {
76             long nHgt=rRect.Bottom()-rRect.Top();
77             if (yFact.GetNumerator()>=0) { // DivZero abfangen
78                 yFact=Fraction(yFact.GetNumerator(),1);
79                 if (nHgt==0) rRect.Bottom()++;
80             } else {
81                 yFact=Fraction(yFact.GetNumerator(),-1);
82                 if (nHgt==0) rRect.Top()--;
83             }
84 
85             yFact=Fraction(yFact.GetNumerator(),1); // DivZero abfangen
86         }
87         rRect.Top()   =rRef.Y()+Round(((double)(rRect.Top()   -rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
88         rRect.Bottom()=rRef.Y()+Round(((double)(rRect.Bottom()-rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
89     }
90     if (!bNoJustify) rRect.Justify();
91 }
92 
93 
94 void ResizePoly(Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
95 {
96     sal_uInt16 nAnz=rPoly.GetSize();
97     for (sal_uInt16 i=0; i<nAnz; i++) {
98         ResizePoint(rPoly[i],rRef,xFact,yFact);
99     }
100 }
101 
102 void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
103 {
104     sal_uInt16 nAnz=rPoly.GetPointCount();
105     for (sal_uInt16 i=0; i<nAnz; i++) {
106         ResizePoint(rPoly[i],rRef,xFact,yFact);
107     }
108 }
109 
110 void ResizePoly(PolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
111 {
112     sal_uInt16 nAnz=rPoly.Count();
113     for (sal_uInt16 i=0; i<nAnz; i++) {
114         ResizePoly(rPoly[i],rRef,xFact,yFact);
115     }
116 }
117 
118 void ResizeXPoly(XPolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
119 {
120     sal_uInt16 nAnz=rPoly.Count();
121     for (sal_uInt16 i=0; i<nAnz; i++) {
122         ResizeXPoly(rPoly[i],rRef,xFact,yFact);
123     }
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////////////////////////
127 
128 void RotatePoly(Polygon& rPoly, const Point& rRef, double sn, double cs)
129 {
130     sal_uInt16 nAnz=rPoly.GetSize();
131     for (sal_uInt16 i=0; i<nAnz; i++) {
132         RotatePoint(rPoly[i],rRef,sn,cs);
133     }
134 }
135 
136 void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs)
137 {
138     sal_uInt16 nAnz=rPoly.GetPointCount();
139     for (sal_uInt16 i=0; i<nAnz; i++) {
140         RotatePoint(rPoly[i],rRef,sn,cs);
141     }
142 }
143 
144 void RotatePoly(PolyPolygon& rPoly, const Point& rRef, double sn, double cs)
145 {
146     sal_uInt16 nAnz=rPoly.Count();
147     for (sal_uInt16 i=0; i<nAnz; i++) {
148         RotatePoly(rPoly[i],rRef,sn,cs);
149     }
150 }
151 
152 void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs)
153 {
154     sal_uInt16 nAnz=rPoly.Count();
155     for (sal_uInt16 i=0; i<nAnz; i++) {
156         RotateXPoly(rPoly[i],rRef,sn,cs);
157     }
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////////////////////////
161 
162 void MirrorRect(Rectangle& rRect, const Point& /*rRef1*/, const Point& /*rRef2*/, FASTBOOL bNoJustify)
163 {
164     // !!! fehlende Implementation !!!
165     if (!bNoJustify) rRect.Justify();
166 }
167 
168 void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2)
169 {
170     long mx=rRef2.X()-rRef1.X();
171     long my=rRef2.Y()-rRef1.Y();
172     if (mx==0) { // Achse senkrecht
173         long dx=rRef1.X()-rPnt.X();
174         rPnt.X()+=2*dx;
175     } else if (my==0) { // Achse waagerecht
176         long dy=rRef1.Y()-rPnt.Y();
177         rPnt.Y()+=2*dy;
178     } else if (mx==my) { // Achse diagonal '\'
179         long dx1=rPnt.X()-rRef1.X();
180         long dy1=rPnt.Y()-rRef1.Y();
181         rPnt.X()=rRef1.X()+dy1;
182         rPnt.Y()=rRef1.Y()+dx1;
183     } else if (mx==-my) { // Achse diagonal '/'
184         long dx1=rPnt.X()-rRef1.X();
185         long dy1=rPnt.Y()-rRef1.Y();
186         rPnt.X()=rRef1.X()-dy1;
187         rPnt.Y()=rRef1.Y()-dx1;
188     } else { // beliebige Achse
189         // mal optimieren !!!
190         // Lot auf der Spiegelachse faellen oder so
191         long nRefWink=GetAngle(rRef2-rRef1);
192         rPnt-=rRef1;
193         long nPntWink=GetAngle(rPnt);
194         long nWink=2*(nRefWink-nPntWink);
195         double a=nWink*nPi180;
196         double nSin=sin(a);
197         double nCos=cos(a);
198         RotatePoint(rPnt,Point(),nSin,nCos);
199         rPnt+=rRef1;
200     }
201 }
202 
203 void MirrorPoly(Polygon& rPoly, const Point& rRef1, const Point& rRef2)
204 {
205     sal_uInt16 nAnz=rPoly.GetSize();
206     for (sal_uInt16 i=0; i<nAnz; i++) {
207         MirrorPoint(rPoly[i],rRef1,rRef2);
208     }
209 }
210 
211 void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2)
212 {
213     sal_uInt16 nAnz=rPoly.GetPointCount();
214     for (sal_uInt16 i=0; i<nAnz; i++) {
215         MirrorPoint(rPoly[i],rRef1,rRef2);
216     }
217 }
218 
219 void MirrorPoly(PolyPolygon& rPoly, const Point& rRef1, const Point& rRef2)
220 {
221     sal_uInt16 nAnz=rPoly.Count();
222     for (sal_uInt16 i=0; i<nAnz; i++) {
223         MirrorPoly(rPoly[i],rRef1,rRef2);
224     }
225 }
226 
227 void MirrorXPoly(XPolyPolygon& rPoly, const Point& rRef1, const Point& rRef2)
228 {
229     sal_uInt16 nAnz=rPoly.Count();
230     for (sal_uInt16 i=0; i<nAnz; i++) {
231         MirrorXPoly(rPoly[i],rRef1,rRef2);
232     }
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////////////////////////
236 
237 void ShearPoly(Polygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
238 {
239     sal_uInt16 nAnz=rPoly.GetSize();
240     for (sal_uInt16 i=0; i<nAnz; i++) {
241         ShearPoint(rPoly[i],rRef,tn,bVShear);
242     }
243 }
244 
245 void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
246 {
247     sal_uInt16 nAnz=rPoly.GetPointCount();
248     for (sal_uInt16 i=0; i<nAnz; i++) {
249         ShearPoint(rPoly[i],rRef,tn,bVShear);
250     }
251 }
252 
253 void ShearPoly(PolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
254 {
255     sal_uInt16 nAnz=rPoly.Count();
256     for (sal_uInt16 i=0; i<nAnz; i++) {
257         ShearPoly(rPoly[i],rRef,tn,bVShear);
258     }
259 }
260 
261 void ShearXPoly(XPolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
262 {
263     sal_uInt16 nAnz=rPoly.Count();
264     for (sal_uInt16 i=0; i<nAnz; i++) {
265         ShearXPoly(rPoly[i],rRef,tn,bVShear);
266     }
267 }
268 
269 ////////////////////////////////////////////////////////////////////////////////////////////////////
270 //
271 //   @@@@  @@@@@   @@@@   @@@@  @@  @@
272 //  @@  @@ @@  @@ @@  @@ @@  @@ @@  @@
273 //  @@     @@  @@ @@  @@ @@  @@ @@ @@
274 //  @@     @@@@@  @@  @@ @@  @@ @@@@
275 //  @@     @@  @@ @@  @@ @@  @@ @@ @@
276 //  @@  @@ @@  @@ @@  @@ @@  @@ @@  @@
277 //   @@@@  @@  @@  @@@@   @@@@  @@  @@
278 //
279 ////////////////////////////////////////////////////////////////////////////////////////////////////
280 
281 double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
282                          const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert)
283 {
284     FASTBOOL bC1=pC1!=NULL;
285     FASTBOOL bC2=pC2!=NULL;
286     long x0=rPnt.X();
287     long y0=rPnt.Y();
288     long cx=rCenter.X();
289     long cy=rCenter.Y();
290     double nWink=GetCrookAngle(rPnt,rCenter,rRad,bVert);
291     double sn=sin(nWink);
292     double cs=cos(nWink);
293     RotatePoint(rPnt,rCenter,sn,cs);
294     if (bC1) {
295         if (bVert) {
296             // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
297             pC1->Y()-=y0;
298             // Resize, entsprechend der Entfernung vom Zentrum
299             pC1->Y()=Round(((double)pC1->Y()) /rRad.X()*(cx-pC1->X()));
300             pC1->Y()+=cy;
301         } else {
302             // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
303             pC1->X()-=x0;
304             // Resize, entsprechend der Entfernung vom Zentrum
305             long nPntRad=cy-pC1->Y();
306             double nFact=(double)nPntRad/(double)rRad.Y();
307             pC1->X()=Round((double)pC1->X()*nFact);
308             pC1->X()+=cx;
309         }
310         RotatePoint(*pC1,rCenter,sn,cs);
311     }
312     if (bC2) {
313         if (bVert) {
314             // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
315             pC2->Y()-=y0;
316             // Resize, entsprechend der Entfernung vom Zentrum
317             pC2->Y()=Round(((double)pC2->Y()) /rRad.X()*(rCenter.X()-pC2->X()));
318             pC2->Y()+=cy;
319         } else {
320             // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
321             pC2->X()-=x0;
322             // Resize, entsprechend der Entfernung vom Zentrum
323             long nPntRad=rCenter.Y()-pC2->Y();
324             double nFact=(double)nPntRad/(double)rRad.Y();
325             pC2->X()=Round((double)pC2->X()*nFact);
326             pC2->X()+=cx;
327         }
328         RotatePoint(*pC2,rCenter,sn,cs);
329     }
330     rSin=sn;
331     rCos=cs;
332     return nWink;
333 }
334 
335 double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
336                         const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert)
337 {
338     FASTBOOL bC1=pC1!=NULL;
339     FASTBOOL bC2=pC2!=NULL;
340     long x0=rPnt.X();
341     long y0=rPnt.Y();
342     long dx1=0,dy1=0;
343     long dxC1=0,dyC1=0;
344     long dxC2=0,dyC2=0;
345     if (bVert) {
346         long nStart=rCenter.X()-rRad.X();
347         dx1=rPnt.X()-nStart;
348         rPnt.X()=nStart;
349         if (bC1) {
350             dxC1=pC1->X()-nStart;
351             pC1->X()=nStart;
352         }
353         if (bC2) {
354             dxC2=pC2->X()-nStart;
355             pC2->X()=nStart;
356         }
357     } else {
358         long nStart=rCenter.Y()-rRad.Y();
359         dy1=rPnt.Y()-nStart;
360         rPnt.Y()=nStart;
361         if (bC1) {
362             dyC1=pC1->Y()-nStart;
363             pC1->Y()=nStart;
364         }
365         if (bC2) {
366             dyC2=pC2->Y()-nStart;
367             pC2->Y()=nStart;
368         }
369     }
370     double nWink=GetCrookAngle(rPnt,rCenter,rRad,bVert);
371     double sn=sin(nWink);
372     double cs=cos(nWink);
373     RotatePoint(rPnt,rCenter,sn,cs);
374     if (bC1) { if (bVert) pC1->Y()-=y0-rCenter.Y(); else pC1->X()-=x0-rCenter.X(); RotatePoint(*pC1,rCenter,sn,cs); }
375     if (bC2) { if (bVert) pC2->Y()-=y0-rCenter.Y(); else pC2->X()-=x0-rCenter.X(); RotatePoint(*pC2,rCenter,sn,cs); }
376     if (bVert) {
377         rPnt.X()+=dx1;
378         if (bC1) pC1->X()+=dxC1;
379         if (bC2) pC2->X()+=dxC2;
380     } else {
381         rPnt.Y()+=dy1;
382         if (bC1) pC1->Y()+=dyC1;
383         if (bC2) pC2->Y()+=dyC2;
384     }
385     rSin=sn;
386     rCos=cs;
387     return nWink;
388 }
389 
390 double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
391                           const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert,
392                           const Rectangle rRefRect)
393 {
394     //FASTBOOL bC1=pC1!=NULL;
395     //FASTBOOL bC2=pC2!=NULL;
396     //long x0=rPnt.X();
397     long y0=rPnt.Y();
398     CrookSlantXPoint(rPnt,pC1,pC2,rCenter,rRad,rSin,rCos,bVert);
399     if (bVert) {
400     } else {
401         //long nBase=rCenter.Y()-rRad.Y();
402         long nTop=rRefRect.Top();
403         long nBtm=rRefRect.Bottom();
404         long nHgt=nBtm-nTop;
405         long dy=rPnt.Y()-y0;
406         //FASTBOOL bOben=rRad.Y()<0;
407         double a=((double)(y0-nTop))/nHgt;
408         a*=dy;
409         rPnt.Y()=y0+Round(a);
410     } return 0.0;
411 }
412 
413 ////////////////////////////////////////////////////////////////////////////////////////////////////
414 
415 void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
416 {
417     double nSin,nCos;
418     sal_uInt16 nPointAnz=rPoly.GetPointCount();
419     sal_uInt16 i=0;
420     while (i<nPointAnz) {
421         Point* pPnt=&rPoly[i];
422         Point* pC1=NULL;
423         Point* pC2=NULL;
424         if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links
425             pC1=pPnt;
426             i++;
427             pPnt=&rPoly[i];
428         }
429         i++;
430         if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts
431             pC2=&rPoly[i];
432             i++;
433         }
434         CrookRotateXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert);
435     }
436 }
437 
438 void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
439 {
440     double nSin,nCos;
441     sal_uInt16 nPointAnz=rPoly.GetPointCount();
442     sal_uInt16 i=0;
443     while (i<nPointAnz) {
444         Point* pPnt=&rPoly[i];
445         Point* pC1=NULL;
446         Point* pC2=NULL;
447         if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links
448             pC1=pPnt;
449             i++;
450             pPnt=&rPoly[i];
451         }
452         i++;
453         if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts
454             pC2=&rPoly[i];
455             i++;
456         }
457         CrookSlantXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert);
458     }
459 }
460 
461 void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect)
462 {
463     double nSin,nCos;
464     sal_uInt16 nPointAnz=rPoly.GetPointCount();
465     sal_uInt16 i=0;
466     while (i<nPointAnz) {
467         Point* pPnt=&rPoly[i];
468         Point* pC1=NULL;
469         Point* pC2=NULL;
470         if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links
471             pC1=pPnt;
472             i++;
473             pPnt=&rPoly[i];
474         }
475         i++;
476         if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts
477             pC2=&rPoly[i];
478             i++;
479         }
480         CrookStretchXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert,rRefRect);
481     }
482 }
483 
484 ////////////////////////////////////////////////////////////////////////////////////////////////////
485 
486 void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
487 {
488     sal_uInt16 nPolyAnz=rPoly.Count();
489     for (sal_uInt16 nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) {
490         CrookRotatePoly(rPoly[nPolyNum],rCenter,rRad,bVert);
491     }
492 }
493 
494 void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
495 {
496     sal_uInt16 nPolyAnz=rPoly.Count();
497     for (sal_uInt16 nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) {
498         CrookSlantPoly(rPoly[nPolyNum],rCenter,rRad,bVert);
499     }
500 }
501 
502 void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect)
503 {
504     sal_uInt16 nPolyAnz=rPoly.Count();
505     for (sal_uInt16 nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) {
506         CrookStretchPoly(rPoly[nPolyNum],rCenter,rRad,bVert,rRefRect);
507     }
508 }
509 
510 ////////////////////////////////////////////////////////////////////////////////////////////////////
511 
512 long GetAngle(const Point& rPnt)
513 {
514     long a=0;
515     if (rPnt.Y()==0) {
516         if (rPnt.X()<0) a=-18000;
517     } else if (rPnt.X()==0) {
518         if (rPnt.Y()>0) a=-9000;
519         else a=9000;
520     } else {
521         a=Round((atan2((double)-rPnt.Y(),(double)rPnt.X())/nPi180));
522     }
523     return a;
524 }
525 
526 long NormAngle180(long a)
527 {
528     while (a<18000) a+=36000;
529     while (a>=18000) a-=36000;
530     return a;
531 }
532 
533 long NormAngle360(long a)
534 {
535     while (a<0) a+=36000;
536     while (a>=36000) a-=36000;
537     return a;
538 }
539 
540 sal_uInt16 GetAngleSector(long nWink)
541 {
542     while (nWink<0) nWink+=36000;
543     while (nWink>=36000) nWink-=36000;
544     if (nWink< 9000) return 0;
545     if (nWink<18000) return 1;
546     if (nWink<27000) return 2;
547     return 3;
548 }
549 
550 long GetLen(const Point& rPnt)
551 {
552     long x=Abs(rPnt.X());
553     long y=Abs(rPnt.Y());
554     if (x+y<0x8000) { // weil 7FFF * 7FFF * 2 = 7FFE0002
555         x*=x;
556         y*=y;
557         x+=y;
558         x=Round(sqrt((double)x));
559         return x;
560     } else {
561         double nx=x;
562         double ny=y;
563         nx*=nx;
564         ny*=ny;
565         nx+=ny;
566         nx=sqrt(nx);
567         if (nx>0x7FFFFFFF) {
568             return 0x7FFFFFFF; // Ueberlauf, mehr is nich!
569         } else {
570             return Round(nx);
571         }
572     }
573 }
574 
575 ////////////////////////////////////////////////////////////////////////////////////////////////////
576 
577 void GeoStat::RecalcSinCos()
578 {
579     if (nDrehWink==0) {
580         nSin=0.0;
581         nCos=1.0;
582     } else {
583         double a=nDrehWink*nPi180;
584         nSin=sin(a);
585         nCos=cos(a);
586     }
587 }
588 
589 void GeoStat::RecalcTan()
590 {
591     if (nShearWink==0) {
592         nTan=0.0;
593     } else {
594         double a=nShearWink*nPi180;
595         nTan=tan(a);
596     }
597 }
598 
599 ////////////////////////////////////////////////////////////////////////////////////////////////////
600 
601 Polygon Rect2Poly(const Rectangle& rRect, const GeoStat& rGeo)
602 {
603     Polygon aPol(5);
604     aPol[0]=rRect.TopLeft();
605     aPol[1]=rRect.TopRight();
606     aPol[2]=rRect.BottomRight();
607     aPol[3]=rRect.BottomLeft();
608     aPol[4]=rRect.TopLeft();
609     if (rGeo.nShearWink!=0) ShearPoly(aPol,rRect.TopLeft(),rGeo.nTan);
610     if (rGeo.nDrehWink!=0) RotatePoly(aPol,rRect.TopLeft(),rGeo.nSin,rGeo.nCos);
611     return aPol;
612 }
613 
614 void Poly2Rect(const Polygon& rPol, Rectangle& rRect, GeoStat& rGeo)
615 {
616     rGeo.nDrehWink=GetAngle(rPol[1]-rPol[0]);
617     rGeo.nDrehWink=NormAngle360(rGeo.nDrehWink);
618     // Drehung ist damit im Kasten
619     rGeo.RecalcSinCos();
620 
621     Point aPt1(rPol[1]-rPol[0]);
622     if (rGeo.nDrehWink!=0) RotatePoint(aPt1,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin fuer Rueckdrehung
623     long nWdt=aPt1.X();
624 
625     Point aPt0(rPol[0]);
626     Point aPt3(rPol[3]-rPol[0]);
627     if (rGeo.nDrehWink!=0) RotatePoint(aPt3,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin fuer Rueckdrehung
628     long nHgt=aPt3.Y();
629 
630     if(aPt3.X())
631     {
632         // #i74358# the axes are not orthogonal, so for getting the correct height,
633         // calculate the length of aPt3
634 
635         // #i74358# this change was wrong, in the field of the old geometry stuff
636         // it is not an error. The new height always is the same as before; shear
637         // does not change object height at all. This is different from the interactions,
638         // but obviously wanted in the old versions.
639         //
640         // nHgt = static_cast< long >(sqrt(static_cast< double >(aPt3.X() * aPt3.X() + aPt3.Y() * aPt3.Y())));
641     }
642 
643     long nShW=GetAngle(aPt3);
644     nShW-=27000; // ShearWink wird zur Senkrechten gemessen
645     nShW=-nShW;  // Negieren, denn '+' ist Rechtskursivierung
646 
647     FASTBOOL bMirr=aPt3.Y()<0;
648     if (bMirr) { // "Punktetausch" bei Spiegelung
649         nHgt=-nHgt;
650         nShW+=18000;
651         aPt0=rPol[3];
652     }
653     nShW=NormAngle180(nShW);
654     if (nShW<-9000 || nShW>9000) {
655         nShW=NormAngle180(nShW+18000);
656     }
657     if (nShW<-SDRMAXSHEAR) nShW=-SDRMAXSHEAR; // ShearWinkel begrenzen auf +/- 89.00 deg
658     if (nShW>SDRMAXSHEAR)  nShW=SDRMAXSHEAR;
659     rGeo.nShearWink=nShW;
660     rGeo.RecalcTan();
661     Point aRU(aPt0);
662     aRU.X()+=nWdt;
663     aRU.Y()+=nHgt;
664     rRect=Rectangle(aPt0,aRU);
665 }
666 
667 ////////////////////////////////////////////////////////////////////////////////////////////////////
668 
669 void OrthoDistance8(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho)
670 {
671     long dx=rPt.X()-rPt0.X();
672     long dy=rPt.Y()-rPt0.Y();
673     long dxa=Abs(dx);
674     long dya=Abs(dy);
675     if (dx==0 || dy==0 || dxa==dya) return;
676     if (dxa>=dya*2) { rPt.Y()=rPt0.Y(); return; }
677     if (dya>=dxa*2) { rPt.X()=rPt0.X(); return; }
678     if ((dxa<dya) != bBigOrtho) {
679         rPt.Y()=rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) );
680     } else {
681         rPt.X()=rPt0.X()+(dya* (dx>=0 ? 1 : -1) );
682     }
683 }
684 
685 void OrthoDistance4(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho)
686 {
687     long dx=rPt.X()-rPt0.X();
688     long dy=rPt.Y()-rPt0.Y();
689     long dxa=Abs(dx);
690     long dya=Abs(dy);
691     if ((dxa<dya) != bBigOrtho) {
692         rPt.Y()=rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) );
693     } else {
694         rPt.X()=rPt0.X()+(dya* (dx>=0 ? 1 : -1) );
695     }
696 }
697 
698 ////////////////////////////////////////////////////////////////////////////////////////////////////
699 
700 long BigMulDiv(long nVal, long nMul, long nDiv)
701 {
702     BigInt aVal(nVal);
703     aVal*=nMul;
704     if (aVal.IsNeg()!=(nDiv<0)) {
705         aVal-=nDiv/2; // fuer korrektes Runden
706     } else {
707         aVal+=nDiv/2; // fuer korrektes Runden
708     }
709     if(nDiv)
710     {
711         aVal/=nDiv;
712         return long(aVal);
713     }
714     return 0x7fffffff;
715 }
716 
717 void Kuerzen(Fraction& rF, unsigned nDigits)
718 {
719     sal_Int32 nMul=rF.GetNumerator();
720     sal_Int32 nDiv=rF.GetDenominator();
721     FASTBOOL bNeg=sal_False;
722     if (nMul<0) { nMul=-nMul; bNeg=!bNeg; }
723     if (nDiv<0) { nDiv=-nDiv; bNeg=!bNeg; }
724     if (nMul==0 || nDiv==0) return;
725     sal_uInt32 a;
726     a=sal_uInt32(nMul); unsigned nMulZ=0; // Fuehrende Nullen zaehlen
727     while (a<0x00800000) { nMulZ+=8; a<<=8; }
728     while (a<0x80000000) { nMulZ++; a<<=1; }
729     a=sal_uInt32(nDiv); unsigned nDivZ=0; // Fuehrende Nullen zaehlen
730     while (a<0x00800000) { nDivZ+=8; a<<=8; }
731     while (a<0x80000000) { nDivZ++; a<<=1; }
732     // Anzahl der verwendeten Digits bestimmen
733     int nMulDigits=32-nMulZ;
734     int nDivDigits=32-nDivZ;
735     // Nun bestimmen, wieviele Stellen hinten weg koennen
736     int nMulWeg=nMulDigits-nDigits; if (nMulWeg<0) nMulWeg=0;
737     int nDivWeg=nDivDigits-nDigits; if (nDivWeg<0) nDivWeg=0;
738     int nWeg=Min(nMulWeg,nDivWeg);
739     nMul>>=nWeg;
740     nDiv>>=nWeg;
741     if (nMul==0 || nDiv==0) {
742         DBG_WARNING("Oups, beim kuerzen einer Fraction hat sich Joe verrechnet.");
743         return;
744     }
745     if (bNeg) nMul=-nMul;
746     rF=Fraction(nMul,nDiv);
747 }
748 
749 ////////////////////////////////////////////////////////////////////////////////////////////////////
750 // Wieviele eU-Einheiten passen in einen mm bzw. Inch?
751 // Oder wie gross ist ein eU in mm bzw. Inch, und davon der Kehrwert
752 
753 FrPair GetInchOrMM(MapUnit eU)
754 {
755     switch (eU) {
756         case MAP_1000TH_INCH: return FrPair(1000,1);
757         case MAP_100TH_INCH : return FrPair( 100,1);
758         case MAP_10TH_INCH  : return FrPair(  10,1);
759         case MAP_INCH       : return FrPair(   1,1);
760         case MAP_POINT      : return FrPair(  72,1);
761         case MAP_TWIP       : return FrPair(1440,1);
762         case MAP_100TH_MM   : return FrPair( 100,1);
763         case MAP_10TH_MM    : return FrPair(  10,1);
764         case MAP_MM         : return FrPair(   1,1);
765         case MAP_CM         : return FrPair(   1,10);
766         case MAP_PIXEL      : {
767             VirtualDevice aVD;
768             aVD.SetMapMode(MapMode(MAP_100TH_MM));
769             Point aP(aVD.PixelToLogic(Point(64,64))); // 64 Pixel fuer bessere Genauigkeit
770             return FrPair(6400,aP.X(),6400,aP.Y());
771         }
772         case MAP_APPFONT: case MAP_SYSFONT: {
773             VirtualDevice aVD;
774             aVD.SetMapMode(MapMode(eU));
775             Point aP(aVD.LogicToPixel(Point(32,32))); // 32 Einheiten fuer bessere Genauigkeit
776             aVD.SetMapMode(MapMode(MAP_100TH_MM));
777             aP=aVD.PixelToLogic(aP);
778             return FrPair(3200,aP.X(),3200,aP.Y());
779         }
780         default: break;
781     }
782     return Fraction(1,1);
783 }
784 
785 FrPair GetInchOrMM(FieldUnit eU)
786 {
787     switch (eU) {
788         case FUNIT_INCH       : return FrPair(   1,1);
789         case FUNIT_POINT      : return FrPair(  72,1);
790         case FUNIT_TWIP       : return FrPair(1440,1);
791         case FUNIT_100TH_MM   : return FrPair( 100,1);
792         case FUNIT_MM         : return FrPair(   1,1);
793         case FUNIT_CM         : return FrPair(   1,10);
794         case FUNIT_M          : return FrPair(   1,1000);
795         case FUNIT_KM         : return FrPair(   1,1000000);
796         case FUNIT_PICA       : return FrPair(   6,1);
797         case FUNIT_FOOT       : return FrPair(   1,12);
798         case FUNIT_MILE       : return FrPair(   1,63360);
799         default: break;
800     }
801     return Fraction(1,1);
802 }
803 
804 // Den Faktor berechnen, der anzuwenden ist um n Einheiten von eS nach
805 // eD umzurechnen. Z.B. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
806 
807 FrPair GetMapFactor(MapUnit eS, MapUnit eD)
808 {
809     if (eS==eD) return FrPair(1,1,1,1);
810     FrPair aS(GetInchOrMM(eS));
811     FrPair aD(GetInchOrMM(eD));
812     FASTBOOL bSInch=IsInch(eS);
813     FASTBOOL bDInch=IsInch(eD);
814     FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
815     if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
816     if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
817     return aRet;
818 };
819 
820 FrPair GetMapFactor(MapUnit eS, FieldUnit eD)
821 {
822     FrPair aS(GetInchOrMM(eS));
823     FrPair aD(GetInchOrMM(eD));
824     FASTBOOL bSInch=IsInch(eS);
825     FASTBOOL bDInch=IsInch(eD);
826     FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
827     if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
828     if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
829     return aRet;
830 };
831 
832 FrPair GetMapFactor(FieldUnit eS, MapUnit eD)
833 {
834     FrPair aS(GetInchOrMM(eS));
835     FrPair aD(GetInchOrMM(eD));
836     FASTBOOL bSInch=IsInch(eS);
837     FASTBOOL bDInch=IsInch(eD);
838     FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
839     if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
840     if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
841     return aRet;
842 };
843 
844 FrPair GetMapFactor(FieldUnit eS, FieldUnit eD)
845 {
846     if (eS==eD) return FrPair(1,1,1,1);
847     FrPair aS(GetInchOrMM(eS));
848     FrPair aD(GetInchOrMM(eD));
849     FASTBOOL bSInch=IsInch(eS);
850     FASTBOOL bDInch=IsInch(eD);
851     FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
852     if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
853     if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
854     return aRet;
855 };
856 
857 ////////////////////////////////////////////////////////////////////////////////////////////////////
858 
859     // 1 mile    =  8 furlong = 63.360" = 1.609.344,0mm
860     // 1 furlong = 10 chains  =  7.920" =   201.168,0mm
861     // 1 chain   =  4 poles   =    792" =    20.116,8mm
862     // 1 pole    =  5 1/2 yd  =    198" =     5.029,2mm
863     // 1 yd      =  3 ft      =     36" =       914,4mm
864     // 1 ft      = 12 "       =      1" =       304,8mm
865 
866 void GetMeterOrInch(MapUnit eMU, short& rnKomma, long& rnMul, long& rnDiv, int& rbMetr, int& rbInch)
867 {
868     rnMul=1; rnDiv=1;
869     short nKomma=0;
870     FASTBOOL bMetr=sal_False,bInch=sal_False;
871     switch (eMU) {
872         // Metrisch
873         case MAP_100TH_MM   : bMetr=sal_True; nKomma=5; break;
874         case MAP_10TH_MM    : bMetr=sal_True; nKomma=4; break;
875         case MAP_MM         : bMetr=sal_True; nKomma=3; break;
876         case MAP_CM         : bMetr=sal_True; nKomma=2; break;
877         // Inch
878         case MAP_1000TH_INCH: bInch=sal_True; nKomma=3; break;
879         case MAP_100TH_INCH : bInch=sal_True; nKomma=2; break;
880         case MAP_10TH_INCH  : bInch=sal_True; nKomma=1; break;
881         case MAP_INCH       : bInch=sal_True; nKomma=0; break;
882         case MAP_POINT      : bInch=sal_True; rnDiv=72;  break;          // 1Pt   = 1/72"
883         case MAP_TWIP       : bInch=sal_True; rnDiv=144; nKomma=1; break; // 1Twip = 1/1440"
884         // Sonstiges
885         case MAP_PIXEL      : break;
886         case MAP_SYSFONT    : break;
887         case MAP_APPFONT    : break;
888         case MAP_RELATIVE   : break;
889         default: break;
890     } // switch
891     rnKomma=nKomma;
892     rbMetr=bMetr;
893     rbInch=bInch;
894 }
895 
896 void GetMeterOrInch(FieldUnit eFU, short& rnKomma, long& rnMul, long& rnDiv, int& rbMetr, int& rbInch)
897 {
898     rnMul=1; rnDiv=1;
899     short nKomma=0;
900     FASTBOOL bMetr=sal_False,bInch=sal_False;
901     switch (eFU) {
902         case FUNIT_NONE     : break;
903         // Metrisch
904         case FUNIT_100TH_MM : bMetr=sal_True; nKomma=5; break;
905         case FUNIT_MM       : bMetr=sal_True; nKomma=3; break;
906         case FUNIT_CM       : bMetr=sal_True; nKomma=2; break;
907         case FUNIT_M        : bMetr=sal_True; nKomma=0; break;
908         case FUNIT_KM       : bMetr=sal_True; nKomma=-3; break;
909         // Inch
910         case FUNIT_TWIP     : bInch=sal_True; rnDiv=144; nKomma=1; break;  // 1Twip = 1/1440"
911         case FUNIT_POINT    : bInch=sal_True; rnDiv=72; break;   // 1Pt   = 1/72"
912         case FUNIT_PICA     : bInch=sal_True; rnDiv=6; break;    // 1Pica = 1/6"  ?
913         case FUNIT_INCH     : bInch=sal_True; break;             // 1"    = 1"
914         case FUNIT_FOOT     : bInch=sal_True; rnMul=12; break;   // 1Ft   = 12"
915         case FUNIT_MILE     : bInch=sal_True; rnMul=6336; nKomma=-1; break; // 1mile = 63360"
916         // sonstiges
917         case FUNIT_CUSTOM   : break;
918         case FUNIT_PERCENT  : nKomma=2; break;
919     } // switch
920     rnKomma=nKomma;
921     rbMetr=bMetr;
922     rbInch=bInch;
923 }
924 
925 void SdrFormatter::Undirty()
926 {
927     if (aScale.GetNumerator()==0 || aScale.GetDenominator()==0) aScale=Fraction(1,1);
928     FASTBOOL bSrcMetr,bSrcInch,bDstMetr,bDstInch;
929     long nMul1,nDiv1,nMul2,nDiv2;
930     short nKomma1,nKomma2;
931     // Zunaechst normalisieren auf m bzw. "
932     if (!bSrcFU) {
933         GetMeterOrInch(eSrcMU,nKomma1,nMul1,nDiv1,bSrcMetr,bSrcInch);
934     } else {
935         GetMeterOrInch(eSrcFU,nKomma1,nMul1,nDiv1,bSrcMetr,bSrcInch);
936     }
937     if (!bDstFU) {
938         GetMeterOrInch(eDstMU,nKomma2,nMul2,nDiv2,bDstMetr,bDstInch);
939     } else {
940         GetMeterOrInch(eDstFU,nKomma2,nMul2,nDiv2,bDstMetr,bDstInch);
941     }
942     nMul1*=nDiv2;
943     nDiv1*=nMul2;
944     nKomma1=nKomma1-nKomma2;
945 
946     if (bSrcInch && bDstMetr) {
947         nKomma1+=4;
948         nMul1*=254;
949     }
950     if (bSrcMetr && bDstInch) {
951         nKomma1-=4;
952         nDiv1*=254;
953     }
954 
955     // Temporaere Fraction zum Kuerzen
956     Fraction aTempFract(nMul1,nDiv1);
957     nMul1=aTempFract.GetNumerator();
958     nDiv1=aTempFract.GetDenominator();
959 
960     nMul_=nMul1;
961     nDiv_=nDiv1;
962     nKomma_=nKomma1;
963     bDirty=sal_False;
964 }
965 
966 
967 void SdrFormatter::TakeStr(long nVal, XubString& rStr) const
968 {
969     sal_Unicode aNullCode('0');
970 
971     if(!nVal)
972     {
973         rStr = UniString();
974         rStr += aNullCode;
975         return;
976     }
977 
978     // Hier fallen trotzdem evtl. Nachkommastellen weg, wg. MulDiv statt Real
979     sal_Bool bNeg(nVal < 0);
980     SvtSysLocale aSysLoc;
981     const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData();
982 
983     ForceUndirty();
984 
985     sal_Int16 nK(nKomma_);
986     XubString aStr;
987 
988     if(bNeg)
989         nVal = -nVal;
990 
991     while(nK <= -3)
992     {
993         nVal *= 1000;
994         nK += 3;
995     }
996 
997     while(nK <= -1)
998     {
999         nVal *= 10;
1000         nK++;
1001     }
1002 
1003     if(nMul_ != nDiv_)
1004         nVal = BigMulDiv(nVal, nMul_, nDiv_);
1005 
1006     aStr = UniString::CreateFromInt32(nVal);
1007 
1008     if(nK > 0 && aStr.Len() <= nK )
1009     {
1010         // Komma erforderlich
1011         sal_Int16 nAnz(nK - aStr.Len());
1012 
1013         if(nAnz >= 0 && rLoc.isNumLeadingZero())
1014             nAnz++;
1015 
1016         for(xub_StrLen  i=0; i<nAnz; i++)
1017             aStr.Insert(aNullCode, 0);
1018 
1019         // zuviele Nachkommastellen abhacken
1020         xub_StrLen nNumDigits(rLoc.getNumDigits());
1021         xub_StrLen nWeg(nK - nNumDigits);
1022 
1023         if(nWeg > 0)
1024         {
1025             // hier muesste eigentlich noch gerundet werden!
1026             aStr.Erase(aStr.Len() - nWeg);
1027             nK = nNumDigits;
1028         }
1029     }
1030 
1031     // Vorkommastellen fuer spaeter merken
1032     xub_StrLen nVorKomma(aStr.Len() - nK);
1033 
1034     if(nK > 0)
1035     {
1036         // KommaChar einfuegen
1037         // erstmal trailing Zeros abhacken
1038         while(nK > 0 && aStr.GetChar(aStr.Len() - 1) == aNullCode)
1039         {
1040             aStr.Erase(aStr.Len() - 1);
1041             nK--;
1042         }
1043 
1044         if(nK > 0)
1045         {
1046             // na, noch Nachkommastellen da?
1047             sal_Unicode cDec(rLoc.getNumDecimalSep().GetChar(0));
1048             aStr.Insert(cDec, nVorKomma);
1049         }
1050     }
1051 
1052     // ggf. Trennpunkte bei jedem Tausender einfuegen
1053     if( nVorKomma > 3 )
1054     {
1055         String aThoSep( rLoc.getNumThousandSep() );
1056         if ( aThoSep.Len() > 0 )
1057         {
1058             sal_Unicode cTho( aThoSep.GetChar(0) );
1059             sal_Int32 i(nVorKomma - 3);
1060 
1061             while(i > 0)
1062             {
1063                 rStr.Insert(cTho, (xub_StrLen)i);
1064                 i -= 3;
1065             }
1066         }
1067     }
1068 
1069     if(!aStr.Len())
1070         aStr += aNullCode;
1071 
1072     if(bNeg && (aStr.Len() > 1 || aStr.GetChar(0) != aNullCode))
1073     {
1074         rStr.Insert(sal_Unicode('-'), 0);
1075     }
1076 
1077     rStr = aStr;
1078 }
1079 
1080 void SdrFormatter::TakeUnitStr(MapUnit eUnit, XubString& rStr)
1081 {
1082     switch(eUnit)
1083     {
1084         // Metrisch
1085         case MAP_100TH_MM   :
1086         {
1087             sal_Char aText[] = "/100mm";
1088             rStr = UniString(aText, sizeof(aText-1));
1089             break;
1090         }
1091         case MAP_10TH_MM    :
1092         {
1093             sal_Char aText[] = "/10mm";
1094             rStr = UniString(aText, sizeof(aText-1));
1095             break;
1096         }
1097         case MAP_MM         :
1098         {
1099             sal_Char aText[] = "mm";
1100             rStr = UniString(aText, sizeof(aText-1));
1101             break;
1102         }
1103         case MAP_CM         :
1104         {
1105             sal_Char aText[] = "cm";
1106             rStr = UniString(aText, sizeof(aText-1));
1107             break;
1108         }
1109 
1110         // Inch
1111         case MAP_1000TH_INCH:
1112         {
1113             sal_Char aText[] = "/1000\"";
1114             rStr = UniString(aText, sizeof(aText-1));
1115             break;
1116         }
1117         case MAP_100TH_INCH :
1118         {
1119             sal_Char aText[] = "/100\"";
1120             rStr = UniString(aText, sizeof(aText-1));
1121             break;
1122         }
1123         case MAP_10TH_INCH  :
1124         {
1125             sal_Char aText[] = "/10\"";
1126             rStr = UniString(aText, sizeof(aText-1));
1127             break;
1128         }
1129         case MAP_INCH       :
1130         {
1131             rStr = UniString();
1132             rStr += sal_Unicode('"');
1133             break;
1134         }
1135         case MAP_POINT      :
1136         {
1137             sal_Char aText[] = "pt";
1138             rStr = UniString(aText, sizeof(aText-1));
1139             break;
1140         }
1141         case MAP_TWIP       :
1142         {
1143             sal_Char aText[] = "twip";
1144             rStr = UniString(aText, sizeof(aText-1));
1145             break;
1146         }
1147 
1148         // Sonstiges
1149         case MAP_PIXEL      :
1150         {
1151             sal_Char aText[] = "pixel";
1152             rStr = UniString(aText, sizeof(aText-1));
1153             break;
1154         }
1155         case MAP_SYSFONT    :
1156         {
1157             sal_Char aText[] = "sysfont";
1158             rStr = UniString(aText, sizeof(aText-1));
1159             break;
1160         }
1161         case MAP_APPFONT    :
1162         {
1163             sal_Char aText[] = "appfont";
1164             rStr = UniString(aText, sizeof(aText-1));
1165             break;
1166         }
1167         case MAP_RELATIVE   :
1168         {
1169             rStr = UniString();
1170             rStr += sal_Unicode('%');
1171             break;
1172         }
1173         default: break;
1174     }
1175 }
1176 
1177 void SdrFormatter::TakeUnitStr(FieldUnit eUnit, XubString& rStr)
1178 {
1179     switch(eUnit)
1180     {
1181         default             :
1182         case FUNIT_NONE     :
1183         case FUNIT_CUSTOM   :
1184         {
1185             rStr = UniString();
1186             break;
1187         }
1188 
1189         // Metrisch
1190         case FUNIT_100TH_MM:
1191         {
1192             sal_Char aText[] = "/100mm";
1193             rStr = UniString(aText, sizeof(aText-1));
1194             break;
1195         }
1196         case FUNIT_MM     :
1197         {
1198             sal_Char aText[] = "mm";
1199             rStr = UniString(aText, sizeof(aText-1));
1200             break;
1201         }
1202         case FUNIT_CM     :
1203         {
1204             sal_Char aText[] = "cm";
1205             rStr = UniString(aText, sizeof(aText-1));
1206             break;
1207         }
1208         case FUNIT_M      :
1209         {
1210             rStr = UniString();
1211             rStr += sal_Unicode('m');
1212             break;
1213         }
1214         case FUNIT_KM     :
1215         {
1216             sal_Char aText[] = "km";
1217             rStr = UniString(aText, sizeof(aText-1));
1218             break;
1219         }
1220 
1221         // Inch
1222         case FUNIT_TWIP   :
1223         {
1224             sal_Char aText[] = "twip";
1225             rStr = UniString(aText, sizeof(aText-1));
1226             break;
1227         }
1228         case FUNIT_POINT  :
1229         {
1230             sal_Char aText[] = "pt";
1231             rStr = UniString(aText, sizeof(aText-1));
1232             break;
1233         }
1234         case FUNIT_PICA   :
1235         {
1236             sal_Char aText[] = "pica";
1237             rStr = UniString(aText, sizeof(aText-1));
1238             break;
1239         }
1240         case FUNIT_INCH   :
1241         {
1242             rStr = UniString();
1243             rStr += sal_Unicode('"');
1244             break;
1245         }
1246         case FUNIT_FOOT   :
1247         {
1248             sal_Char aText[] = "ft";
1249             rStr = UniString(aText, sizeof(aText-1));
1250             break;
1251         }
1252         case FUNIT_MILE   :
1253         {
1254             sal_Char aText[] = "mile(s)";
1255             rStr = UniString(aText, sizeof(aText-1));
1256             break;
1257         }
1258 
1259         // sonstiges
1260         case FUNIT_PERCENT:
1261         {
1262             rStr = UniString();
1263             rStr += sal_Unicode('%');
1264             break;
1265         }
1266     }
1267 }
1268 
1269 ////////////////////////////////////////////////////////////////////////////////////////////////////
1270 
1271 
1272