Update ooo320-m1
[ooovba.git] / svx / source / svdraw / svdtrans.cxx
blob3d8285b895a2c5119508b15f0e150a9a8a1664d3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdtrans.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <svx/svdtrans.hxx>
35 #include <math.h>
36 #include <svx/xpoly.hxx>
38 #include <vcl/virdev.hxx>
39 #include <tools/bigint.hxx>
40 #include <tools/debug.hxx>
41 #include <svtools/syslocale.hxx>
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
45 void MoveXPoly(XPolygon& rPoly, const Size& S)
47 rPoly.Move(S.Width(),S.Height());
50 void MoveXPoly(XPolyPolygon& rPoly, const Size& S)
52 rPoly.Move(S.Width(),S.Height());
55 ////////////////////////////////////////////////////////////////////////////////////////////////////
57 void ResizeRect(Rectangle& rRect, const Point& rRef, const Fraction& rxFact, const Fraction& ryFact, FASTBOOL bNoJustify)
59 Fraction xFact(rxFact);
60 Fraction yFact(ryFact);
61 //long nHgt=rRect.Bottom()-rRect.Top();
64 if (xFact.GetDenominator()==0) {
65 long nWdt=rRect.Right()-rRect.Left();
66 if (xFact.GetNumerator()>=0) { // DivZero abfangen
67 xFact=Fraction(xFact.GetNumerator(),1);
68 if (nWdt==0) rRect.Right()++;
69 } else {
70 xFact=Fraction(xFact.GetNumerator(),-1);
71 if (nWdt==0) rRect.Left()--;
74 rRect.Left() =rRef.X()+Round(((double)(rRect.Left() -rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
75 rRect.Right() =rRef.X()+Round(((double)(rRect.Right() -rRef.X())*xFact.GetNumerator())/xFact.GetDenominator());
78 if (yFact.GetDenominator()==0) {
79 long nHgt=rRect.Bottom()-rRect.Top();
80 if (yFact.GetNumerator()>=0) { // DivZero abfangen
81 yFact=Fraction(yFact.GetNumerator(),1);
82 if (nHgt==0) rRect.Bottom()++;
83 } else {
84 yFact=Fraction(yFact.GetNumerator(),-1);
85 if (nHgt==0) rRect.Top()--;
88 yFact=Fraction(yFact.GetNumerator(),1); // DivZero abfangen
90 rRect.Top() =rRef.Y()+Round(((double)(rRect.Top() -rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
91 rRect.Bottom()=rRef.Y()+Round(((double)(rRect.Bottom()-rRef.Y())*yFact.GetNumerator())/yFact.GetDenominator());
93 if (!bNoJustify) rRect.Justify();
97 void ResizePoly(Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
99 USHORT nAnz=rPoly.GetSize();
100 for (USHORT i=0; i<nAnz; i++) {
101 ResizePoint(rPoly[i],rRef,xFact,yFact);
105 void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
107 USHORT nAnz=rPoly.GetPointCount();
108 for (USHORT i=0; i<nAnz; i++) {
109 ResizePoint(rPoly[i],rRef,xFact,yFact);
113 void ResizePoly(PolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
115 USHORT nAnz=rPoly.Count();
116 for (USHORT i=0; i<nAnz; i++) {
117 ResizePoly(rPoly[i],rRef,xFact,yFact);
121 void ResizeXPoly(XPolyPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
123 USHORT nAnz=rPoly.Count();
124 for (USHORT i=0; i<nAnz; i++) {
125 ResizeXPoly(rPoly[i],rRef,xFact,yFact);
129 ////////////////////////////////////////////////////////////////////////////////////////////////////
131 void RotatePoly(Polygon& rPoly, const Point& rRef, double sn, double cs)
133 USHORT nAnz=rPoly.GetSize();
134 for (USHORT i=0; i<nAnz; i++) {
135 RotatePoint(rPoly[i],rRef,sn,cs);
139 void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs)
141 USHORT nAnz=rPoly.GetPointCount();
142 for (USHORT i=0; i<nAnz; i++) {
143 RotatePoint(rPoly[i],rRef,sn,cs);
147 void RotatePoly(PolyPolygon& rPoly, const Point& rRef, double sn, double cs)
149 USHORT nAnz=rPoly.Count();
150 for (USHORT i=0; i<nAnz; i++) {
151 RotatePoly(rPoly[i],rRef,sn,cs);
155 void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs)
157 USHORT nAnz=rPoly.Count();
158 for (USHORT i=0; i<nAnz; i++) {
159 RotateXPoly(rPoly[i],rRef,sn,cs);
163 ////////////////////////////////////////////////////////////////////////////////////////////////////
165 void MirrorRect(Rectangle& rRect, const Point& /*rRef1*/, const Point& /*rRef2*/, FASTBOOL bNoJustify)
167 // !!! fehlende Implementation !!!
168 if (!bNoJustify) rRect.Justify();
171 void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2)
173 long mx=rRef2.X()-rRef1.X();
174 long my=rRef2.Y()-rRef1.Y();
175 if (mx==0) { // Achse senkrecht
176 long dx=rRef1.X()-rPnt.X();
177 rPnt.X()+=2*dx;
178 } else if (my==0) { // Achse waagerecht
179 long dy=rRef1.Y()-rPnt.Y();
180 rPnt.Y()+=2*dy;
181 } else if (mx==my) { // Achse diagonal '\'
182 long dx1=rPnt.X()-rRef1.X();
183 long dy1=rPnt.Y()-rRef1.Y();
184 rPnt.X()=rRef1.X()+dy1;
185 rPnt.Y()=rRef1.Y()+dx1;
186 } else if (mx==-my) { // Achse diagonal '/'
187 long dx1=rPnt.X()-rRef1.X();
188 long dy1=rPnt.Y()-rRef1.Y();
189 rPnt.X()=rRef1.X()-dy1;
190 rPnt.Y()=rRef1.Y()-dx1;
191 } else { // beliebige Achse
192 // mal optimieren !!!
193 // Lot auf der Spiegelachse faellen oder so
194 long nRefWink=GetAngle(rRef2-rRef1);
195 rPnt-=rRef1;
196 long nPntWink=GetAngle(rPnt);
197 long nWink=2*(nRefWink-nPntWink);
198 double a=nWink*nPi180;
199 double nSin=sin(a);
200 double nCos=cos(a);
201 RotatePoint(rPnt,Point(),nSin,nCos);
202 rPnt+=rRef1;
206 void MirrorPoly(Polygon& rPoly, const Point& rRef1, const Point& rRef2)
208 USHORT nAnz=rPoly.GetSize();
209 for (USHORT i=0; i<nAnz; i++) {
210 MirrorPoint(rPoly[i],rRef1,rRef2);
214 void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2)
216 USHORT nAnz=rPoly.GetPointCount();
217 for (USHORT i=0; i<nAnz; i++) {
218 MirrorPoint(rPoly[i],rRef1,rRef2);
222 void MirrorPoly(PolyPolygon& rPoly, const Point& rRef1, const Point& rRef2)
224 USHORT nAnz=rPoly.Count();
225 for (USHORT i=0; i<nAnz; i++) {
226 MirrorPoly(rPoly[i],rRef1,rRef2);
230 void MirrorXPoly(XPolyPolygon& rPoly, const Point& rRef1, const Point& rRef2)
232 USHORT nAnz=rPoly.Count();
233 for (USHORT i=0; i<nAnz; i++) {
234 MirrorXPoly(rPoly[i],rRef1,rRef2);
238 ////////////////////////////////////////////////////////////////////////////////////////////////////
240 void ShearPoly(Polygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
242 USHORT nAnz=rPoly.GetSize();
243 for (USHORT i=0; i<nAnz; i++) {
244 ShearPoint(rPoly[i],rRef,tn,bVShear);
248 void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
250 USHORT nAnz=rPoly.GetPointCount();
251 for (USHORT i=0; i<nAnz; i++) {
252 ShearPoint(rPoly[i],rRef,tn,bVShear);
256 void ShearPoly(PolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
258 USHORT nAnz=rPoly.Count();
259 for (USHORT i=0; i<nAnz; i++) {
260 ShearPoly(rPoly[i],rRef,tn,bVShear);
264 void ShearXPoly(XPolyPolygon& rPoly, const Point& rRef, double tn, FASTBOOL bVShear)
266 USHORT nAnz=rPoly.Count();
267 for (USHORT i=0; i<nAnz; i++) {
268 ShearXPoly(rPoly[i],rRef,tn,bVShear);
272 ////////////////////////////////////////////////////////////////////////////////////////////////////
274 // @@@@ @@@@@ @@@@ @@@@ @@ @@
275 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
276 // @@ @@ @@ @@ @@ @@ @@ @@ @@
277 // @@ @@@@@ @@ @@ @@ @@ @@@@
278 // @@ @@ @@ @@ @@ @@ @@ @@ @@
279 // @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
280 // @@@@ @@ @@ @@@@ @@@@ @@ @@
282 ////////////////////////////////////////////////////////////////////////////////////////////////////
284 double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
285 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert)
287 FASTBOOL bC1=pC1!=NULL;
288 FASTBOOL bC2=pC2!=NULL;
289 long x0=rPnt.X();
290 long y0=rPnt.Y();
291 long cx=rCenter.X();
292 long cy=rCenter.Y();
293 double nWink=GetCrookAngle(rPnt,rCenter,rRad,bVert);
294 double sn=sin(nWink);
295 double cs=cos(nWink);
296 RotatePoint(rPnt,rCenter,sn,cs);
297 if (bC1) {
298 if (bVert) {
299 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
300 pC1->Y()-=y0;
301 // Resize, entsprechend der Entfernung vom Zentrum
302 pC1->Y()=Round(((double)pC1->Y()) /rRad.X()*(cx-pC1->X()));
303 pC1->Y()+=cy;
304 } else {
305 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
306 pC1->X()-=x0;
307 // Resize, entsprechend der Entfernung vom Zentrum
308 long nPntRad=cy-pC1->Y();
309 double nFact=(double)nPntRad/(double)rRad.Y();
310 pC1->X()=Round((double)pC1->X()*nFact);
311 pC1->X()+=cx;
313 RotatePoint(*pC1,rCenter,sn,cs);
315 if (bC2) {
316 if (bVert) {
317 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
318 pC2->Y()-=y0;
319 // Resize, entsprechend der Entfernung vom Zentrum
320 pC2->Y()=Round(((double)pC2->Y()) /rRad.X()*(rCenter.X()-pC2->X()));
321 pC2->Y()+=cy;
322 } else {
323 // Richtung Zentrum verschieben, als Ausgangsposition fuer Rotate
324 pC2->X()-=x0;
325 // Resize, entsprechend der Entfernung vom Zentrum
326 long nPntRad=rCenter.Y()-pC2->Y();
327 double nFact=(double)nPntRad/(double)rRad.Y();
328 pC2->X()=Round((double)pC2->X()*nFact);
329 pC2->X()+=cx;
331 RotatePoint(*pC2,rCenter,sn,cs);
333 rSin=sn;
334 rCos=cs;
335 return nWink;
338 double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
339 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert)
341 FASTBOOL bC1=pC1!=NULL;
342 FASTBOOL bC2=pC2!=NULL;
343 long x0=rPnt.X();
344 long y0=rPnt.Y();
345 long dx1=0,dy1=0;
346 long dxC1=0,dyC1=0;
347 long dxC2=0,dyC2=0;
348 if (bVert) {
349 long nStart=rCenter.X()-rRad.X();
350 dx1=rPnt.X()-nStart;
351 rPnt.X()=nStart;
352 if (bC1) {
353 dxC1=pC1->X()-nStart;
354 pC1->X()=nStart;
356 if (bC2) {
357 dxC2=pC2->X()-nStart;
358 pC2->X()=nStart;
360 } else {
361 long nStart=rCenter.Y()-rRad.Y();
362 dy1=rPnt.Y()-nStart;
363 rPnt.Y()=nStart;
364 if (bC1) {
365 dyC1=pC1->Y()-nStart;
366 pC1->Y()=nStart;
368 if (bC2) {
369 dyC2=pC2->Y()-nStart;
370 pC2->Y()=nStart;
373 double nWink=GetCrookAngle(rPnt,rCenter,rRad,bVert);
374 double sn=sin(nWink);
375 double cs=cos(nWink);
376 RotatePoint(rPnt,rCenter,sn,cs);
377 if (bC1) { if (bVert) pC1->Y()-=y0-rCenter.Y(); else pC1->X()-=x0-rCenter.X(); RotatePoint(*pC1,rCenter,sn,cs); }
378 if (bC2) { if (bVert) pC2->Y()-=y0-rCenter.Y(); else pC2->X()-=x0-rCenter.X(); RotatePoint(*pC2,rCenter,sn,cs); }
379 if (bVert) {
380 rPnt.X()+=dx1;
381 if (bC1) pC1->X()+=dxC1;
382 if (bC2) pC2->X()+=dxC2;
383 } else {
384 rPnt.Y()+=dy1;
385 if (bC1) pC1->Y()+=dyC1;
386 if (bC2) pC2->Y()+=dyC2;
388 rSin=sn;
389 rCos=cs;
390 return nWink;
393 double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
394 const Point& rRad, double& rSin, double& rCos, FASTBOOL bVert,
395 const Rectangle rRefRect)
397 //FASTBOOL bC1=pC1!=NULL;
398 //FASTBOOL bC2=pC2!=NULL;
399 //long x0=rPnt.X();
400 long y0=rPnt.Y();
401 CrookSlantXPoint(rPnt,pC1,pC2,rCenter,rRad,rSin,rCos,bVert);
402 if (bVert) {
403 } else {
404 //long nBase=rCenter.Y()-rRad.Y();
405 long nTop=rRefRect.Top();
406 long nBtm=rRefRect.Bottom();
407 long nHgt=nBtm-nTop;
408 long dy=rPnt.Y()-y0;
409 //FASTBOOL bOben=rRad.Y()<0;
410 double a=((double)(y0-nTop))/nHgt;
411 a*=dy;
412 rPnt.Y()=y0+Round(a);
413 } return 0.0;
416 ////////////////////////////////////////////////////////////////////////////////////////////////////
418 void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
420 double nSin,nCos;
421 USHORT nPointAnz=rPoly.GetPointCount();
422 USHORT i=0;
423 while (i<nPointAnz) {
424 Point* pPnt=&rPoly[i];
425 Point* pC1=NULL;
426 Point* pC2=NULL;
427 if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links
428 pC1=pPnt;
429 i++;
430 pPnt=&rPoly[i];
432 i++;
433 if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts
434 pC2=&rPoly[i];
435 i++;
437 CrookRotateXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert);
441 void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
443 double nSin,nCos;
444 USHORT nPointAnz=rPoly.GetPointCount();
445 USHORT i=0;
446 while (i<nPointAnz) {
447 Point* pPnt=&rPoly[i];
448 Point* pC1=NULL;
449 Point* pC2=NULL;
450 if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links
451 pC1=pPnt;
452 i++;
453 pPnt=&rPoly[i];
455 i++;
456 if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts
457 pC2=&rPoly[i];
458 i++;
460 CrookSlantXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert);
464 void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect)
466 double nSin,nCos;
467 USHORT nPointAnz=rPoly.GetPointCount();
468 USHORT i=0;
469 while (i<nPointAnz) {
470 Point* pPnt=&rPoly[i];
471 Point* pC1=NULL;
472 Point* pC2=NULL;
473 if (i+1<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt links
474 pC1=pPnt;
475 i++;
476 pPnt=&rPoly[i];
478 i++;
479 if (i<nPointAnz && rPoly.IsControl(i)) { // Kontrollpunkt rechts
480 pC2=&rPoly[i];
481 i++;
483 CrookStretchXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert,rRefRect);
487 ////////////////////////////////////////////////////////////////////////////////////////////////////
489 void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
491 USHORT nPolyAnz=rPoly.Count();
492 for (USHORT nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) {
493 CrookRotatePoly(rPoly[nPolyNum],rCenter,rRad,bVert);
497 void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert)
499 USHORT nPolyAnz=rPoly.Count();
500 for (USHORT nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) {
501 CrookSlantPoly(rPoly[nPolyNum],rCenter,rRad,bVert);
505 void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, FASTBOOL bVert, const Rectangle rRefRect)
507 USHORT nPolyAnz=rPoly.Count();
508 for (USHORT nPolyNum=0; nPolyNum<nPolyAnz; nPolyNum++) {
509 CrookStretchPoly(rPoly[nPolyNum],rCenter,rRad,bVert,rRefRect);
513 ////////////////////////////////////////////////////////////////////////////////////////////////////
515 long GetAngle(const Point& rPnt)
517 long a=0;
518 if (rPnt.Y()==0) {
519 if (rPnt.X()<0) a=-18000;
520 } else if (rPnt.X()==0) {
521 if (rPnt.Y()>0) a=-9000;
522 else a=9000;
523 } else {
524 a=Round((atan2((double)-rPnt.Y(),(double)rPnt.X())/nPi180));
526 return a;
529 long NormAngle180(long a)
531 while (a<18000) a+=36000;
532 while (a>=18000) a-=36000;
533 return a;
536 long NormAngle360(long a)
538 while (a<0) a+=36000;
539 while (a>=36000) a-=36000;
540 return a;
543 USHORT GetAngleSector(long nWink)
545 while (nWink<0) nWink+=36000;
546 while (nWink>=36000) nWink-=36000;
547 if (nWink< 9000) return 0;
548 if (nWink<18000) return 1;
549 if (nWink<27000) return 2;
550 return 3;
553 long GetLen(const Point& rPnt)
555 long x=Abs(rPnt.X());
556 long y=Abs(rPnt.Y());
557 if (x+y<0x8000) { // weil 7FFF * 7FFF * 2 = 7FFE0002
558 x*=x;
559 y*=y;
560 x+=y;
561 x=Round(sqrt((double)x));
562 return x;
563 } else {
564 double nx=x;
565 double ny=y;
566 nx*=nx;
567 ny*=ny;
568 nx+=ny;
569 nx=sqrt(nx);
570 if (nx>0x7FFFFFFF) {
571 return 0x7FFFFFFF; // Ueberlauf, mehr is nich!
572 } else {
573 return Round(nx);
578 ////////////////////////////////////////////////////////////////////////////////////////////////////
580 void GeoStat::RecalcSinCos()
582 if (nDrehWink==0) {
583 nSin=0.0;
584 nCos=1.0;
585 } else {
586 double a=nDrehWink*nPi180;
587 nSin=sin(a);
588 nCos=cos(a);
592 void GeoStat::RecalcTan()
594 if (nShearWink==0) {
595 nTan=0.0;
596 } else {
597 double a=nShearWink*nPi180;
598 nTan=tan(a);
602 ////////////////////////////////////////////////////////////////////////////////////////////////////
604 Polygon Rect2Poly(const Rectangle& rRect, const GeoStat& rGeo)
606 Polygon aPol(5);
607 aPol[0]=rRect.TopLeft();
608 aPol[1]=rRect.TopRight();
609 aPol[2]=rRect.BottomRight();
610 aPol[3]=rRect.BottomLeft();
611 aPol[4]=rRect.TopLeft();
612 if (rGeo.nShearWink!=0) ShearPoly(aPol,rRect.TopLeft(),rGeo.nTan);
613 if (rGeo.nDrehWink!=0) RotatePoly(aPol,rRect.TopLeft(),rGeo.nSin,rGeo.nCos);
614 return aPol;
617 void Poly2Rect(const Polygon& rPol, Rectangle& rRect, GeoStat& rGeo)
619 rGeo.nDrehWink=GetAngle(rPol[1]-rPol[0]);
620 rGeo.nDrehWink=NormAngle360(rGeo.nDrehWink);
621 // Drehung ist damit im Kasten
622 rGeo.RecalcSinCos();
624 Point aPt1(rPol[1]-rPol[0]);
625 if (rGeo.nDrehWink!=0) RotatePoint(aPt1,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin fuer Rueckdrehung
626 long nWdt=aPt1.X();
628 Point aPt0(rPol[0]);
629 Point aPt3(rPol[3]-rPol[0]);
630 if (rGeo.nDrehWink!=0) RotatePoint(aPt3,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin fuer Rueckdrehung
631 long nHgt=aPt3.Y();
633 if(aPt3.X())
635 // #i74358# the axes are not orthogonal, so for getting the correct height,
636 // calculate the length of aPt3
638 // #i74358# this change was wrong, in the field of the old geometry stuff
639 // it is not an error. The new height always is the same as before; shear
640 // does not change object height at all. This is different from the interactions,
641 // but obviously wanted in the old versions.
643 // nHgt = static_cast< long >(sqrt(static_cast< double >(aPt3.X() * aPt3.X() + aPt3.Y() * aPt3.Y())));
646 long nShW=GetAngle(aPt3);
647 nShW-=27000; // ShearWink wird zur Senkrechten gemessen
648 nShW=-nShW; // Negieren, denn '+' ist Rechtskursivierung
650 FASTBOOL bMirr=aPt3.Y()<0;
651 if (bMirr) { // "Punktetausch" bei Spiegelung
652 nHgt=-nHgt;
653 nShW+=18000;
654 aPt0=rPol[3];
656 nShW=NormAngle180(nShW);
657 if (nShW<-9000 || nShW>9000) {
658 nShW=NormAngle180(nShW+18000);
660 if (nShW<-SDRMAXSHEAR) nShW=-SDRMAXSHEAR; // ShearWinkel begrenzen auf +/- 89.00 deg
661 if (nShW>SDRMAXSHEAR) nShW=SDRMAXSHEAR;
662 rGeo.nShearWink=nShW;
663 rGeo.RecalcTan();
664 Point aRU(aPt0);
665 aRU.X()+=nWdt;
666 aRU.Y()+=nHgt;
667 rRect=Rectangle(aPt0,aRU);
670 ////////////////////////////////////////////////////////////////////////////////////////////////////
672 void OrthoDistance8(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho)
674 long dx=rPt.X()-rPt0.X();
675 long dy=rPt.Y()-rPt0.Y();
676 long dxa=Abs(dx);
677 long dya=Abs(dy);
678 if (dx==0 || dy==0 || dxa==dya) return;
679 if (dxa>=dya*2) { rPt.Y()=rPt0.Y(); return; }
680 if (dya>=dxa*2) { rPt.X()=rPt0.X(); return; }
681 if ((dxa<dya) != bBigOrtho) {
682 rPt.Y()=rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) );
683 } else {
684 rPt.X()=rPt0.X()+(dya* (dx>=0 ? 1 : -1) );
688 void OrthoDistance4(const Point& rPt0, Point& rPt, FASTBOOL bBigOrtho)
690 long dx=rPt.X()-rPt0.X();
691 long dy=rPt.Y()-rPt0.Y();
692 long dxa=Abs(dx);
693 long dya=Abs(dy);
694 if ((dxa<dya) != bBigOrtho) {
695 rPt.Y()=rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) );
696 } else {
697 rPt.X()=rPt0.X()+(dya* (dx>=0 ? 1 : -1) );
701 ////////////////////////////////////////////////////////////////////////////////////////////////////
703 long BigMulDiv(long nVal, long nMul, long nDiv)
705 BigInt aVal(nVal);
706 aVal*=nMul;
707 if (aVal.IsNeg()!=(nDiv<0)) {
708 aVal-=nDiv/2; // fuer korrektes Runden
709 } else {
710 aVal+=nDiv/2; // fuer korrektes Runden
712 if(nDiv)
714 aVal/=nDiv;
715 return long(aVal);
717 return 0x7fffffff;
720 void Kuerzen(Fraction& rF, unsigned nDigits)
722 INT32 nMul=rF.GetNumerator();
723 INT32 nDiv=rF.GetDenominator();
724 FASTBOOL bNeg=FALSE;
725 if (nMul<0) { nMul=-nMul; bNeg=!bNeg; }
726 if (nDiv<0) { nDiv=-nDiv; bNeg=!bNeg; }
727 if (nMul==0 || nDiv==0) return;
728 UINT32 a;
729 a=UINT32(nMul); unsigned nMulZ=0; // Fuehrende Nullen zaehlen
730 while (a<0x00800000) { nMulZ+=8; a<<=8; }
731 while (a<0x80000000) { nMulZ++; a<<=1; }
732 a=UINT32(nDiv); unsigned nDivZ=0; // Fuehrende Nullen zaehlen
733 while (a<0x00800000) { nDivZ+=8; a<<=8; }
734 while (a<0x80000000) { nDivZ++; a<<=1; }
735 // Anzahl der verwendeten Digits bestimmen
736 int nMulDigits=32-nMulZ;
737 int nDivDigits=32-nDivZ;
738 // Nun bestimmen, wieviele Stellen hinten weg koennen
739 int nMulWeg=nMulDigits-nDigits; if (nMulWeg<0) nMulWeg=0;
740 int nDivWeg=nDivDigits-nDigits; if (nDivWeg<0) nDivWeg=0;
741 int nWeg=Min(nMulWeg,nDivWeg);
742 nMul>>=nWeg;
743 nDiv>>=nWeg;
744 if (nMul==0 || nDiv==0) {
745 DBG_WARNING("Oups, beim kuerzen einer Fraction hat sich Joe verrechnet.");
746 return;
748 if (bNeg) nMul=-nMul;
749 rF=Fraction(nMul,nDiv);
752 ////////////////////////////////////////////////////////////////////////////////////////////////////
753 // Wieviele eU-Einheiten passen in einen mm bzw. Inch?
754 // Oder wie gross ist ein eU in mm bzw. Inch, und davon der Kehrwert
756 FrPair GetInchOrMM(MapUnit eU)
758 switch (eU) {
759 case MAP_1000TH_INCH: return FrPair(1000,1);
760 case MAP_100TH_INCH : return FrPair( 100,1);
761 case MAP_10TH_INCH : return FrPair( 10,1);
762 case MAP_INCH : return FrPair( 1,1);
763 case MAP_POINT : return FrPair( 72,1);
764 case MAP_TWIP : return FrPair(1440,1);
765 case MAP_100TH_MM : return FrPair( 100,1);
766 case MAP_10TH_MM : return FrPair( 10,1);
767 case MAP_MM : return FrPair( 1,1);
768 case MAP_CM : return FrPair( 1,10);
769 case MAP_PIXEL : {
770 VirtualDevice aVD;
771 aVD.SetMapMode(MapMode(MAP_100TH_MM));
772 Point aP(aVD.PixelToLogic(Point(64,64))); // 64 Pixel fuer bessere Genauigkeit
773 return FrPair(6400,aP.X(),6400,aP.Y());
775 case MAP_APPFONT: case MAP_SYSFONT: {
776 VirtualDevice aVD;
777 aVD.SetMapMode(MapMode(eU));
778 Point aP(aVD.LogicToPixel(Point(32,32))); // 32 Einheiten fuer bessere Genauigkeit
779 aVD.SetMapMode(MapMode(MAP_100TH_MM));
780 aP=aVD.PixelToLogic(aP);
781 return FrPair(3200,aP.X(),3200,aP.Y());
783 default: break;
785 return Fraction(1,1);
788 FrPair GetInchOrMM(FieldUnit eU)
790 switch (eU) {
791 case FUNIT_INCH : return FrPair( 1,1);
792 case FUNIT_POINT : return FrPair( 72,1);
793 case FUNIT_TWIP : return FrPair(1440,1);
794 case FUNIT_100TH_MM : return FrPair( 100,1);
795 case FUNIT_MM : return FrPair( 1,1);
796 case FUNIT_CM : return FrPair( 1,10);
797 case FUNIT_M : return FrPair( 1,1000);
798 case FUNIT_KM : return FrPair( 1,1000000);
799 case FUNIT_PICA : return FrPair( 6,1);
800 case FUNIT_FOOT : return FrPair( 1,12);
801 case FUNIT_MILE : return FrPair( 1,63360);
802 default: break;
804 return Fraction(1,1);
807 // Den Faktor berechnen, der anzuwenden ist um n Einheiten von eS nach
808 // eD umzurechnen. Z.B. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
810 FrPair GetMapFactor(MapUnit eS, MapUnit eD)
812 if (eS==eD) return FrPair(1,1,1,1);
813 FrPair aS(GetInchOrMM(eS));
814 FrPair aD(GetInchOrMM(eD));
815 FASTBOOL bSInch=IsInch(eS);
816 FASTBOOL bDInch=IsInch(eD);
817 FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
818 if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
819 if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
820 return aRet;
823 FrPair GetMapFactor(MapUnit eS, FieldUnit eD)
825 FrPair aS(GetInchOrMM(eS));
826 FrPair aD(GetInchOrMM(eD));
827 FASTBOOL bSInch=IsInch(eS);
828 FASTBOOL bDInch=IsInch(eD);
829 FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
830 if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
831 if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
832 return aRet;
835 FrPair GetMapFactor(FieldUnit eS, MapUnit eD)
837 FrPair aS(GetInchOrMM(eS));
838 FrPair aD(GetInchOrMM(eD));
839 FASTBOOL bSInch=IsInch(eS);
840 FASTBOOL bDInch=IsInch(eD);
841 FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
842 if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
843 if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
844 return aRet;
847 FrPair GetMapFactor(FieldUnit eS, FieldUnit eD)
849 if (eS==eD) return FrPair(1,1,1,1);
850 FrPair aS(GetInchOrMM(eS));
851 FrPair aD(GetInchOrMM(eD));
852 FASTBOOL bSInch=IsInch(eS);
853 FASTBOOL bDInch=IsInch(eD);
854 FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
855 if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
856 if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
857 return aRet;
860 ////////////////////////////////////////////////////////////////////////////////////////////////////
862 // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm
863 // 1 furlong = 10 chains = 7.920" = 201.168,0mm
864 // 1 chain = 4 poles = 792" = 20.116,8mm
865 // 1 pole = 5 1/2 yd = 198" = 5.029,2mm
866 // 1 yd = 3 ft = 36" = 914,4mm
867 // 1 ft = 12 " = 1" = 304,8mm
869 void GetMeterOrInch(MapUnit eMU, short& rnKomma, long& rnMul, long& rnDiv, FASTBOOL& rbMetr, FASTBOOL& rbInch)
871 rnMul=1; rnDiv=1;
872 short nKomma=0;
873 FASTBOOL bMetr=FALSE,bInch=FALSE;
874 switch (eMU) {
875 // Metrisch
876 case MAP_100TH_MM : bMetr=TRUE; nKomma=5; break;
877 case MAP_10TH_MM : bMetr=TRUE; nKomma=4; break;
878 case MAP_MM : bMetr=TRUE; nKomma=3; break;
879 case MAP_CM : bMetr=TRUE; nKomma=2; break;
880 // Inch
881 case MAP_1000TH_INCH: bInch=TRUE; nKomma=3; break;
882 case MAP_100TH_INCH : bInch=TRUE; nKomma=2; break;
883 case MAP_10TH_INCH : bInch=TRUE; nKomma=1; break;
884 case MAP_INCH : bInch=TRUE; nKomma=0; break;
885 case MAP_POINT : bInch=TRUE; rnDiv=72; break; // 1Pt = 1/72"
886 case MAP_TWIP : bInch=TRUE; rnDiv=144; nKomma=1; break; // 1Twip = 1/1440"
887 // Sonstiges
888 case MAP_PIXEL : break;
889 case MAP_SYSFONT : break;
890 case MAP_APPFONT : break;
891 case MAP_RELATIVE : break;
892 default: break;
893 } // switch
894 rnKomma=nKomma;
895 rbMetr=bMetr;
896 rbInch=bInch;
899 void GetMeterOrInch(FieldUnit eFU, short& rnKomma, long& rnMul, long& rnDiv, FASTBOOL& rbMetr, FASTBOOL& rbInch)
901 rnMul=1; rnDiv=1;
902 short nKomma=0;
903 FASTBOOL bMetr=FALSE,bInch=FALSE;
904 switch (eFU) {
905 case FUNIT_NONE : break;
906 // Metrisch
907 case FUNIT_100TH_MM : bMetr=TRUE; nKomma=5; break;
908 case FUNIT_MM : bMetr=TRUE; nKomma=3; break;
909 case FUNIT_CM : bMetr=TRUE; nKomma=2; break;
910 case FUNIT_M : bMetr=TRUE; nKomma=0; break;
911 case FUNIT_KM : bMetr=TRUE; nKomma=-3; break;
912 // Inch
913 case FUNIT_TWIP : bInch=TRUE; rnDiv=144; nKomma=1; break; // 1Twip = 1/1440"
914 case FUNIT_POINT : bInch=TRUE; rnDiv=72; break; // 1Pt = 1/72"
915 case FUNIT_PICA : bInch=TRUE; rnDiv=6; break; // 1Pica = 1/6" ?
916 case FUNIT_INCH : bInch=TRUE; break; // 1" = 1"
917 case FUNIT_FOOT : bInch=TRUE; rnMul=12; break; // 1Ft = 12"
918 case FUNIT_MILE : bInch=TRUE; rnMul=6336; nKomma=-1; break; // 1mile = 63360"
919 // sonstiges
920 case FUNIT_CUSTOM : break;
921 case FUNIT_PERCENT : nKomma=2; break;
922 } // switch
923 rnKomma=nKomma;
924 rbMetr=bMetr;
925 rbInch=bInch;
928 void SdrFormatter::Undirty()
930 if (aScale.GetNumerator()==0 || aScale.GetDenominator()==0) aScale=Fraction(1,1);
931 FASTBOOL bSrcMetr,bSrcInch,bDstMetr,bDstInch;
932 long nMul1,nDiv1,nMul2,nDiv2;
933 short nKomma1,nKomma2;
934 // Zunaechst normalisieren auf m bzw. "
935 if (!bSrcFU) {
936 GetMeterOrInch(eSrcMU,nKomma1,nMul1,nDiv1,bSrcMetr,bSrcInch);
937 } else {
938 GetMeterOrInch(eSrcFU,nKomma1,nMul1,nDiv1,bSrcMetr,bSrcInch);
940 if (!bDstFU) {
941 GetMeterOrInch(eDstMU,nKomma2,nMul2,nDiv2,bDstMetr,bDstInch);
942 } else {
943 GetMeterOrInch(eDstFU,nKomma2,nMul2,nDiv2,bDstMetr,bDstInch);
945 nMul1*=nDiv2;
946 nDiv1*=nMul2;
947 nKomma1=nKomma1-nKomma2;
949 if (bSrcInch && bDstMetr) {
950 nKomma1+=4;
951 nMul1*=254;
953 if (bSrcMetr && bDstInch) {
954 nKomma1-=4;
955 nDiv1*=254;
958 // Temporaere Fraction zum Kuerzen
959 Fraction aTempFract(nMul1,nDiv1);
960 nMul1=aTempFract.GetNumerator();
961 nDiv1=aTempFract.GetDenominator();
963 nMul_=nMul1;
964 nDiv_=nDiv1;
965 nKomma_=nKomma1;
966 bDirty=FALSE;
970 void SdrFormatter::TakeStr(long nVal, XubString& rStr) const
972 sal_Unicode aNullCode('0');
974 if(!nVal)
976 rStr = UniString();
977 rStr += aNullCode;
978 return;
981 // Hier fallen trotzdem evtl. Nachkommastellen weg, wg. MulDiv statt Real
982 BOOL bNeg(nVal < 0);
983 SvtSysLocale aSysLoc;
984 const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData();
986 ForceUndirty();
988 sal_Int16 nK(nKomma_);
989 XubString aStr;
991 if(bNeg)
992 nVal = -nVal;
994 while(nK <= -3)
996 nVal *= 1000;
997 nK += 3;
1000 while(nK <= -1)
1002 nVal *= 10;
1003 nK++;
1006 if(nMul_ != nDiv_)
1007 nVal = BigMulDiv(nVal, nMul_, nDiv_);
1009 aStr = UniString::CreateFromInt32(nVal);
1011 if(nK > 0 && aStr.Len() <= nK )
1013 // Komma erforderlich
1014 sal_Int16 nAnz(nK - aStr.Len());
1016 if(nAnz >= 0 && rLoc.isNumLeadingZero())
1017 nAnz++;
1019 for(xub_StrLen i=0; i<nAnz; i++)
1020 aStr.Insert(aNullCode, 0);
1022 // zuviele Nachkommastellen abhacken
1023 xub_StrLen nNumDigits(rLoc.getNumDigits());
1024 xub_StrLen nWeg(nK - nNumDigits);
1026 if(nWeg > 0)
1028 // hier muesste eigentlich noch gerundet werden!
1029 aStr.Erase(aStr.Len() - nWeg);
1030 nK = nNumDigits;
1034 // Vorkommastellen fuer spaeter merken
1035 xub_StrLen nVorKomma(aStr.Len() - nK);
1037 if(nK > 0)
1039 // KommaChar einfuegen
1040 // erstmal trailing Zeros abhacken
1041 while(nK > 0 && aStr.GetChar(aStr.Len() - 1) == aNullCode)
1043 aStr.Erase(aStr.Len() - 1);
1044 nK--;
1047 if(nK > 0)
1049 // na, noch Nachkommastellen da?
1050 sal_Unicode cDec(rLoc.getNumDecimalSep().GetChar(0));
1051 aStr.Insert(cDec, nVorKomma);
1055 // ggf. Trennpunkte bei jedem Tausender einfuegen
1056 if( nVorKomma > 3 )
1058 String aThoSep( rLoc.getNumThousandSep() );
1059 if ( aThoSep.Len() > 0 )
1061 sal_Unicode cTho( aThoSep.GetChar(0) );
1062 sal_Int32 i(nVorKomma - 3);
1064 while(i > 0)
1066 rStr.Insert(cTho, (xub_StrLen)i);
1067 i -= 3;
1072 if(!aStr.Len())
1073 aStr += aNullCode;
1075 if(bNeg && (aStr.Len() > 1 || aStr.GetChar(0) != aNullCode))
1077 rStr.Insert(sal_Unicode('-'), 0);
1080 rStr = aStr;
1083 void SdrFormatter::TakeUnitStr(MapUnit eUnit, XubString& rStr)
1085 switch(eUnit)
1087 // Metrisch
1088 case MAP_100TH_MM :
1090 sal_Char aText[] = "/100mm";
1091 rStr = UniString(aText, sizeof(aText-1));
1092 break;
1094 case MAP_10TH_MM :
1096 sal_Char aText[] = "/10mm";
1097 rStr = UniString(aText, sizeof(aText-1));
1098 break;
1100 case MAP_MM :
1102 sal_Char aText[] = "mm";
1103 rStr = UniString(aText, sizeof(aText-1));
1104 break;
1106 case MAP_CM :
1108 sal_Char aText[] = "cm";
1109 rStr = UniString(aText, sizeof(aText-1));
1110 break;
1113 // Inch
1114 case MAP_1000TH_INCH:
1116 sal_Char aText[] = "/1000\"";
1117 rStr = UniString(aText, sizeof(aText-1));
1118 break;
1120 case MAP_100TH_INCH :
1122 sal_Char aText[] = "/100\"";
1123 rStr = UniString(aText, sizeof(aText-1));
1124 break;
1126 case MAP_10TH_INCH :
1128 sal_Char aText[] = "/10\"";
1129 rStr = UniString(aText, sizeof(aText-1));
1130 break;
1132 case MAP_INCH :
1134 rStr = UniString();
1135 rStr += sal_Unicode('"');
1136 break;
1138 case MAP_POINT :
1140 sal_Char aText[] = "pt";
1141 rStr = UniString(aText, sizeof(aText-1));
1142 break;
1144 case MAP_TWIP :
1146 sal_Char aText[] = "twip";
1147 rStr = UniString(aText, sizeof(aText-1));
1148 break;
1151 // Sonstiges
1152 case MAP_PIXEL :
1154 sal_Char aText[] = "pixel";
1155 rStr = UniString(aText, sizeof(aText-1));
1156 break;
1158 case MAP_SYSFONT :
1160 sal_Char aText[] = "sysfont";
1161 rStr = UniString(aText, sizeof(aText-1));
1162 break;
1164 case MAP_APPFONT :
1166 sal_Char aText[] = "appfont";
1167 rStr = UniString(aText, sizeof(aText-1));
1168 break;
1170 case MAP_RELATIVE :
1172 rStr = UniString();
1173 rStr += sal_Unicode('%');
1174 break;
1176 default: break;
1180 void SdrFormatter::TakeUnitStr(FieldUnit eUnit, XubString& rStr)
1182 switch(eUnit)
1184 default :
1185 case FUNIT_NONE :
1186 case FUNIT_CUSTOM :
1188 rStr = UniString();
1189 break;
1192 // Metrisch
1193 case FUNIT_100TH_MM:
1195 sal_Char aText[] = "/100mm";
1196 rStr = UniString(aText, sizeof(aText-1));
1197 break;
1199 case FUNIT_MM :
1201 sal_Char aText[] = "mm";
1202 rStr = UniString(aText, sizeof(aText-1));
1203 break;
1205 case FUNIT_CM :
1207 sal_Char aText[] = "cm";
1208 rStr = UniString(aText, sizeof(aText-1));
1209 break;
1211 case FUNIT_M :
1213 rStr = UniString();
1214 rStr += sal_Unicode('m');
1215 break;
1217 case FUNIT_KM :
1219 sal_Char aText[] = "km";
1220 rStr = UniString(aText, sizeof(aText-1));
1221 break;
1224 // Inch
1225 case FUNIT_TWIP :
1227 sal_Char aText[] = "twip";
1228 rStr = UniString(aText, sizeof(aText-1));
1229 break;
1231 case FUNIT_POINT :
1233 sal_Char aText[] = "pt";
1234 rStr = UniString(aText, sizeof(aText-1));
1235 break;
1237 case FUNIT_PICA :
1239 sal_Char aText[] = "pica";
1240 rStr = UniString(aText, sizeof(aText-1));
1241 break;
1243 case FUNIT_INCH :
1245 rStr = UniString();
1246 rStr += sal_Unicode('"');
1247 break;
1249 case FUNIT_FOOT :
1251 sal_Char aText[] = "ft";
1252 rStr = UniString(aText, sizeof(aText-1));
1253 break;
1255 case FUNIT_MILE :
1257 sal_Char aText[] = "mile(s)";
1258 rStr = UniString(aText, sizeof(aText-1));
1259 break;
1262 // sonstiges
1263 case FUNIT_PERCENT:
1265 rStr = UniString();
1266 rStr += sal_Unicode('%');
1267 break;
1272 ////////////////////////////////////////////////////////////////////////////////////////////////////