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