LibreOffice Module svx (master)  1
svdtrans.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 
21 #include <svx/svdtrans.hxx>
22 #include <math.h>
23 #include <svx/xpoly.hxx>
24 #include <rtl/ustrbuf.hxx>
25 
26 #include <vcl/virdev.hxx>
27 #include <tools/bigint.hxx>
28 #include <unotools/syslocale.hxx>
30 #include <sal/log.hxx>
31 
32 void MoveXPoly(XPolygon& rPoly, const Size& S)
33 {
34  rPoly.Move(S.Width(),S.Height());
35 }
36 
37 void ResizeRect(tools::Rectangle& rRect, const Point& rRef, const Fraction& rxFact, const Fraction& ryFact)
38 {
39  Fraction aXFact(rxFact);
40  Fraction aYFact(ryFact);
41 
42  if (!aXFact.IsValid()) {
43  SAL_WARN( "svx.svdraw", "invalid fraction xFract, using Fraction(1,1)" );
44  aXFact = Fraction(1,1);
45  long nWdt = rRect.Right() - rRect.Left();
46  if (nWdt == 0) rRect.AdjustRight( 1 );
47  }
48  rRect.SetLeft( rRef.X() + FRound( (rRect.Left() - rRef.X()) * double(aXFact) ) );
49  rRect.SetRight( rRef.X() + FRound( (rRect.Right() - rRef.X()) * double(aXFact) ) );
50 
51  if (!aYFact.IsValid()) {
52  SAL_WARN( "svx.svdraw", "invalid fraction yFract, using Fraction(1,1)" );
53  aYFact = Fraction(1,1);
54  long nHgt = rRect.Bottom() - rRect.Top();
55  if (nHgt == 0) rRect.AdjustBottom( 1 );
56  }
57  rRect.SetTop( rRef.Y() + FRound( (rRect.Top() - rRef.Y()) * double(aYFact) ) );
58  rRect.SetBottom( rRef.Y() + FRound( (rRect.Bottom() - rRef.Y()) * double(aYFact) ) );
59 
60  rRect.Justify();
61 }
62 
63 
64 void ResizePoly(tools::Polygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
65 {
66  sal_uInt16 nCount=rPoly.GetSize();
67  for (sal_uInt16 i=0; i<nCount; i++) {
68  ResizePoint(rPoly[i],rRef,xFact,yFact);
69  }
70 }
71 
72 void ResizeXPoly(XPolygon& rPoly, const Point& rRef, const Fraction& xFact, const Fraction& yFact)
73 {
74  sal_uInt16 nCount=rPoly.GetPointCount();
75  for (sal_uInt16 i=0; i<nCount; i++) {
76  ResizePoint(rPoly[i],rRef,xFact,yFact);
77  }
78 }
79 
80 void RotatePoly(tools::Polygon& rPoly, const Point& rRef, double sn, double cs)
81 {
82  sal_uInt16 nCount=rPoly.GetSize();
83  for (sal_uInt16 i=0; i<nCount; i++) {
84  RotatePoint(rPoly[i],rRef,sn,cs);
85  }
86 }
87 
88 void RotateXPoly(XPolygon& rPoly, const Point& rRef, double sn, double cs)
89 {
90  sal_uInt16 nCount=rPoly.GetPointCount();
91  for (sal_uInt16 i=0; i<nCount; i++) {
92  RotatePoint(rPoly[i],rRef,sn,cs);
93  }
94 }
95 
96 void RotateXPoly(XPolyPolygon& rPoly, const Point& rRef, double sn, double cs)
97 {
98  sal_uInt16 nCount=rPoly.Count();
99  for (sal_uInt16 i=0; i<nCount; i++) {
100  RotateXPoly(rPoly[i],rRef,sn,cs);
101  }
102 }
103 
104 void MirrorPoint(Point& rPnt, const Point& rRef1, const Point& rRef2)
105 {
106  long mx=rRef2.X()-rRef1.X();
107  long my=rRef2.Y()-rRef1.Y();
108  if (mx==0) { // vertical axis
109  long dx=rRef1.X()-rPnt.X();
110  rPnt.AdjustX(2*dx );
111  } else if (my==0) { // horizontal axis
112  long dy=rRef1.Y()-rPnt.Y();
113  rPnt.AdjustY(2*dy );
114  } else if (mx==my) { // diagonal axis '\'
115  long dx1=rPnt.X()-rRef1.X();
116  long dy1=rPnt.Y()-rRef1.Y();
117  rPnt.setX(rRef1.X()+dy1 );
118  rPnt.setY(rRef1.Y()+dx1 );
119  } else if (mx==-my) { // diagonal axis '/'
120  long dx1=rPnt.X()-rRef1.X();
121  long dy1=rPnt.Y()-rRef1.Y();
122  rPnt.setX(rRef1.X()-dy1 );
123  rPnt.setY(rRef1.Y()-dx1 );
124  } else { // arbitrary axis
125  // TODO: Optimize this! Raise perpendicular on the mirroring axis..?
126  long nRefWink=GetAngle(rRef2-rRef1);
127  rPnt-=rRef1;
128  long nPntWink=GetAngle(rPnt);
129  long nAngle=2*(nRefWink-nPntWink);
130  double a = nAngle * F_PI18000;
131  double nSin=sin(a);
132  double nCos=cos(a);
133  RotatePoint(rPnt,Point(),nSin,nCos);
134  rPnt+=rRef1;
135  }
136 }
137 
138 void MirrorXPoly(XPolygon& rPoly, const Point& rRef1, const Point& rRef2)
139 {
140  sal_uInt16 nCount=rPoly.GetPointCount();
141  for (sal_uInt16 i=0; i<nCount; i++) {
142  MirrorPoint(rPoly[i],rRef1,rRef2);
143  }
144 }
145 
146 void ShearPoly(tools::Polygon& rPoly, const Point& rRef, double tn)
147 {
148  sal_uInt16 nCount=rPoly.GetSize();
149  for (sal_uInt16 i=0; i<nCount; i++) {
150  ShearPoint(rPoly[i],rRef,tn);
151  }
152 }
153 
154 void ShearXPoly(XPolygon& rPoly, const Point& rRef, double tn, bool bVShear)
155 {
156  sal_uInt16 nCount=rPoly.GetPointCount();
157  for (sal_uInt16 i=0; i<nCount; i++) {
158  ShearPoint(rPoly[i],rRef,tn,bVShear);
159  }
160 }
161 
162 double CrookRotateXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
163  const Point& rRad, double& rSin, double& rCos, bool bVert)
164 {
165  bool bC1=pC1!=nullptr;
166  bool bC2=pC2!=nullptr;
167  long x0=rPnt.X();
168  long y0=rPnt.Y();
169  long cx=rCenter.X();
170  long cy=rCenter.Y();
171  double nAngle=GetCrookAngle(rPnt,rCenter,rRad,bVert);
172  double sn=sin(nAngle);
173  double cs=cos(nAngle);
174  RotatePoint(rPnt,rCenter,sn,cs);
175  if (bC1) {
176  if (bVert) {
177  // move into the direction of the center, as a basic position for the rotation
178  pC1->AdjustY( -y0 );
179  // resize, account for the distance from the center
180  pC1->setY(FRound(static_cast<double>(pC1->Y()) /rRad.X()*(cx-pC1->X())) );
181  pC1->AdjustY(cy );
182  } else {
183  // move into the direction of the center, as a basic position for the rotation
184  pC1->AdjustX( -x0 );
185  // resize, account for the distance from the center
186  long nPntRad=cy-pC1->Y();
187  double nFact=static_cast<double>(nPntRad)/static_cast<double>(rRad.Y());
188  pC1->setX(FRound(static_cast<double>(pC1->X())*nFact) );
189  pC1->AdjustX(cx );
190  }
191  RotatePoint(*pC1,rCenter,sn,cs);
192  }
193  if (bC2) {
194  if (bVert) {
195  // move into the direction of the center, as a basic position for the rotation
196  pC2->AdjustY( -y0 );
197  // resize, account for the distance from the center
198  pC2->setY(FRound(static_cast<double>(pC2->Y()) /rRad.X()*(rCenter.X()-pC2->X())) );
199  pC2->AdjustY(cy );
200  } else {
201  // move into the direction of the center, as a basic position for the rotation
202  pC2->AdjustX( -x0 );
203  // resize, account for the distance from the center
204  long nPntRad=rCenter.Y()-pC2->Y();
205  double nFact=static_cast<double>(nPntRad)/static_cast<double>(rRad.Y());
206  pC2->setX(FRound(static_cast<double>(pC2->X())*nFact) );
207  pC2->AdjustX(cx );
208  }
209  RotatePoint(*pC2,rCenter,sn,cs);
210  }
211  rSin=sn;
212  rCos=cs;
213  return nAngle;
214 }
215 
216 double CrookSlantXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
217  const Point& rRad, double& rSin, double& rCos, bool bVert)
218 {
219  bool bC1=pC1!=nullptr;
220  bool bC2=pC2!=nullptr;
221  long x0=rPnt.X();
222  long y0=rPnt.Y();
223  long dx1=0,dy1=0;
224  long dxC1=0,dyC1=0;
225  long dxC2=0,dyC2=0;
226  if (bVert) {
227  long nStart=rCenter.X()-rRad.X();
228  dx1=rPnt.X()-nStart;
229  rPnt.setX(nStart );
230  if (bC1) {
231  dxC1=pC1->X()-nStart;
232  pC1->setX(nStart );
233  }
234  if (bC2) {
235  dxC2=pC2->X()-nStart;
236  pC2->setX(nStart );
237  }
238  } else {
239  long nStart=rCenter.Y()-rRad.Y();
240  dy1=rPnt.Y()-nStart;
241  rPnt.setY(nStart );
242  if (bC1) {
243  dyC1=pC1->Y()-nStart;
244  pC1->setY(nStart );
245  }
246  if (bC2) {
247  dyC2=pC2->Y()-nStart;
248  pC2->setY(nStart );
249  }
250  }
251  double nAngle=GetCrookAngle(rPnt,rCenter,rRad,bVert);
252  double sn=sin(nAngle);
253  double cs=cos(nAngle);
254  RotatePoint(rPnt,rCenter,sn,cs);
255  if (bC1) { if (bVert) pC1->AdjustY( -(y0-rCenter.Y()) ); else pC1->AdjustX( -(x0-rCenter.X()) ); RotatePoint(*pC1,rCenter,sn,cs); }
256  if (bC2) { if (bVert) pC2->AdjustY( -(y0-rCenter.Y()) ); else pC2->AdjustX( -(x0-rCenter.X()) ); RotatePoint(*pC2,rCenter,sn,cs); }
257  if (bVert) {
258  rPnt.AdjustX(dx1 );
259  if (bC1) pC1->AdjustX(dxC1 );
260  if (bC2) pC2->AdjustX(dxC2 );
261  } else {
262  rPnt.AdjustY(dy1 );
263  if (bC1) pC1->AdjustY(dyC1 );
264  if (bC2) pC2->AdjustY(dyC2 );
265  }
266  rSin=sn;
267  rCos=cs;
268  return nAngle;
269 }
270 
271 double CrookStretchXPoint(Point& rPnt, Point* pC1, Point* pC2, const Point& rCenter,
272  const Point& rRad, double& rSin, double& rCos, bool bVert,
273  const tools::Rectangle& rRefRect)
274 {
275  long y0=rPnt.Y();
276  CrookSlantXPoint(rPnt,pC1,pC2,rCenter,rRad,rSin,rCos,bVert);
277  if (bVert) {
278  } else {
279  long nTop=rRefRect.Top();
280  long nBtm=rRefRect.Bottom();
281  long nHgt=nBtm-nTop;
282  long dy=rPnt.Y()-y0;
283  double a=static_cast<double>(y0-nTop)/nHgt;
284  a*=dy;
285  rPnt.setY(y0+FRound(a) );
286  }
287  return 0.0;
288 }
289 
290 
291 void CrookRotatePoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert)
292 {
293  double nSin,nCos;
294  sal_uInt16 nPointCnt=rPoly.GetPointCount();
295  sal_uInt16 i=0;
296  while (i<nPointCnt) {
297  Point* pPnt=&rPoly[i];
298  Point* pC1=nullptr;
299  Point* pC2=nullptr;
300  if (i+1<nPointCnt && rPoly.IsControl(i)) { // control point to the left
301  pC1=pPnt;
302  i++;
303  pPnt=&rPoly[i];
304  }
305  i++;
306  if (i<nPointCnt && rPoly.IsControl(i)) { // control point to the right
307  pC2=&rPoly[i];
308  i++;
309  }
310  CrookRotateXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert);
311  }
312 }
313 
314 void CrookSlantPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert)
315 {
316  double nSin,nCos;
317  sal_uInt16 nPointCnt=rPoly.GetPointCount();
318  sal_uInt16 i=0;
319  while (i<nPointCnt) {
320  Point* pPnt=&rPoly[i];
321  Point* pC1=nullptr;
322  Point* pC2=nullptr;
323  if (i+1<nPointCnt && rPoly.IsControl(i)) { // control point to the left
324  pC1=pPnt;
325  i++;
326  pPnt=&rPoly[i];
327  }
328  i++;
329  if (i<nPointCnt && rPoly.IsControl(i)) { // control point to the right
330  pC2=&rPoly[i];
331  i++;
332  }
333  CrookSlantXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert);
334  }
335 }
336 
337 void CrookStretchPoly(XPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert, const tools::Rectangle& rRefRect)
338 {
339  double nSin,nCos;
340  sal_uInt16 nPointCnt=rPoly.GetPointCount();
341  sal_uInt16 i=0;
342  while (i<nPointCnt) {
343  Point* pPnt=&rPoly[i];
344  Point* pC1=nullptr;
345  Point* pC2=nullptr;
346  if (i+1<nPointCnt && rPoly.IsControl(i)) { // control point to the left
347  pC1=pPnt;
348  i++;
349  pPnt=&rPoly[i];
350  }
351  i++;
352  if (i<nPointCnt && rPoly.IsControl(i)) { // control point to the right
353  pC2=&rPoly[i];
354  i++;
355  }
356  CrookStretchXPoint(*pPnt,pC1,pC2,rCenter,rRad,nSin,nCos,bVert,rRefRect);
357  }
358 }
359 
360 
361 void CrookRotatePoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert)
362 {
363  sal_uInt16 nPolyCount=rPoly.Count();
364  for (sal_uInt16 nPolyNum=0; nPolyNum<nPolyCount; nPolyNum++) {
365  CrookRotatePoly(rPoly[nPolyNum],rCenter,rRad,bVert);
366  }
367 }
368 
369 void CrookSlantPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert)
370 {
371  sal_uInt16 nPolyCount=rPoly.Count();
372  for (sal_uInt16 nPolyNum=0; nPolyNum<nPolyCount; nPolyNum++) {
373  CrookSlantPoly(rPoly[nPolyNum],rCenter,rRad,bVert);
374  }
375 }
376 
377 void CrookStretchPoly(XPolyPolygon& rPoly, const Point& rCenter, const Point& rRad, bool bVert, const tools::Rectangle& rRefRect)
378 {
379  sal_uInt16 nPolyCount=rPoly.Count();
380  for (sal_uInt16 nPolyNum=0; nPolyNum<nPolyCount; nPolyNum++) {
381  CrookStretchPoly(rPoly[nPolyNum],rCenter,rRad,bVert,rRefRect);
382  }
383 }
384 
385 
386 long GetAngle(const Point& rPnt)
387 {
388  long a=0;
389  if (rPnt.Y()==0) {
390  if (rPnt.X()<0) a=-18000;
391  } else if (rPnt.X()==0) {
392  if (rPnt.Y()>0) a=-9000;
393  else a=9000;
394  } else {
395  a = FRound(atan2(static_cast<double>(-rPnt.Y()), static_cast<double>(rPnt.X()))
396  / F_PI18000);
397  }
398  return a;
399 }
400 
401 long NormAngle18000(long a)
402 {
403  while (a<-18000) a+=36000;
404  while (a>=18000) a-=36000;
405  return a;
406 }
407 
408 long NormAngle36000(long a)
409 {
410  while (a<0) a+=36000;
411  while (a>=36000) a-=36000;
412  return a;
413 }
414 
415 sal_uInt16 GetAngleSector(long nAngle)
416 {
417  while (nAngle<0) nAngle+=36000;
418  while (nAngle>=36000) nAngle-=36000;
419  if (nAngle< 9000) return 0;
420  if (nAngle<18000) return 1;
421  if (nAngle<27000) return 2;
422  return 3;
423 }
424 
425 long GetLen(const Point& rPnt)
426 {
427  long x=std::abs(rPnt.X());
428  long y=std::abs(rPnt.Y());
429  if (x+y<0x8000) { // because 7FFF * 7FFF * 2 = 7FFE0002
430  x*=x;
431  y*=y;
432  x+=y;
433  x=FRound(sqrt(static_cast<double>(x)));
434  return x;
435  } else {
436  double nx=x;
437  double ny=y;
438  nx*=nx;
439  ny*=ny;
440  nx+=ny;
441  nx=sqrt(nx);
442  if (nx>0x7FFFFFFF) {
443  return 0x7FFFFFFF; // we can't go any further, for fear of an overrun!
444  } else {
445  return FRound(nx);
446  }
447  }
448 }
449 
450 
452 {
453  if (nRotationAngle==0) {
454  nSin=0.0;
455  nCos=1.0;
456  } else {
457  double a = nRotationAngle * F_PI18000;
458  nSin=sin(a);
459  nCos=cos(a);
460  }
461 }
462 
464 {
465  if (nShearAngle==0) {
466  nTan=0.0;
467  } else {
468  double a = nShearAngle * F_PI18000;
469  nTan=tan(a);
470  }
471 }
472 
473 
475 {
476  tools::Polygon aPol(5);
477  aPol[0]=rRect.TopLeft();
478  aPol[1]=rRect.TopRight();
479  aPol[2]=rRect.BottomRight();
480  aPol[3]=rRect.BottomLeft();
481  aPol[4]=rRect.TopLeft();
482  if (rGeo.nShearAngle!=0) ShearPoly(aPol,rRect.TopLeft(),rGeo.nTan);
483  if (rGeo.nRotationAngle!=0) RotatePoly(aPol,rRect.TopLeft(),rGeo.nSin,rGeo.nCos);
484  return aPol;
485 }
486 
487 void Poly2Rect(const tools::Polygon& rPol, tools::Rectangle& rRect, GeoStat& rGeo)
488 {
489  rGeo.nRotationAngle=GetAngle(rPol[1]-rPol[0]);
491  // rotation successful
492  rGeo.RecalcSinCos();
493 
494  Point aPt1(rPol[1]-rPol[0]);
495  if (rGeo.nRotationAngle!=0) RotatePoint(aPt1,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin to reverse rotation
496  long nWdt=aPt1.X();
497 
498  Point aPt0(rPol[0]);
499  Point aPt3(rPol[3]-rPol[0]);
500  if (rGeo.nRotationAngle!=0) RotatePoint(aPt3,Point(0,0),-rGeo.nSin,rGeo.nCos); // -Sin to reverse rotation
501  long nHgt=aPt3.Y();
502 
503 
504  long nShW=GetAngle(aPt3);
505  nShW-=27000; // ShearWink is measured against a vertical line
506  nShW=-nShW; // negating, because '+' is shearing clock-wise
507 
508  bool bMirr=aPt3.Y()<0;
509  if (bMirr) { // "exchange of points" when mirroring
510  nHgt=-nHgt;
511  nShW+=18000;
512  aPt0=rPol[3];
513  }
514  nShW=NormAngle18000(nShW);
515  if (nShW<-9000 || nShW>9000) {
516  nShW=NormAngle18000(nShW+18000);
517  }
518  if (nShW<-SDRMAXSHEAR) nShW=-SDRMAXSHEAR; // limit ShearWinkel (shear angle) to +/- 89.00 deg
519  if (nShW>SDRMAXSHEAR) nShW=SDRMAXSHEAR;
520  rGeo.nShearAngle=nShW;
521  rGeo.RecalcTan();
522  Point aRU(aPt0);
523  aRU.AdjustX(nWdt );
524  aRU.AdjustY(nHgt );
525  rRect=tools::Rectangle(aPt0,aRU);
526 }
527 
528 
529 void OrthoDistance8(const Point& rPt0, Point& rPt, bool bBigOrtho)
530 {
531  long dx=rPt.X()-rPt0.X();
532  long dy=rPt.Y()-rPt0.Y();
533  long dxa=std::abs(dx);
534  long dya=std::abs(dy);
535  if (dx==0 || dy==0 || dxa==dya) return;
536  if (dxa>=dya*2) { rPt.setY(rPt0.Y() ); return; }
537  if (dya>=dxa*2) { rPt.setX(rPt0.X() ); return; }
538  if ((dxa<dya) != bBigOrtho) {
539  rPt.setY(rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) ) );
540  } else {
541  rPt.setX(rPt0.X()+(dya* (dx>=0 ? 1 : -1) ) );
542  }
543 }
544 
545 void OrthoDistance4(const Point& rPt0, Point& rPt, bool bBigOrtho)
546 {
547  long dx=rPt.X()-rPt0.X();
548  long dy=rPt.Y()-rPt0.Y();
549  long dxa=std::abs(dx);
550  long dya=std::abs(dy);
551  if ((dxa<dya) != bBigOrtho) {
552  rPt.setY(rPt0.Y()+(dxa* (dy>=0 ? 1 : -1) ) );
553  } else {
554  rPt.setX(rPt0.X()+(dya* (dx>=0 ? 1 : -1) ) );
555  }
556 }
557 
558 
559 long BigMulDiv(long nVal, long nMul, long nDiv)
560 {
561  BigInt aVal(nVal);
562  aVal*=nMul;
563  if (aVal.IsNeg()!=(nDiv<0)) {
564  aVal-=nDiv/2; // to round correctly
565  } else {
566  aVal+=nDiv/2; // to round correctly
567  }
568  if(nDiv)
569  {
570  aVal/=nDiv;
571  return long(aVal);
572  }
573  return 0x7fffffff;
574 }
575 
576 // How many eU units fit into a mm, respectively an inch?
577 // Or: How many mm, respectively inches, are there in an eU (and then give me the inverse)
578 
580 {
581  switch (eU) {
582  case MapUnit::Map1000thInch: return FrPair(1000,1);
583  case MapUnit::Map100thInch : return FrPair( 100,1);
584  case MapUnit::Map10thInch : return FrPair( 10,1);
585  case MapUnit::MapInch : return FrPair( 1,1);
586  case MapUnit::MapPoint : return FrPair( 72,1);
587  case MapUnit::MapTwip : return FrPair(1440,1);
588  case MapUnit::Map100thMM : return FrPair( 100,1);
589  case MapUnit::Map10thMM : return FrPair( 10,1);
590  case MapUnit::MapMM : return FrPair( 1,1);
591  case MapUnit::MapCM : return FrPair( 1,10);
592  case MapUnit::MapPixel : {
594  pVD->SetMapMode(MapMode(MapUnit::Map100thMM));
595  Point aP(pVD->PixelToLogic(Point(64,64))); // 64 pixels for more accuracy
596  return FrPair(6400,aP.X(),6400,aP.Y());
597  }
598  case MapUnit::MapAppFont: case MapUnit::MapSysFont: {
600  pVD->SetMapMode(MapMode(eU));
601  Point aP(pVD->LogicToPixel(Point(32,32))); // 32 units for more accuracy
602  pVD->SetMapMode(MapMode(MapUnit::Map100thMM));
603  aP=pVD->PixelToLogic(aP);
604  return FrPair(3200,aP.X(),3200,aP.Y());
605  }
606  default: break;
607  }
608  return Fraction(1,1);
609 }
610 
612 {
613  switch (eU) {
614  case FieldUnit::INCH : return FrPair( 1,1);
615  case FieldUnit::POINT : return FrPair( 72,1);
616  case FieldUnit::TWIP : return FrPair(1440,1);
617  case FieldUnit::MM_100TH : return FrPair( 100,1);
618  case FieldUnit::MM : return FrPair( 1,1);
619  case FieldUnit::CM : return FrPair( 1,10);
620  case FieldUnit::M : return FrPair( 1,1000);
621  case FieldUnit::KM : return FrPair( 1,1000000);
622  case FieldUnit::PICA : return FrPair( 6,1);
623  case FieldUnit::FOOT : return FrPair( 1,12);
624  case FieldUnit::MILE : return FrPair( 1,63360);
625  default: break;
626  }
627  return Fraction(1,1);
628 }
629 
630 // Calculate the factor that we need to convert units from eS to eD.
631 // e. g. GetMapFactor(UNIT_MM,UNIT_100TH_MM) => 100.
632 
634 {
635  if (eS==eD) return FrPair(1,1,1,1);
636  FrPair aS(GetInchOrMM(eS));
637  FrPair aD(GetInchOrMM(eD));
638  bool bSInch=IsInch(eS);
639  bool bDInch=IsInch(eD);
640  FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
641  if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
642  if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
643  return aRet;
644 };
645 
647 {
648  if (eS==eD) return FrPair(1,1,1,1);
649  FrPair aS(GetInchOrMM(eS));
650  FrPair aD(GetInchOrMM(eD));
651  bool bSInch=IsInch(eS);
652  bool bDInch=IsInch(eD);
653  FrPair aRet(aD.X()/aS.X(),aD.Y()/aS.Y());
654  if (bSInch && !bDInch) { aRet.X()*=Fraction(127,5); aRet.Y()*=Fraction(127,5); }
655  if (!bSInch && bDInch) { aRet.X()*=Fraction(5,127); aRet.Y()*=Fraction(5,127); }
656  return aRet;
657 };
658 
659 
660  // 1 mile = 8 furlong = 63.360" = 1.609.344,0mm
661  // 1 furlong = 10 chains = 7.920" = 201.168,0mm
662  // 1 chain = 4 poles = 792" = 20.116,8mm
663  // 1 pole = 5 1/2 yd = 198" = 5.029,2mm
664  // 1 yd = 3 ft = 36" = 914,4mm
665  // 1 ft = 12 " = 1" = 304,8mm
666 
667 static void GetMeterOrInch(MapUnit eMU, short& rnComma, long& rnMul, long& rnDiv, bool& rbMetr, bool& rbInch)
668 {
669  rnMul=1; rnDiv=1;
670  short nComma=0;
671  bool bMetr = false, bInch = false;
672  switch (eMU) {
673  // Metrically
674  case MapUnit::Map100thMM : bMetr = true; nComma=5; break;
675  case MapUnit::Map10thMM : bMetr = true; nComma=4; break;
676  case MapUnit::MapMM : bMetr = true; nComma=3; break;
677  case MapUnit::MapCM : bMetr = true; nComma=2; break;
678  // Inch
679  case MapUnit::Map1000thInch: bInch = true; nComma=3; break;
680  case MapUnit::Map100thInch : bInch = true; nComma=2; break;
681  case MapUnit::Map10thInch : bInch = true; nComma=1; break;
682  case MapUnit::MapInch : bInch = true; nComma=0; break;
683  case MapUnit::MapPoint : bInch = true; rnDiv=72; break; // 1Pt = 1/72"
684  case MapUnit::MapTwip : bInch = true; rnDiv=144; nComma=1; break; // 1Twip = 1/1440"
685  // Others
686  case MapUnit::MapPixel : break;
687  case MapUnit::MapSysFont : break;
688  case MapUnit::MapAppFont : break;
689  case MapUnit::MapRelative : break;
690  default: break;
691  } // switch
692  rnComma=nComma;
693  rbMetr=bMetr;
694  rbInch=bInch;
695 }
696 
697 
699 {
700  bool bSrcMetr,bSrcInch,bDstMetr,bDstInch;
701  long nMul1,nDiv1,nMul2,nDiv2;
702  short nComma1,nComma2;
703  // first: normalize to m or in
704  GetMeterOrInch(eSrcMU,nComma1,nMul1,nDiv1,bSrcMetr,bSrcInch);
705  GetMeterOrInch(eDstMU,nComma2,nMul2,nDiv2,bDstMetr,bDstInch);
706  nMul1*=nDiv2;
707  nDiv1*=nMul2;
708  nComma1=nComma1-nComma2;
709 
710  if (bSrcInch && bDstMetr) {
711  nComma1+=4;
712  nMul1*=254;
713  }
714  if (bSrcMetr && bDstInch) {
715  nComma1-=4;
716  nDiv1*=254;
717  }
718 
719  // temporary fraction for canceling
720  Fraction aTempFract(nMul1,nDiv1);
721  nMul1=aTempFract.GetNumerator();
722  nDiv1=aTempFract.GetDenominator();
723 
724  nMul_=nMul1;
725  nDiv_=nDiv1;
726  nComma_=nComma1;
727  bDirty=false;
728 }
729 
730 
731 OUString SdrFormatter::GetStr(long nVal) const
732 {
733  const OUString aNullCode("0");
734 
735  if(!nVal)
736  {
737  return aNullCode;
738  }
739 
740  // we may lose some decimal places here, because of MulDiv instead of Real
741  bool bNeg(nVal < 0);
742  SvtSysLocale aSysLoc;
743  const LocaleDataWrapper& rLoc = aSysLoc.GetLocaleData();
744 
745  if (bDirty)
746  const_cast<SdrFormatter*>(this)->Undirty();
747 
748  sal_Int16 nC(nComma_);
749 
750  if(bNeg)
751  nVal = -nVal;
752 
753  while(nC <= -3)
754  {
755  nVal *= 1000;
756  nC += 3;
757  }
758 
759  while(nC <= -1)
760  {
761  nVal *= 10;
762  nC++;
763  }
764 
765  if(nMul_ != nDiv_)
766  nVal = BigMulDiv(nVal, nMul_, nDiv_);
767 
768  OUStringBuffer aStr = OUString::number(nVal);
769 
770  if(nC > 0 && aStr.getLength() <= nC )
771  {
772  // decimal separator necessary
773  sal_Int32 nCount(nC - aStr.getLength());
774 
776  nCount++;
777 
778  for(sal_Int32 i=0; i<nCount; i++)
779  aStr.insert(0, aNullCode);
780 
781  // remove superfluous decimal points
782  sal_Int32 nNumDigits(LocaleDataWrapper::getNumDigits());
783  sal_Int32 nWeg(nC - nNumDigits);
784 
785  if(nWeg > 0)
786  {
787  // TODO: we should round here
788  aStr.remove(aStr.getLength() - nWeg, nWeg);
789  nC = nNumDigits;
790  }
791  }
792 
793  // remember everything before the decimal separator for later
794  sal_Int32 nForComma(aStr.getLength() - nC);
795 
796  if(nC > 0)
797  {
798  // insert comma char (decimal separator)
799  // remove trailing zeros
800  while(nC > 0 && aStr[aStr.getLength() - 1] == aNullCode[0])
801  {
802  aStr.remove(aStr.getLength() - 1, 1);
803  nC--;
804  }
805 
806  if(nC > 0)
807  {
808  // do we still have decimal places?
809  sal_Unicode cDec(rLoc.getNumDecimalSep()[0]);
810  aStr.insert(nForComma, cDec);
811  }
812  }
813 
814  // add in thousands separator (if necessary)
815  if( nForComma > 3 )
816  {
817  const OUString& aThoSep( rLoc.getNumThousandSep() );
818  if ( aThoSep.getLength() > 0 )
819  {
820  sal_Unicode cTho( aThoSep[0] );
821  sal_Int32 i(nForComma - 3);
822 
823  while(i > 0)
824  {
825  aStr.insert(i, cTho);
826  i -= 3;
827  }
828  }
829  }
830 
831  if(aStr.isEmpty())
832  aStr.append(aNullCode);
833 
834  if(bNeg && (aStr.getLength() > 1 || aStr[0] != aNullCode[0]))
835  {
836  aStr.insert(0, "-");
837  }
838 
839  return aStr.makeStringAndClear();
840 }
841 
843 {
844  switch(eUnit)
845  {
846  // metrically
847  case MapUnit::Map100thMM :
848  return "/100mm";
849  case MapUnit::Map10thMM :
850  return "/10mm";
851  case MapUnit::MapMM :
852  return "mm";
853  case MapUnit::MapCM :
854  return "cm";
855 
856  // Inch
857  case MapUnit::Map1000thInch:
858  return "/1000\"";
859  case MapUnit::Map100thInch :
860  return "/100\"";
861  case MapUnit::Map10thInch :
862  return "/10\"";
863  case MapUnit::MapInch :
864  return "\"";
865  case MapUnit::MapPoint :
866  return "pt";
867  case MapUnit::MapTwip :
868  return "twip";
869 
870  // others
871  case MapUnit::MapPixel :
872  return "pixel";
873  case MapUnit::MapSysFont :
874  return "sysfont";
875  case MapUnit::MapAppFont :
876  return "appfont";
877  case MapUnit::MapRelative :
878  return "%";
879  default:
880  return OUString();
881  }
882 }
883 
885 {
886  switch(eUnit)
887  {
888  default :
889  case FieldUnit::NONE :
890  case FieldUnit::CUSTOM :
891  return OUString();
892 
893  // metrically
894  case FieldUnit::MM_100TH:
895  return "/100mm";
896  case FieldUnit::MM :
897  return "mm";
898  case FieldUnit::CM :
899  return "cm";
900  case FieldUnit::M :
901  return "m";
902  case FieldUnit::KM :
903  return "km";
904 
905  // Inch
906  case FieldUnit::TWIP :
907  return "twip";
908  case FieldUnit::POINT :
909  return "pt";
910  case FieldUnit::PICA :
911  return "pica";
912  case FieldUnit::INCH :
913  return "\"";
914  case FieldUnit::FOOT :
915  return "ft";
916  case FieldUnit::MILE :
917  return "mile(s)";
918 
919  // others
920  case FieldUnit::PERCENT:
921  return "%";
922  }
923 }
924 
925 
926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
long Width() const
static OUString GetUnitStr(MapUnit eUnit)
Definition: svdtrans.cxx:842
FieldUnit
void ShearXPoly(XPolygon &rPoly, const Point &rRef, double tn, bool bVShear)
Definition: svdtrans.cxx:154
sal_uInt16 Count() const
Definition: _xpoly.cxx:890
#define SDRMAXSHEAR
Definition: svdtrans.hxx:46
void ShearPoint(Point &rPnt, const Point &rRef, double tn, bool bVShear=false)
Definition: svdtrans.hxx:122
long FRound(double fVal)
double GetCrookAngle(Point &rPnt, const Point &rCenter, const Point &rRad, bool bVertical)
rPnt.X/rPnt.Y is set to rCenter.X or rCenter.Y! We then only need to rotate rPnt by rCenter...
Definition: svdtrans.hxx:135
void ResizePoint(Point &rPnt, const Point &rRef, const Fraction &xFract, const Fraction &yFract)
Definition: svdtrans.hxx:106
long Height() const
double nSin
Definition: svdtrans.hxx:219
void ResizePoly(tools::Polygon &rPoly, const Point &rRef, const Fraction &xFact, const Fraction &yFact)
Definition: svdtrans.cxx:64
Point BottomLeft() const
void ResizeXPoly(XPolygon &rPoly, const Point &rRef, const Fraction &xFact, const Fraction &yFact)
Definition: svdtrans.cxx:72
void Poly2Rect(const tools::Polygon &rPol, tools::Rectangle &rRect, GeoStat &rGeo)
Definition: svdtrans.cxx:487
double ny
long nRotationAngle
Definition: svdtrans.hxx:216
static sal_uInt16 getNumDigits()
static bool isNumLeadingZero()
static FrPair GetInchOrMM(MapUnit eU)
Definition: svdtrans.cxx:579
void RotatePoly(tools::Polygon &rPoly, const Point &rRef, double sn, double cs)
Definition: svdtrans.cxx:80
void RecalcTan()
Definition: svdtrans.cxx:463
float x
long NormAngle36000(long a)
Normalize angle to -180.00..179.99.
Definition: svdtrans.cxx:408
double CrookRotateXPoint(Point &rPnt, Point *pC1, Point *pC2, const Point &rCenter, const Point &rRad, double &rSin, double &rCos, bool bVert)
The following methods accept a point of an XPolygon, whereas the neighbouring control points of the a...
Definition: svdtrans.cxx:162
long AdjustBottom(long nVertMoveDelta)
void ShearPoly(tools::Polygon &rPoly, const Point &rRef, double tn)
Definition: svdtrans.cxx:146
long GetLen(const Point &rPnt)
Determine sector within the cartesian coordinate system.
Definition: svdtrans.cxx:425
sal_uInt16 sal_Unicode
void Move(long nHorzMove, long nVertMove)
Definition: _xpoly.cxx:381
const LocaleDataWrapper & GetLocaleData() const
long Right() const
void CrookRotatePoly(XPolygon &rPoly, const Point &rCenter, const Point &rRad, bool bVert)
Definition: svdtrans.cxx:291
static void GetMeterOrInch(MapUnit eMU, short &rnComma, long &rnMul, long &rnDiv, bool &rbMetr, bool &rbInch)
Definition: svdtrans.cxx:667
double CrookStretchXPoint(Point &rPnt, Point *pC1, Point *pC2, const Point &rCenter, const Point &rRad, double &rSin, double &rCos, bool bVert, const tools::Rectangle &rRefRect)
Definition: svdtrans.cxx:271
The transformation of a rectangle into a polygon, by using angle parameters from GeoStat.
Definition: svdtrans.hxx:214
int nCount
sal_uInt16 GetAngleSector(long nAngle)
Normalize angle to 0.00..359.99.
Definition: svdtrans.cxx:415
long Top() const
float y
Point BottomRight() const
const OUString & getNumDecimalSep() const
void ResizeRect(tools::Rectangle &rRect, const Point &rRef, const Fraction &rxFact, const Fraction &ryFact)
Definition: svdtrans.cxx:37
void CrookStretchPoly(XPolygon &rPoly, const Point &rCenter, const Point &rRad, bool bVert, const tools::Rectangle &rRefRect)
Definition: svdtrans.cxx:337
double nCos
Definition: svdtrans.hxx:220
void SetTop(long v)
int i
MapUnit eSrcMU
Definition: svdtrans.hxx:280
void MirrorXPoly(XPolygon &rPoly, const Point &rRef1, const Point &rRef2)
Definition: svdtrans.cxx:138
short nComma_
Definition: svdtrans.hxx:278
uno_Any a
const Fraction & Y() const
Definition: svdtrans.hxx:246
void MirrorPoint(Point &rPnt, const Point &rRef1, const Point &rRef2)
Definition: svdtrans.cxx:104
const Fraction & X() const
Definition: svdtrans.hxx:245
void SetRight(long v)
double nTan
Definition: svdtrans.hxx:218
void OrthoDistance8(const Point &rPt0, Point &rPt, bool bBigOrtho)
Definition: svdtrans.cxx:529
long Bottom() const
sal_uInt16 GetSize() const
tools::Polygon Rect2Poly(const tools::Rectangle &rRect, const GeoStat &rGeo)
Definition: svdtrans.cxx:474
bool IsNeg() const
MapUnit eDstMU
Definition: svdtrans.hxx:281
long nShearAngle
Definition: svdtrans.hxx:217
long BigMulDiv(long nVal, long nMul, long nDiv)
Definition: svdtrans.cxx:559
long NormAngle18000(long a)
Definition: svdtrans.cxx:401
void RotatePoint(Point &rPnt, const Point &rRef, double sn, double cs)
Definition: svdtrans.hxx:114
FrPair GetMapFactor(MapUnit eS, MapUnit eD)
Definition: svdtrans.cxx:633
long AdjustRight(long nHorzMoveDelta)
sal_Int32 GetDenominator() const
double nx
void RecalcSinCos()
Definition: svdtrans.cxx:451
bool IsControl(sal_uInt16 nPos) const
short path to read the CONTROL flag directly (TODO: better explain what the sense behind this flag is...
Definition: _xpoly.cxx:466
double CrookSlantXPoint(Point &rPnt, Point *pC1, Point *pC2, const Point &rCenter, const Point &rRad, double &rSin, double &rCos, bool bVert)
Definition: svdtrans.cxx:216
void SetBottom(long v)
#define F_PI18000
sal_Int32 GetNumerator() const
long GetAngle(const Point &rPnt)
The Y axis points down! The function negates the Y axis, when calculating the angle, such that GetAngle(Point(0,-1))=90 deg.
Definition: svdtrans.cxx:386
long Left() const
bool IsInch(MapUnit eU)
Definition: svdtrans.hxx:259
const OUString & getNumThousandSep() const
SVX_DLLPRIVATE void Undirty()
Definition: svdtrans.cxx:698
OUString GetStr(long nVal) const
Definition: svdtrans.cxx:731
void SetLeft(long v)
void RotateXPoly(XPolygon &rPoly, const Point &rRef, double sn, double cs)
Definition: svdtrans.cxx:88
MapUnit
#define SAL_WARN(area, stream)
bool IsValid() const
void CrookSlantPoly(XPolygon &rPoly, const Point &rCenter, const Point &rRad, bool bVert)
Definition: svdtrans.cxx:314
sal_uInt16 GetPointCount() const
Definition: _xpoly.cxx:346
void MoveXPoly(XPolygon &rPoly, const Size &S)
Definition: svdtrans.cxx:32
void OrthoDistance4(const Point &rPt0, Point &rPt, bool bBigOrtho)
Definition: svdtrans.cxx:545
aStr
Point TopRight() const