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