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