bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / outdev / map.cxx
blob6182541e19ffb9b4e714e929a4b9cbbbcffde907
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/bigint.hxx>
21 #include <tools/debug.hxx>
22 #include <vcl/cursor.hxx>
23 #include <vcl/gdimtf.hxx>
24 #include <vcl/lineinfo.hxx>
25 #include <vcl/metaact.hxx>
26 #include <vcl/virdev.hxx>
27 #include <vcl/wrkwin.hxx>
28 #include <sal/log.hxx>
29 #include <osl/diagnose.h>
31 #include <svdata.hxx>
32 #include <window.h>
33 #include <outdev.h>
35 #include <basegfx/matrix/b2dhommatrix.hxx>
36 #include <o3tl/enumarray.hxx>
38 // we don't actually handle units beyond, hence the zeros in the arrays
39 static const MapUnit s_MaxValidUnit = MapUnit::MapPixel;
40 static const o3tl::enumarray<MapUnit,long> aImplNumeratorAry =
41 { 1, 1, 5, 50, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 };
42 static const o3tl::enumarray<MapUnit,long> aImplDenominatorAry =
43 { 2540, 254, 127, 127, 1000, 100, 10, 1, 72, 1440, 1, 0, 0, 0 };
46 Reduces accuracy until it is a fraction (should become
47 ctor fraction once); we could also do this with BigInts
50 static Fraction ImplMakeFraction( long nN1, long nN2, long nD1, long nD2 )
52 if( nD1 == 0 || nD2 == 0 ) //under these bad circumstances the following while loop will be endless
54 SAL_WARN("vcl.gdi", "Invalid parameter for ImplMakeFraction");
55 return Fraction( 1, 1 );
58 long i = 1;
60 if ( nN1 < 0 ) { i = -i; nN1 = -nN1; }
61 if ( nN2 < 0 ) { i = -i; nN2 = -nN2; }
62 if ( nD1 < 0 ) { i = -i; nD1 = -nD1; }
63 if ( nD2 < 0 ) { i = -i; nD2 = -nD2; }
64 // all positive; i sign
66 Fraction aF = Fraction( i*nN1, nD1 ) * Fraction( nN2, nD2 );
68 while ( !aF.IsValid() ) {
69 if ( nN1 > nN2 )
70 nN1 = (nN1 + 1) / 2;
71 else
72 nN2 = (nN2 + 1) / 2;
73 if ( nD1 > nD2 )
74 nD1 = (nD1 + 1) / 2;
75 else
76 nD2 = (nD2 + 1) / 2;
78 aF = Fraction( i*nN1, nD1 ) * Fraction( nN2, nD2 );
81 aF.ReduceInaccurate(32);
82 return aF;
85 // Fraction.GetNumerator()
86 // Fraction.GetDenominator() > 0
87 // rOutRes.nPixPerInch? > 0
88 // rMapRes.nMapScNum?
89 // rMapRes.nMapScDenom? > 0
91 static void ImplCalcBigIntThreshold( long nDPIX, long nDPIY,
92 const ImplMapRes& rMapRes,
93 ImplThresholdRes& rThresRes )
95 if ( nDPIX && (LONG_MAX / nDPIX < std::abs( rMapRes.mnMapScNumX ) ) ) // #111139# avoid div by zero
97 rThresRes.mnThresLogToPixX = 0;
98 rThresRes.mnThresPixToLogX = 0;
100 else
102 // calculate thresholds for BigInt arithmetic
103 long nDenomHalfX = rMapRes.mnMapScDenomX / 2;
104 sal_uLong nDenomX = rMapRes.mnMapScDenomX;
105 long nProductX = nDPIX * rMapRes.mnMapScNumX;
107 if ( !nProductX )
108 rThresRes.mnThresLogToPixX = LONG_MAX;
109 else
110 rThresRes.mnThresLogToPixX = std::abs( (LONG_MAX - nDenomHalfX) / nProductX );
112 if ( !nDenomX )
113 rThresRes.mnThresPixToLogX = LONG_MAX;
114 else if ( nProductX >= 0 )
115 rThresRes.mnThresPixToLogX = static_cast<long>((sal_uLong(LONG_MAX) - static_cast<sal_uLong>( nProductX/2)) / nDenomX);
116 else
117 rThresRes.mnThresPixToLogX = static_cast<long>((sal_uLong(LONG_MAX) + static_cast<sal_uLong>(-nProductX/2)) / nDenomX);
120 if ( nDPIY && (LONG_MAX / nDPIY < std::abs( rMapRes.mnMapScNumY ) ) ) // #111139# avoid div by zero
122 rThresRes.mnThresLogToPixY = 0;
123 rThresRes.mnThresPixToLogY = 0;
125 else
127 // calculate thresholds for BigInt arithmetic
128 long nDenomHalfY = rMapRes.mnMapScDenomY / 2;
129 sal_uLong nDenomY = rMapRes.mnMapScDenomY;
130 long nProductY = nDPIY * rMapRes.mnMapScNumY;
132 if ( !nProductY )
133 rThresRes.mnThresLogToPixY = LONG_MAX;
134 else
135 rThresRes.mnThresLogToPixY = std::abs( (LONG_MAX - nDenomHalfY) / nProductY );
137 if ( !nDenomY )
138 rThresRes.mnThresPixToLogY = LONG_MAX;
139 else if ( nProductY >= 0 )
140 rThresRes.mnThresPixToLogY = static_cast<long>((sal_uLong(LONG_MAX) - static_cast<sal_uLong>( nProductY/2)) / nDenomY);
141 else
142 rThresRes.mnThresPixToLogY = static_cast<long>((sal_uLong(LONG_MAX) + static_cast<sal_uLong>(-nProductY/2)) / nDenomY);
145 rThresRes.mnThresLogToPixX /= 2;
146 rThresRes.mnThresLogToPixY /= 2;
147 rThresRes.mnThresPixToLogX /= 2;
148 rThresRes.mnThresPixToLogY /= 2;
151 static void ImplCalcMapResolution( const MapMode& rMapMode,
152 long nDPIX, long nDPIY, ImplMapRes& rMapRes )
154 switch ( rMapMode.GetMapUnit() )
156 case MapUnit::MapRelative:
157 break;
158 case MapUnit::Map100thMM:
159 rMapRes.mnMapScNumX = 1;
160 rMapRes.mnMapScDenomX = 2540;
161 rMapRes.mnMapScNumY = 1;
162 rMapRes.mnMapScDenomY = 2540;
163 break;
164 case MapUnit::Map10thMM:
165 rMapRes.mnMapScNumX = 1;
166 rMapRes.mnMapScDenomX = 254;
167 rMapRes.mnMapScNumY = 1;
168 rMapRes.mnMapScDenomY = 254;
169 break;
170 case MapUnit::MapMM:
171 rMapRes.mnMapScNumX = 5; // 10
172 rMapRes.mnMapScDenomX = 127; // 254
173 rMapRes.mnMapScNumY = 5; // 10
174 rMapRes.mnMapScDenomY = 127; // 254
175 break;
176 case MapUnit::MapCM:
177 rMapRes.mnMapScNumX = 50; // 100
178 rMapRes.mnMapScDenomX = 127; // 254
179 rMapRes.mnMapScNumY = 50; // 100
180 rMapRes.mnMapScDenomY = 127; // 254
181 break;
182 case MapUnit::Map1000thInch:
183 rMapRes.mnMapScNumX = 1;
184 rMapRes.mnMapScDenomX = 1000;
185 rMapRes.mnMapScNumY = 1;
186 rMapRes.mnMapScDenomY = 1000;
187 break;
188 case MapUnit::Map100thInch:
189 rMapRes.mnMapScNumX = 1;
190 rMapRes.mnMapScDenomX = 100;
191 rMapRes.mnMapScNumY = 1;
192 rMapRes.mnMapScDenomY = 100;
193 break;
194 case MapUnit::Map10thInch:
195 rMapRes.mnMapScNumX = 1;
196 rMapRes.mnMapScDenomX = 10;
197 rMapRes.mnMapScNumY = 1;
198 rMapRes.mnMapScDenomY = 10;
199 break;
200 case MapUnit::MapInch:
201 rMapRes.mnMapScNumX = 1;
202 rMapRes.mnMapScDenomX = 1;
203 rMapRes.mnMapScNumY = 1;
204 rMapRes.mnMapScDenomY = 1;
205 break;
206 case MapUnit::MapPoint:
207 rMapRes.mnMapScNumX = 1;
208 rMapRes.mnMapScDenomX = 72;
209 rMapRes.mnMapScNumY = 1;
210 rMapRes.mnMapScDenomY = 72;
211 break;
212 case MapUnit::MapTwip:
213 rMapRes.mnMapScNumX = 1;
214 rMapRes.mnMapScDenomX = 1440;
215 rMapRes.mnMapScNumY = 1;
216 rMapRes.mnMapScDenomY = 1440;
217 break;
218 case MapUnit::MapPixel:
219 rMapRes.mnMapScNumX = 1;
220 rMapRes.mnMapScDenomX = nDPIX;
221 rMapRes.mnMapScNumY = 1;
222 rMapRes.mnMapScDenomY = nDPIY;
223 break;
224 case MapUnit::MapSysFont:
225 case MapUnit::MapAppFont:
227 ImplSVData* pSVData = ImplGetSVData();
228 if ( !pSVData->maGDIData.mnAppFontX )
230 if( pSVData->maWinData.mpFirstFrame )
231 vcl::Window::ImplInitAppFontData( pSVData->maWinData.mpFirstFrame );
232 else
234 ScopedVclPtrInstance<WorkWindow> pWin( nullptr, 0 );
235 vcl::Window::ImplInitAppFontData( pWin );
238 rMapRes.mnMapScNumX = pSVData->maGDIData.mnAppFontX;
239 rMapRes.mnMapScDenomX = nDPIX * 40;
240 rMapRes.mnMapScNumY = pSVData->maGDIData.mnAppFontY;
241 rMapRes.mnMapScDenomY = nDPIY * 80;
243 break;
244 default:
245 OSL_FAIL( "unhandled MapUnit" );
246 break;
249 const Fraction& aScaleX = rMapMode.GetScaleX();
250 const Fraction& aScaleY = rMapMode.GetScaleY();
252 // set offset according to MapMode
253 Point aOrigin = rMapMode.GetOrigin();
254 if ( rMapMode.GetMapUnit() != MapUnit::MapRelative )
256 rMapRes.mnMapOfsX = aOrigin.X();
257 rMapRes.mnMapOfsY = aOrigin.Y();
259 else
261 auto nXNumerator = aScaleX.GetNumerator();
262 auto nYNumerator = aScaleY.GetNumerator();
263 assert(nXNumerator != 0 && nYNumerator != 0);
265 BigInt aX( rMapRes.mnMapOfsX );
266 aX *= BigInt( aScaleX.GetDenominator() );
267 if ( rMapRes.mnMapOfsX >= 0 )
269 if (nXNumerator >= 0)
270 aX += BigInt(nXNumerator / 2);
271 else
272 aX -= BigInt((nXNumerator + 1) / 2);
274 else
276 if (nXNumerator >= 0 )
277 aX -= BigInt((nXNumerator - 1) / 2);
278 else
279 aX += BigInt(nXNumerator / 2);
281 aX /= BigInt(nXNumerator);
282 rMapRes.mnMapOfsX = static_cast<long>(aX) + aOrigin.X();
283 BigInt aY( rMapRes.mnMapOfsY );
284 aY *= BigInt( aScaleY.GetDenominator() );
285 if( rMapRes.mnMapOfsY >= 0 )
287 if (nYNumerator >= 0)
288 aY += BigInt(nYNumerator / 2);
289 else
290 aY -= BigInt((nYNumerator + 1) / 2);
292 else
294 if (nYNumerator >= 0)
295 aY -= BigInt((nYNumerator - 1) / 2);
296 else
297 aY += BigInt(nYNumerator / 2);
299 aY /= BigInt(nYNumerator);
300 rMapRes.mnMapOfsY = static_cast<long>(aY) + aOrigin.Y();
303 // calculate scaling factor according to MapMode
304 // aTemp? = rMapRes.mnMapSc? * aScale?
305 Fraction aTempX = ImplMakeFraction( rMapRes.mnMapScNumX,
306 aScaleX.GetNumerator(),
307 rMapRes.mnMapScDenomX,
308 aScaleX.GetDenominator() );
309 Fraction aTempY = ImplMakeFraction( rMapRes.mnMapScNumY,
310 aScaleY.GetNumerator(),
311 rMapRes.mnMapScDenomY,
312 aScaleY.GetDenominator() );
313 rMapRes.mnMapScNumX = aTempX.GetNumerator();
314 rMapRes.mnMapScDenomX = aTempX.GetDenominator();
315 rMapRes.mnMapScNumY = aTempY.GetNumerator();
316 rMapRes.mnMapScDenomY = aTempY.GetDenominator();
319 static void ImplCalcMapResolution( const MapMode& rMapMode,
320 long nDPIX, long nDPIY,
321 ImplMapRes& rMapRes,
322 ImplThresholdRes& rThresRes )
324 ImplCalcMapResolution( rMapMode, nDPIX, nDPIY, rMapRes );
325 ImplCalcBigIntThreshold( nDPIX, nDPIY, rMapRes, rThresRes );
328 // #i75163#
329 void OutputDevice::ImplInvalidateViewTransform()
331 if(!mpOutDevData)
332 return;
334 if(mpOutDevData->mpViewTransform)
336 delete mpOutDevData->mpViewTransform;
337 mpOutDevData->mpViewTransform = nullptr;
340 if(mpOutDevData->mpInverseViewTransform)
342 delete mpOutDevData->mpInverseViewTransform;
343 mpOutDevData->mpInverseViewTransform = nullptr;
347 static long ImplLogicToPixel( long n, long nDPI, long nMapNum, long nMapDenom,
348 long nThres )
350 assert(nDPI > 0);
351 #if (SAL_TYPES_SIZEOFLONG < 8)
352 if( (+n < nThres) && (-n < nThres) )
354 n *= nMapNum * nDPI;
355 if( nMapDenom != 1 )
357 n = (2 * n) / nMapDenom;
358 if( n < 0 ) --n; else ++n;
359 n /= 2;
362 else
363 #else
364 (void) nThres;
365 assert(nMapNum >= 0);
366 assert(nMapNum == 0 || std::abs(n) < std::numeric_limits<long>::max() / nMapNum / nDPI); //detect overflows
367 #endif
369 sal_Int64 n64 = n;
370 n64 *= nMapNum;
371 n64 *= nDPI;
372 if( nMapDenom == 1 )
373 n = static_cast<long>(n64);
374 else
376 n = static_cast<long>(2 * n64 / nMapDenom);
377 if( n < 0 ) --n; else ++n;
378 n /= 2;
381 return n;
384 static long ImplPixelToLogic( long n, long nDPI, long nMapNum, long nMapDenom,
385 long nThres )
387 assert(nDPI > 0);
388 long nDenom = nDPI * nMapNum;
389 if (nDenom == 0)
391 return 0;
394 #if (SAL_TYPES_SIZEOFLONG < 8)
395 if( (+n < nThres) && (-n < nThres) )
396 n = (2 * n * nMapDenom) / nDenom;
397 else
398 #else
399 (void) nThres;
400 #endif
402 sal_Int64 n64 = n;
403 n64 *= nMapDenom;
404 n = static_cast<long>(2 * n64 / nDenom);
406 if( n < 0 ) --n; else ++n;
407 return (n / 2);
410 long OutputDevice::ImplLogicXToDevicePixel( long nX ) const
412 if ( !mbMap )
413 return nX+mnOutOffX;
415 return ImplLogicToPixel( nX + maMapRes.mnMapOfsX, mnDPIX,
416 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
417 maThresRes.mnThresLogToPixX )+mnOutOffX+mnOutOffOrigX;
420 long OutputDevice::ImplLogicYToDevicePixel( long nY ) const
422 if ( !mbMap )
423 return nY+mnOutOffY;
425 return ImplLogicToPixel( nY + maMapRes.mnMapOfsY, mnDPIY,
426 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
427 maThresRes.mnThresLogToPixY )+mnOutOffY+mnOutOffOrigY;
430 long OutputDevice::ImplLogicWidthToDevicePixel( long nWidth ) const
432 if ( !mbMap )
433 return nWidth;
435 return ImplLogicToPixel( nWidth, mnDPIX,
436 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
437 maThresRes.mnThresLogToPixX );
440 long OutputDevice::ImplLogicHeightToDevicePixel( long nHeight ) const
442 if ( !mbMap )
443 return nHeight;
445 return ImplLogicToPixel( nHeight, mnDPIY,
446 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
447 maThresRes.mnThresLogToPixY );
450 float OutputDevice::ImplFloatLogicHeightToDevicePixel( float fLogicHeight) const
452 if( !mbMap)
453 return fLogicHeight;
454 float fPixelHeight = (fLogicHeight * mnDPIY * maMapRes.mnMapScNumY) / maMapRes.mnMapScDenomY;
455 return fPixelHeight;
458 long OutputDevice::ImplDevicePixelToLogicWidth( long nWidth ) const
460 if ( !mbMap )
461 return nWidth;
463 return ImplPixelToLogic( nWidth, mnDPIX,
464 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
465 maThresRes.mnThresPixToLogX );
468 long OutputDevice::ImplDevicePixelToLogicHeight( long nHeight ) const
470 if ( !mbMap )
471 return nHeight;
473 return ImplPixelToLogic( nHeight, mnDPIY,
474 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
475 maThresRes.mnThresPixToLogY );
478 Point OutputDevice::ImplLogicToDevicePixel( const Point& rLogicPt ) const
480 if ( !mbMap )
481 return Point( rLogicPt.X()+mnOutOffX, rLogicPt.Y()+mnOutOffY );
483 return Point( ImplLogicToPixel( rLogicPt.X() + maMapRes.mnMapOfsX, mnDPIX,
484 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
485 maThresRes.mnThresLogToPixX )+mnOutOffX+mnOutOffOrigX,
486 ImplLogicToPixel( rLogicPt.Y() + maMapRes.mnMapOfsY, mnDPIY,
487 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
488 maThresRes.mnThresLogToPixY )+mnOutOffY+mnOutOffOrigY );
491 Size OutputDevice::ImplLogicToDevicePixel( const Size& rLogicSize ) const
493 if ( !mbMap )
494 return rLogicSize;
496 return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
497 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
498 maThresRes.mnThresLogToPixX ),
499 ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
500 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
501 maThresRes.mnThresLogToPixY ) );
504 tools::Rectangle OutputDevice::ImplLogicToDevicePixel( const tools::Rectangle& rLogicRect ) const
506 if ( rLogicRect.IsEmpty() )
507 return rLogicRect;
509 if ( !mbMap )
511 return tools::Rectangle( rLogicRect.Left()+mnOutOffX, rLogicRect.Top()+mnOutOffY,
512 rLogicRect.Right()+mnOutOffX, rLogicRect.Bottom()+mnOutOffY );
515 return tools::Rectangle( ImplLogicToPixel( rLogicRect.Left()+maMapRes.mnMapOfsX, mnDPIX,
516 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
517 maThresRes.mnThresLogToPixX )+mnOutOffX+mnOutOffOrigX,
518 ImplLogicToPixel( rLogicRect.Top()+maMapRes.mnMapOfsY, mnDPIY,
519 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
520 maThresRes.mnThresLogToPixY )+mnOutOffY+mnOutOffOrigY,
521 ImplLogicToPixel( rLogicRect.Right()+maMapRes.mnMapOfsX, mnDPIX,
522 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
523 maThresRes.mnThresLogToPixX )+mnOutOffX+mnOutOffOrigX,
524 ImplLogicToPixel( rLogicRect.Bottom()+maMapRes.mnMapOfsY, mnDPIY,
525 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
526 maThresRes.mnThresLogToPixY )+mnOutOffY+mnOutOffOrigY );
529 tools::Polygon OutputDevice::ImplLogicToDevicePixel( const tools::Polygon& rLogicPoly ) const
531 if ( !mbMap && !mnOutOffX && !mnOutOffY )
532 return rLogicPoly;
534 sal_uInt16 i;
535 sal_uInt16 nPoints = rLogicPoly.GetSize();
536 tools::Polygon aPoly( rLogicPoly );
538 // get pointer to Point-array (copy data)
539 const Point* pPointAry = aPoly.GetConstPointAry();
541 if ( mbMap )
543 for ( i = 0; i < nPoints; i++ )
545 const Point* pPt = &(pPointAry[i]);
546 Point aPt;
547 aPt.setX( ImplLogicToPixel( pPt->X()+maMapRes.mnMapOfsX, mnDPIX,
548 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
549 maThresRes.mnThresLogToPixX )+mnOutOffX+mnOutOffOrigX );
550 aPt.setY( ImplLogicToPixel( pPt->Y()+maMapRes.mnMapOfsY, mnDPIY,
551 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
552 maThresRes.mnThresLogToPixY )+mnOutOffY+mnOutOffOrigY );
553 aPoly[i] = aPt;
556 else
558 for ( i = 0; i < nPoints; i++ )
560 Point aPt = pPointAry[i];
561 aPt.AdjustX(mnOutOffX );
562 aPt.AdjustY(mnOutOffY );
563 aPoly[i] = aPt;
567 return aPoly;
570 tools::PolyPolygon OutputDevice::ImplLogicToDevicePixel( const tools::PolyPolygon& rLogicPolyPoly ) const
572 if ( !mbMap && !mnOutOffX && !mnOutOffY )
573 return rLogicPolyPoly;
575 tools::PolyPolygon aPolyPoly( rLogicPolyPoly );
576 sal_uInt16 nPoly = aPolyPoly.Count();
577 for( sal_uInt16 i = 0; i < nPoly; i++ )
579 tools::Polygon& rPoly = aPolyPoly[i];
580 rPoly = ImplLogicToDevicePixel( rPoly );
582 return aPolyPoly;
585 LineInfo OutputDevice::ImplLogicToDevicePixel( const LineInfo& rLineInfo ) const
587 LineInfo aInfo( rLineInfo );
589 if( aInfo.GetStyle() == LineStyle::Dash )
591 if( aInfo.GetDotCount() && aInfo.GetDotLen() )
592 aInfo.SetDotLen( std::max( ImplLogicWidthToDevicePixel( aInfo.GetDotLen() ), 1L ) );
593 else
594 aInfo.SetDotCount( 0 );
596 if( aInfo.GetDashCount() && aInfo.GetDashLen() )
597 aInfo.SetDashLen( std::max( ImplLogicWidthToDevicePixel( aInfo.GetDashLen() ), 1L ) );
598 else
599 aInfo.SetDashCount( 0 );
601 aInfo.SetDistance( ImplLogicWidthToDevicePixel( aInfo.GetDistance() ) );
603 if( ( !aInfo.GetDashCount() && !aInfo.GetDotCount() ) || !aInfo.GetDistance() )
604 aInfo.SetStyle( LineStyle::Solid );
607 aInfo.SetWidth( ImplLogicWidthToDevicePixel( aInfo.GetWidth() ) );
609 return aInfo;
612 tools::Rectangle OutputDevice::ImplDevicePixelToLogic( const tools::Rectangle& rPixelRect ) const
614 if ( rPixelRect.IsEmpty() )
615 return rPixelRect;
617 if ( !mbMap )
619 return tools::Rectangle( rPixelRect.Left()-mnOutOffX, rPixelRect.Top()-mnOutOffY,
620 rPixelRect.Right()-mnOutOffX, rPixelRect.Bottom()-mnOutOffY );
623 return tools::Rectangle( ImplPixelToLogic( rPixelRect.Left()-mnOutOffX-mnOutOffOrigX, mnDPIX,
624 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
625 maThresRes.mnThresPixToLogX )-maMapRes.mnMapOfsX,
626 ImplPixelToLogic( rPixelRect.Top()-mnOutOffY-mnOutOffOrigY, mnDPIY,
627 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
628 maThresRes.mnThresPixToLogY )-maMapRes.mnMapOfsY,
629 ImplPixelToLogic( rPixelRect.Right()-mnOutOffX-mnOutOffOrigX, mnDPIX,
630 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
631 maThresRes.mnThresPixToLogX )-maMapRes.mnMapOfsX,
632 ImplPixelToLogic( rPixelRect.Bottom()-mnOutOffY-mnOutOffOrigY, mnDPIY,
633 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
634 maThresRes.mnThresPixToLogY )-maMapRes.mnMapOfsY );
637 vcl::Region OutputDevice::ImplPixelToDevicePixel( const vcl::Region& rRegion ) const
639 if ( !mnOutOffX && !mnOutOffY )
640 return rRegion;
642 vcl::Region aRegion( rRegion );
643 aRegion.Move( mnOutOffX+mnOutOffOrigX, mnOutOffY+mnOutOffOrigY );
644 return aRegion;
647 void OutputDevice::EnableMapMode( bool bEnable )
649 mbMap = bEnable;
651 if( mpAlphaVDev )
652 mpAlphaVDev->EnableMapMode( bEnable );
655 void OutputDevice::SetMapMode()
658 if ( mpMetaFile )
659 mpMetaFile->AddAction( new MetaMapModeAction( MapMode() ) );
661 if ( mbMap || !maMapMode.IsDefault() )
663 mbMap = false;
664 maMapMode = MapMode();
666 // create new objects (clip region are not re-scaled)
667 mbNewFont = true;
668 mbInitFont = true;
669 if ( GetOutDevType() == OUTDEV_WINDOW )
671 if ( static_cast<vcl::Window*>(this)->mpWindowImpl->mpCursor )
672 static_cast<vcl::Window*>(this)->mpWindowImpl->mpCursor->ImplNew();
675 // #106426# Adapt logical offset when changing mapmode
676 mnOutOffLogicX = mnOutOffOrigX; // no mapping -> equal offsets
677 mnOutOffLogicY = mnOutOffOrigY;
679 // #i75163#
680 ImplInvalidateViewTransform();
683 if( mpAlphaVDev )
684 mpAlphaVDev->SetMapMode();
687 void OutputDevice::SetMapMode( const MapMode& rNewMapMode )
690 bool bRelMap = (rNewMapMode.GetMapUnit() == MapUnit::MapRelative);
692 if ( mpMetaFile )
694 mpMetaFile->AddAction( new MetaMapModeAction( rNewMapMode ) );
697 // do nothing if MapMode was not changed
698 if ( maMapMode == rNewMapMode )
699 return;
701 if( mpAlphaVDev )
702 mpAlphaVDev->SetMapMode( rNewMapMode );
704 // if default MapMode calculate nothing
705 bool bOldMap = mbMap;
706 mbMap = !rNewMapMode.IsDefault();
707 if ( mbMap )
709 // if only the origin is converted, do not scale new
710 if ( (rNewMapMode.GetMapUnit() == maMapMode.GetMapUnit()) &&
711 (rNewMapMode.GetScaleX() == maMapMode.GetScaleX()) &&
712 (rNewMapMode.GetScaleY() == maMapMode.GetScaleY()) &&
713 (bOldMap == mbMap) )
715 // set offset
716 Point aOrigin = rNewMapMode.GetOrigin();
717 maMapRes.mnMapOfsX = aOrigin.X();
718 maMapRes.mnMapOfsY = aOrigin.Y();
719 maMapMode = rNewMapMode;
721 // #i75163#
722 ImplInvalidateViewTransform();
724 return;
726 if ( !bOldMap && bRelMap )
728 maMapRes.mnMapScNumX = 1;
729 maMapRes.mnMapScNumY = 1;
730 maMapRes.mnMapScDenomX = mnDPIX;
731 maMapRes.mnMapScDenomY = mnDPIY;
732 maMapRes.mnMapOfsX = 0;
733 maMapRes.mnMapOfsY = 0;
736 // calculate new MapMode-resolution
737 ImplCalcMapResolution( rNewMapMode, mnDPIX, mnDPIY, maMapRes, maThresRes );
740 // set new MapMode
741 if ( bRelMap )
743 Point aOrigin( maMapRes.mnMapOfsX, maMapRes.mnMapOfsY );
744 // aScale? = maMapMode.GetScale?() * rNewMapMode.GetScale?()
745 Fraction aScaleX = ImplMakeFraction( maMapMode.GetScaleX().GetNumerator(),
746 rNewMapMode.GetScaleX().GetNumerator(),
747 maMapMode.GetScaleX().GetDenominator(),
748 rNewMapMode.GetScaleX().GetDenominator() );
749 Fraction aScaleY = ImplMakeFraction( maMapMode.GetScaleY().GetNumerator(),
750 rNewMapMode.GetScaleY().GetNumerator(),
751 maMapMode.GetScaleY().GetDenominator(),
752 rNewMapMode.GetScaleY().GetDenominator() );
753 maMapMode.SetOrigin( aOrigin );
754 maMapMode.SetScaleX( aScaleX );
755 maMapMode.SetScaleY( aScaleY );
757 else
758 maMapMode = rNewMapMode;
760 // create new objects (clip region are not re-scaled)
761 mbNewFont = true;
762 mbInitFont = true;
763 if ( GetOutDevType() == OUTDEV_WINDOW )
765 if ( static_cast<vcl::Window*>(this)->mpWindowImpl->mpCursor )
766 static_cast<vcl::Window*>(this)->mpWindowImpl->mpCursor->ImplNew();
769 // #106426# Adapt logical offset when changing mapmode
770 mnOutOffLogicX = ImplPixelToLogic( mnOutOffOrigX, mnDPIX,
771 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
772 maThresRes.mnThresPixToLogX );
773 mnOutOffLogicY = ImplPixelToLogic( mnOutOffOrigY, mnDPIY,
774 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
775 maThresRes.mnThresPixToLogY );
777 // #i75163#
778 ImplInvalidateViewTransform();
781 void OutputDevice::SetRelativeMapMode( const MapMode& rNewMapMode )
783 // do nothing if MapMode did not change
784 if ( maMapMode == rNewMapMode )
785 return;
787 MapUnit eOld = maMapMode.GetMapUnit();
788 MapUnit eNew = rNewMapMode.GetMapUnit();
790 // a?F = rNewMapMode.GetScale?() / maMapMode.GetScale?()
791 Fraction aXF = ImplMakeFraction( rNewMapMode.GetScaleX().GetNumerator(),
792 maMapMode.GetScaleX().GetDenominator(),
793 rNewMapMode.GetScaleX().GetDenominator(),
794 maMapMode.GetScaleX().GetNumerator() );
795 Fraction aYF = ImplMakeFraction( rNewMapMode.GetScaleY().GetNumerator(),
796 maMapMode.GetScaleY().GetDenominator(),
797 rNewMapMode.GetScaleY().GetDenominator(),
798 maMapMode.GetScaleY().GetNumerator() );
800 Point aPt( LogicToLogic( Point(), nullptr, &rNewMapMode ) );
801 if ( eNew != eOld )
803 if ( eOld > MapUnit::MapPixel )
805 SAL_WARN( "vcl.gdi", "Not implemented MapUnit" );
807 else if ( eNew > MapUnit::MapPixel )
809 SAL_WARN( "vcl.gdi", "Not implemented MapUnit" );
811 else
813 Fraction aF( aImplNumeratorAry[eNew] * aImplDenominatorAry[eOld],
814 aImplNumeratorAry[eOld] * aImplDenominatorAry[eNew] );
816 // a?F = a?F * aF
817 aXF = ImplMakeFraction( aXF.GetNumerator(), aF.GetNumerator(),
818 aXF.GetDenominator(), aF.GetDenominator() );
819 aYF = ImplMakeFraction( aYF.GetNumerator(), aF.GetNumerator(),
820 aYF.GetDenominator(), aF.GetDenominator() );
821 if ( eOld == MapUnit::MapPixel )
823 aXF *= Fraction( mnDPIX, 1 );
824 aYF *= Fraction( mnDPIY, 1 );
826 else if ( eNew == MapUnit::MapPixel )
828 aXF *= Fraction( 1, mnDPIX );
829 aYF *= Fraction( 1, mnDPIY );
834 MapMode aNewMapMode( MapUnit::MapRelative, Point( -aPt.X(), -aPt.Y() ), aXF, aYF );
835 SetMapMode( aNewMapMode );
837 if ( eNew != eOld )
838 maMapMode = rNewMapMode;
840 // #106426# Adapt logical offset when changing MapMode
841 mnOutOffLogicX = ImplPixelToLogic( mnOutOffOrigX, mnDPIX,
842 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
843 maThresRes.mnThresPixToLogX );
844 mnOutOffLogicY = ImplPixelToLogic( mnOutOffOrigY, mnDPIY,
845 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
846 maThresRes.mnThresPixToLogY );
848 if( mpAlphaVDev )
849 mpAlphaVDev->SetRelativeMapMode( rNewMapMode );
852 // #i75163#
853 basegfx::B2DHomMatrix OutputDevice::GetViewTransformation() const
855 if(mbMap && mpOutDevData)
857 if(!mpOutDevData->mpViewTransform)
859 mpOutDevData->mpViewTransform = new basegfx::B2DHomMatrix;
861 const double fScaleFactorX(static_cast<double>(mnDPIX) * static_cast<double>(maMapRes.mnMapScNumX) / static_cast<double>(maMapRes.mnMapScDenomX));
862 const double fScaleFactorY(static_cast<double>(mnDPIY) * static_cast<double>(maMapRes.mnMapScNumY) / static_cast<double>(maMapRes.mnMapScDenomY));
863 const double fZeroPointX((static_cast<double>(maMapRes.mnMapOfsX) * fScaleFactorX) + static_cast<double>(mnOutOffOrigX));
864 const double fZeroPointY((static_cast<double>(maMapRes.mnMapOfsY) * fScaleFactorY) + static_cast<double>(mnOutOffOrigY));
866 mpOutDevData->mpViewTransform->set(0, 0, fScaleFactorX);
867 mpOutDevData->mpViewTransform->set(1, 1, fScaleFactorY);
868 mpOutDevData->mpViewTransform->set(0, 2, fZeroPointX);
869 mpOutDevData->mpViewTransform->set(1, 2, fZeroPointY);
872 return *mpOutDevData->mpViewTransform;
874 else
876 return basegfx::B2DHomMatrix();
880 // #i75163#
881 basegfx::B2DHomMatrix OutputDevice::GetInverseViewTransformation() const
883 if(mbMap && mpOutDevData)
885 if(!mpOutDevData->mpInverseViewTransform)
887 GetViewTransformation();
888 mpOutDevData->mpInverseViewTransform = new basegfx::B2DHomMatrix(*mpOutDevData->mpViewTransform);
889 mpOutDevData->mpInverseViewTransform->invert();
892 return *mpOutDevData->mpInverseViewTransform;
894 else
896 return basegfx::B2DHomMatrix();
900 // #i75163#
901 basegfx::B2DHomMatrix OutputDevice::GetViewTransformation( const MapMode& rMapMode ) const
903 // #i82615#
904 ImplMapRes aMapRes;
905 ImplThresholdRes aThresRes;
906 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
908 basegfx::B2DHomMatrix aTransform;
910 const double fScaleFactorX(static_cast<double>(mnDPIX) * static_cast<double>(aMapRes.mnMapScNumX) / static_cast<double>(aMapRes.mnMapScDenomX));
911 const double fScaleFactorY(static_cast<double>(mnDPIY) * static_cast<double>(aMapRes.mnMapScNumY) / static_cast<double>(aMapRes.mnMapScDenomY));
912 const double fZeroPointX((static_cast<double>(aMapRes.mnMapOfsX) * fScaleFactorX) + static_cast<double>(mnOutOffOrigX));
913 const double fZeroPointY((static_cast<double>(aMapRes.mnMapOfsY) * fScaleFactorY) + static_cast<double>(mnOutOffOrigY));
915 aTransform.set(0, 0, fScaleFactorX);
916 aTransform.set(1, 1, fScaleFactorY);
917 aTransform.set(0, 2, fZeroPointX);
918 aTransform.set(1, 2, fZeroPointY);
920 return aTransform;
923 // #i75163#
924 basegfx::B2DHomMatrix OutputDevice::GetInverseViewTransformation( const MapMode& rMapMode ) const
926 basegfx::B2DHomMatrix aMatrix( GetViewTransformation( rMapMode ) );
927 aMatrix.invert();
928 return aMatrix;
931 basegfx::B2DHomMatrix OutputDevice::ImplGetDeviceTransformation() const
933 basegfx::B2DHomMatrix aTransformation = GetViewTransformation();
934 // TODO: is it worth to cache the transformed result?
935 if( mnOutOffX || mnOutOffY )
936 aTransformation.translate( mnOutOffX, mnOutOffY );
937 return aTransformation;
940 Point OutputDevice::LogicToPixel( const Point& rLogicPt ) const
943 if ( !mbMap )
944 return rLogicPt;
946 return Point( ImplLogicToPixel( rLogicPt.X() + maMapRes.mnMapOfsX, mnDPIX,
947 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
948 maThresRes.mnThresLogToPixX )+mnOutOffOrigX,
949 ImplLogicToPixel( rLogicPt.Y() + maMapRes.mnMapOfsY, mnDPIY,
950 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
951 maThresRes.mnThresLogToPixY )+mnOutOffOrigY );
954 Size OutputDevice::LogicToPixel( const Size& rLogicSize ) const
957 if ( !mbMap )
958 return rLogicSize;
960 return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
961 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
962 maThresRes.mnThresLogToPixX ),
963 ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
964 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
965 maThresRes.mnThresLogToPixY ) );
968 tools::Rectangle OutputDevice::LogicToPixel( const tools::Rectangle& rLogicRect ) const
971 if ( !mbMap || rLogicRect.IsEmpty() )
972 return rLogicRect;
974 return tools::Rectangle( ImplLogicToPixel( rLogicRect.Left() + maMapRes.mnMapOfsX, mnDPIX,
975 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
976 maThresRes.mnThresLogToPixX )+mnOutOffOrigX,
977 ImplLogicToPixel( rLogicRect.Top() + maMapRes.mnMapOfsY, mnDPIY,
978 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
979 maThresRes.mnThresLogToPixY )+mnOutOffOrigY,
980 ImplLogicToPixel( rLogicRect.Right() + maMapRes.mnMapOfsX, mnDPIX,
981 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
982 maThresRes.mnThresLogToPixX )+mnOutOffOrigX,
983 ImplLogicToPixel( rLogicRect.Bottom() + maMapRes.mnMapOfsY, mnDPIY,
984 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
985 maThresRes.mnThresLogToPixY )+mnOutOffOrigY );
988 tools::Polygon OutputDevice::LogicToPixel( const tools::Polygon& rLogicPoly ) const
991 if ( !mbMap )
992 return rLogicPoly;
994 sal_uInt16 i;
995 sal_uInt16 nPoints = rLogicPoly.GetSize();
996 tools::Polygon aPoly( rLogicPoly );
998 // get pointer to Point-array (copy data)
999 const Point* pPointAry = aPoly.GetConstPointAry();
1001 for ( i = 0; i < nPoints; i++ )
1003 const Point* pPt = &(pPointAry[i]);
1004 Point aPt;
1005 aPt.setX( ImplLogicToPixel( pPt->X() + maMapRes.mnMapOfsX, mnDPIX,
1006 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1007 maThresRes.mnThresLogToPixX )+mnOutOffOrigX );
1008 aPt.setY( ImplLogicToPixel( pPt->Y() + maMapRes.mnMapOfsY, mnDPIY,
1009 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1010 maThresRes.mnThresLogToPixY )+mnOutOffOrigY );
1011 aPoly[i] = aPt;
1014 return aPoly;
1017 tools::PolyPolygon OutputDevice::LogicToPixel( const tools::PolyPolygon& rLogicPolyPoly ) const
1020 if ( !mbMap )
1021 return rLogicPolyPoly;
1023 tools::PolyPolygon aPolyPoly( rLogicPolyPoly );
1024 sal_uInt16 nPoly = aPolyPoly.Count();
1025 for( sal_uInt16 i = 0; i < nPoly; i++ )
1027 tools::Polygon& rPoly = aPolyPoly[i];
1028 rPoly = LogicToPixel( rPoly );
1030 return aPolyPoly;
1033 basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly ) const
1035 basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly;
1036 const basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation();
1037 aTransformedPoly.transform( rTransformationMatrix );
1038 return aTransformedPoly;
1041 vcl::Region OutputDevice::LogicToPixel( const vcl::Region& rLogicRegion ) const
1044 if(!mbMap || rLogicRegion.IsNull() || rLogicRegion.IsEmpty())
1046 return rLogicRegion;
1049 vcl::Region aRegion;
1051 if(rLogicRegion.getB2DPolyPolygon())
1053 aRegion = vcl::Region(LogicToPixel(*rLogicRegion.getB2DPolyPolygon()));
1055 else if(rLogicRegion.getPolyPolygon())
1057 aRegion = vcl::Region(LogicToPixel(*rLogicRegion.getPolyPolygon()));
1059 else if(rLogicRegion.getRegionBand())
1061 RectangleVector aRectangles;
1062 rLogicRegion.GetRegionRectangles(aRectangles);
1063 const RectangleVector& rRectangles(aRectangles); // needed to make the '!=' work
1065 // make reverse run to fill new region bottom-up, this will speed it up due to the used data structuring
1066 for(RectangleVector::const_reverse_iterator aRectIter(rRectangles.rbegin()); aRectIter != rRectangles.rend(); ++aRectIter)
1068 aRegion.Union(LogicToPixel(*aRectIter));
1072 return aRegion;
1075 Point OutputDevice::LogicToPixel( const Point& rLogicPt,
1076 const MapMode& rMapMode ) const
1079 if ( rMapMode.IsDefault() )
1080 return rLogicPt;
1082 // convert MapMode resolution and convert
1083 ImplMapRes aMapRes;
1084 ImplThresholdRes aThresRes;
1085 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1087 return Point( ImplLogicToPixel( rLogicPt.X() + aMapRes.mnMapOfsX, mnDPIX,
1088 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1089 aThresRes.mnThresLogToPixX )+mnOutOffOrigX,
1090 ImplLogicToPixel( rLogicPt.Y() + aMapRes.mnMapOfsY, mnDPIY,
1091 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1092 aThresRes.mnThresLogToPixY )+mnOutOffOrigY );
1095 Size OutputDevice::LogicToPixel( const Size& rLogicSize,
1096 const MapMode& rMapMode ) const
1099 if ( rMapMode.IsDefault() )
1100 return rLogicSize;
1102 // convert MapMode resolution and convert
1103 ImplMapRes aMapRes;
1104 ImplThresholdRes aThresRes;
1105 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1107 return Size( ImplLogicToPixel( rLogicSize.Width(), mnDPIX,
1108 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1109 aThresRes.mnThresLogToPixX ),
1110 ImplLogicToPixel( rLogicSize.Height(), mnDPIY,
1111 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1112 aThresRes.mnThresLogToPixY ) );
1115 tools::Rectangle OutputDevice::LogicToPixel( const tools::Rectangle& rLogicRect,
1116 const MapMode& rMapMode ) const
1119 if ( rMapMode.IsDefault() || rLogicRect.IsEmpty() )
1120 return rLogicRect;
1122 // convert MapMode resolution and convert
1123 ImplMapRes aMapRes;
1124 ImplThresholdRes aThresRes;
1125 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1127 return tools::Rectangle( ImplLogicToPixel( rLogicRect.Left() + aMapRes.mnMapOfsX, mnDPIX,
1128 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1129 aThresRes.mnThresLogToPixX )+mnOutOffOrigX,
1130 ImplLogicToPixel( rLogicRect.Top() + aMapRes.mnMapOfsY, mnDPIY,
1131 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1132 aThresRes.mnThresLogToPixY )+mnOutOffOrigY,
1133 ImplLogicToPixel( rLogicRect.Right() + aMapRes.mnMapOfsX, mnDPIX,
1134 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1135 aThresRes.mnThresLogToPixX )+mnOutOffOrigX,
1136 ImplLogicToPixel( rLogicRect.Bottom() + aMapRes.mnMapOfsY, mnDPIY,
1137 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1138 aThresRes.mnThresLogToPixY )+mnOutOffOrigY );
1141 tools::Polygon OutputDevice::LogicToPixel( const tools::Polygon& rLogicPoly,
1142 const MapMode& rMapMode ) const
1145 if ( rMapMode.IsDefault() )
1146 return rLogicPoly;
1148 // convert MapMode resolution and convert
1149 ImplMapRes aMapRes;
1150 ImplThresholdRes aThresRes;
1151 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1153 sal_uInt16 i;
1154 sal_uInt16 nPoints = rLogicPoly.GetSize();
1155 tools::Polygon aPoly( rLogicPoly );
1157 // get pointer to Point-array (copy data)
1158 const Point* pPointAry = aPoly.GetConstPointAry();
1160 for ( i = 0; i < nPoints; i++ )
1162 const Point* pPt = &(pPointAry[i]);
1163 Point aPt;
1164 aPt.setX( ImplLogicToPixel( pPt->X() + aMapRes.mnMapOfsX, mnDPIX,
1165 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1166 aThresRes.mnThresLogToPixX )+mnOutOffOrigX );
1167 aPt.setY( ImplLogicToPixel( pPt->Y() + aMapRes.mnMapOfsY, mnDPIY,
1168 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1169 aThresRes.mnThresLogToPixY )+mnOutOffOrigY );
1170 aPoly[i] = aPt;
1173 return aPoly;
1176 basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly,
1177 const MapMode& rMapMode ) const
1179 basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly;
1180 const basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation( rMapMode );
1181 aTransformedPoly.transform( rTransformationMatrix );
1182 return aTransformedPoly;
1185 Point OutputDevice::PixelToLogic( const Point& rDevicePt ) const
1188 if ( !mbMap )
1189 return rDevicePt;
1191 return Point( ImplPixelToLogic( rDevicePt.X(), mnDPIX,
1192 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1193 maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX - mnOutOffLogicX,
1194 ImplPixelToLogic( rDevicePt.Y(), mnDPIY,
1195 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1196 maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY - mnOutOffLogicY );
1199 Size OutputDevice::PixelToLogic( const Size& rDeviceSize ) const
1202 if ( !mbMap )
1203 return rDeviceSize;
1205 return Size( ImplPixelToLogic( rDeviceSize.Width(), mnDPIX,
1206 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1207 maThresRes.mnThresPixToLogX ),
1208 ImplPixelToLogic( rDeviceSize.Height(), mnDPIY,
1209 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1210 maThresRes.mnThresPixToLogY ) );
1213 tools::Rectangle OutputDevice::PixelToLogic( const tools::Rectangle& rDeviceRect ) const
1216 if ( !mbMap || rDeviceRect.IsEmpty() )
1217 return rDeviceRect;
1219 return tools::Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX,
1220 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1221 maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX - mnOutOffLogicX,
1222 ImplPixelToLogic( rDeviceRect.Top(), mnDPIY,
1223 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1224 maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY - mnOutOffLogicY,
1225 ImplPixelToLogic( rDeviceRect.Right(), mnDPIX,
1226 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1227 maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX - mnOutOffLogicX,
1228 ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY,
1229 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1230 maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY - mnOutOffLogicY );
1233 tools::Polygon OutputDevice::PixelToLogic( const tools::Polygon& rDevicePoly ) const
1236 if ( !mbMap )
1237 return rDevicePoly;
1239 sal_uInt16 i;
1240 sal_uInt16 nPoints = rDevicePoly.GetSize();
1241 tools::Polygon aPoly( rDevicePoly );
1243 // get pointer to Point-array (copy data)
1244 const Point* pPointAry = aPoly.GetConstPointAry();
1246 for ( i = 0; i < nPoints; i++ )
1248 const Point* pPt = &(pPointAry[i]);
1249 Point aPt;
1250 aPt.setX( ImplPixelToLogic( pPt->X(), mnDPIX,
1251 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1252 maThresRes.mnThresPixToLogX ) - maMapRes.mnMapOfsX - mnOutOffLogicX );
1253 aPt.setY( ImplPixelToLogic( pPt->Y(), mnDPIY,
1254 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1255 maThresRes.mnThresPixToLogY ) - maMapRes.mnMapOfsY - mnOutOffLogicY );
1256 aPoly[i] = aPt;
1259 return aPoly;
1262 tools::PolyPolygon OutputDevice::PixelToLogic( const tools::PolyPolygon& rDevicePolyPoly ) const
1265 if ( !mbMap )
1266 return rDevicePolyPoly;
1268 tools::PolyPolygon aPolyPoly( rDevicePolyPoly );
1269 sal_uInt16 nPoly = aPolyPoly.Count();
1270 for( sal_uInt16 i = 0; i < nPoly; i++ )
1272 tools::Polygon& rPoly = aPolyPoly[i];
1273 rPoly = PixelToLogic( rPoly );
1275 return aPolyPoly;
1278 basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygon& rPixelPolyPoly ) const
1280 basegfx::B2DPolyPolygon aTransformedPoly = rPixelPolyPoly;
1281 const basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation();
1282 aTransformedPoly.transform( rTransformationMatrix );
1283 return aTransformedPoly;
1286 vcl::Region OutputDevice::PixelToLogic( const vcl::Region& rDeviceRegion ) const
1289 if(!mbMap || rDeviceRegion.IsNull() || rDeviceRegion.IsEmpty())
1291 return rDeviceRegion;
1294 vcl::Region aRegion;
1296 if(rDeviceRegion.getB2DPolyPolygon())
1298 aRegion = vcl::Region(PixelToLogic(*rDeviceRegion.getB2DPolyPolygon()));
1300 else if(rDeviceRegion.getPolyPolygon())
1302 aRegion = vcl::Region(PixelToLogic(*rDeviceRegion.getPolyPolygon()));
1304 else if(rDeviceRegion.getRegionBand())
1306 RectangleVector aRectangles;
1307 rDeviceRegion.GetRegionRectangles(aRectangles);
1308 const RectangleVector& rRectangles(aRectangles); // needed to make the '!=' work
1310 // make reverse run to fill new region bottom-up, this will speed it up due to the used data structuring
1311 for(RectangleVector::const_reverse_iterator aRectIter(rRectangles.rbegin()); aRectIter != rRectangles.rend(); ++aRectIter)
1313 aRegion.Union(PixelToLogic(*aRectIter));
1317 return aRegion;
1320 Point OutputDevice::PixelToLogic( const Point& rDevicePt,
1321 const MapMode& rMapMode ) const
1324 // calculate nothing if default-MapMode
1325 if ( rMapMode.IsDefault() )
1326 return rDevicePt;
1328 // calculate MapMode-resolution and convert
1329 ImplMapRes aMapRes;
1330 ImplThresholdRes aThresRes;
1331 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1333 return Point( ImplPixelToLogic( rDevicePt.X(), mnDPIX,
1334 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1335 aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX - mnOutOffLogicX,
1336 ImplPixelToLogic( rDevicePt.Y(), mnDPIY,
1337 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1338 aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY - mnOutOffLogicY );
1341 Size OutputDevice::PixelToLogic( const Size& rDeviceSize,
1342 const MapMode& rMapMode ) const
1345 // calculate nothing if default-MapMode
1346 if ( rMapMode.IsDefault() )
1347 return rDeviceSize;
1349 // calculate MapMode-resolution and convert
1350 ImplMapRes aMapRes;
1351 ImplThresholdRes aThresRes;
1352 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1354 return Size( ImplPixelToLogic( rDeviceSize.Width(), mnDPIX,
1355 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1356 aThresRes.mnThresPixToLogX ),
1357 ImplPixelToLogic( rDeviceSize.Height(), mnDPIY,
1358 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1359 aThresRes.mnThresPixToLogY ) );
1362 tools::Rectangle OutputDevice::PixelToLogic( const tools::Rectangle& rDeviceRect,
1363 const MapMode& rMapMode ) const
1366 // calculate nothing if default-MapMode
1367 if ( rMapMode.IsDefault() || rDeviceRect.IsEmpty() )
1368 return rDeviceRect;
1370 // calculate MapMode-resolution and convert
1371 ImplMapRes aMapRes;
1372 ImplThresholdRes aThresRes;
1373 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1375 return tools::Rectangle( ImplPixelToLogic( rDeviceRect.Left(), mnDPIX,
1376 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1377 aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX - mnOutOffLogicX,
1378 ImplPixelToLogic( rDeviceRect.Top(), mnDPIY,
1379 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1380 aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY - mnOutOffLogicY,
1381 ImplPixelToLogic( rDeviceRect.Right(), mnDPIX,
1382 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1383 aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX - mnOutOffLogicX,
1384 ImplPixelToLogic( rDeviceRect.Bottom(), mnDPIY,
1385 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1386 aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY - mnOutOffLogicY );
1389 tools::Polygon OutputDevice::PixelToLogic( const tools::Polygon& rDevicePoly,
1390 const MapMode& rMapMode ) const
1393 // calculate nothing if default-MapMode
1394 if ( rMapMode.IsDefault() )
1395 return rDevicePoly;
1397 // calculate MapMode-resolution and convert
1398 ImplMapRes aMapRes;
1399 ImplThresholdRes aThresRes;
1400 ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes );
1402 sal_uInt16 i;
1403 sal_uInt16 nPoints = rDevicePoly.GetSize();
1404 tools::Polygon aPoly( rDevicePoly );
1406 // get pointer to Point-array (copy data)
1407 const Point* pPointAry = aPoly.GetConstPointAry();
1409 for ( i = 0; i < nPoints; i++ )
1411 const Point* pPt = &(pPointAry[i]);
1412 Point aPt;
1413 aPt.setX( ImplPixelToLogic( pPt->X(), mnDPIX,
1414 aMapRes.mnMapScNumX, aMapRes.mnMapScDenomX,
1415 aThresRes.mnThresPixToLogX ) - aMapRes.mnMapOfsX - mnOutOffLogicX );
1416 aPt.setY( ImplPixelToLogic( pPt->Y(), mnDPIY,
1417 aMapRes.mnMapScNumY, aMapRes.mnMapScDenomY,
1418 aThresRes.mnThresPixToLogY ) - aMapRes.mnMapOfsY - mnOutOffLogicY );
1419 aPoly[i] = aPt;
1422 return aPoly;
1425 basegfx::B2DPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolygon& rPixelPoly,
1426 const MapMode& rMapMode ) const
1428 basegfx::B2DPolygon aTransformedPoly = rPixelPoly;
1429 const basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation( rMapMode );
1430 aTransformedPoly.transform( rTransformationMatrix );
1431 return aTransformedPoly;
1434 basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygon& rPixelPolyPoly,
1435 const MapMode& rMapMode ) const
1437 basegfx::B2DPolyPolygon aTransformedPoly = rPixelPolyPoly;
1438 const basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation( rMapMode );
1439 aTransformedPoly.transform( rTransformationMatrix );
1440 return aTransformedPoly;
1443 #define ENTER1( rSource, pMapModeSource, pMapModeDest ) \
1444 if ( !pMapModeSource ) \
1445 pMapModeSource = &maMapMode; \
1446 if ( !pMapModeDest ) \
1447 pMapModeDest = &maMapMode; \
1448 if ( *pMapModeSource == *pMapModeDest ) \
1449 return rSource; \
1451 ImplMapRes aMapResSource; \
1452 aMapResSource.mnMapOfsX = 0; \
1453 aMapResSource.mnMapOfsY = 0; \
1454 aMapResSource.mnMapScNumX = 1; \
1455 aMapResSource.mnMapScNumY = 1; \
1456 aMapResSource.mnMapScDenomX = 1; \
1457 aMapResSource.mnMapScDenomY = 1; \
1458 ImplMapRes aMapResDest(aMapResSource); \
1460 if ( !mbMap || pMapModeSource != &maMapMode ) \
1462 if ( pMapModeSource->GetMapUnit() == MapUnit::MapRelative ) \
1463 aMapResSource = maMapRes; \
1464 ImplCalcMapResolution( *pMapModeSource, \
1465 mnDPIX, mnDPIY, aMapResSource ); \
1467 else \
1468 aMapResSource = maMapRes; \
1469 if ( !mbMap || pMapModeDest != &maMapMode ) \
1471 if ( pMapModeDest->GetMapUnit() == MapUnit::MapRelative ) \
1472 aMapResDest = maMapRes; \
1473 ImplCalcMapResolution( *pMapModeDest, \
1474 mnDPIX, mnDPIY, aMapResDest ); \
1476 else \
1477 aMapResDest = maMapRes
1479 static void verifyUnitSourceDest( MapUnit eUnitSource, MapUnit eUnitDest )
1481 DBG_ASSERT( eUnitSource != MapUnit::MapSysFont
1482 && eUnitSource != MapUnit::MapAppFont
1483 && eUnitSource != MapUnit::MapRelative,
1484 "Source MapUnit is not permitted" );
1485 DBG_ASSERT( eUnitDest != MapUnit::MapSysFont
1486 && eUnitDest != MapUnit::MapAppFont
1487 && eUnitDest != MapUnit::MapRelative,
1488 "Destination MapUnit is not permitted" );
1491 #define ENTER3( eUnitSource, eUnitDest ) \
1492 long nNumerator = 1; \
1493 long nDenominator = 1; \
1494 SAL_WARN_IF( eUnitSource > s_MaxValidUnit, "vcl.gdi", "Invalid source map unit"); \
1495 SAL_WARN_IF( eUnitDest > s_MaxValidUnit, "vcl.gdi", "Invalid destination map unit"); \
1496 if( (eUnitSource <= s_MaxValidUnit) && (eUnitDest <= s_MaxValidUnit) ) \
1498 nNumerator = aImplNumeratorAry[eUnitSource] * \
1499 aImplDenominatorAry[eUnitDest]; \
1500 nDenominator = aImplNumeratorAry[eUnitDest] * \
1501 aImplDenominatorAry[eUnitSource]; \
1503 if ( eUnitSource == MapUnit::MapPixel ) \
1504 nDenominator *= 72; \
1505 else if( eUnitDest == MapUnit::MapPixel ) \
1506 nNumerator *= 72
1508 #define ENTER4( rMapModeSource, rMapModeDest ) \
1509 ImplMapRes aMapResSource; \
1510 aMapResSource.mnMapOfsX = 0; \
1511 aMapResSource.mnMapOfsY = 0; \
1512 aMapResSource.mnMapScNumX = 1; \
1513 aMapResSource.mnMapScNumY = 1; \
1514 aMapResSource.mnMapScDenomX = 1; \
1515 aMapResSource.mnMapScDenomY = 1; \
1516 ImplMapRes aMapResDest(aMapResSource); \
1518 ImplCalcMapResolution( rMapModeSource, 72, 72, aMapResSource ); \
1519 ImplCalcMapResolution( rMapModeDest, 72, 72, aMapResDest )
1521 // return (n1 * n2 * n3) / (n4 * n5)
1522 static long fn5( const long n1,
1523 const long n2,
1524 const long n3,
1525 const long n4,
1526 const long n5 )
1528 if ( n1 == 0 || n2 == 0 || n3 == 0 || n4 == 0 || n5 == 0 )
1529 return 0;
1530 if ( LONG_MAX / std::abs(n2) < std::abs(n3) )
1532 // a6 is skipped
1533 BigInt a7 = n2;
1534 a7 *= n3;
1535 a7 *= n1;
1537 if ( LONG_MAX / std::abs(n4) < std::abs(n5) )
1539 BigInt a8 = n4;
1540 a8 *= n5;
1542 BigInt a9 = a8;
1543 a9 /= 2;
1544 if ( a7.IsNeg() )
1545 a7 -= a9;
1546 else
1547 a7 += a9;
1549 a7 /= a8;
1550 } // of if
1551 else
1553 long n8 = n4 * n5;
1555 if ( a7.IsNeg() )
1556 a7 -= n8 / 2;
1557 else
1558 a7 += n8 / 2;
1560 a7 /= n8;
1561 } // of else
1562 return static_cast<long>(a7);
1563 } // of if
1564 else
1566 long n6 = n2 * n3;
1568 if ( LONG_MAX / std::abs(n1) < std::abs(n6) )
1570 BigInt a7 = n1;
1571 a7 *= n6;
1573 if ( LONG_MAX / std::abs(n4) < std::abs(n5) )
1575 BigInt a8 = n4;
1576 a8 *= n5;
1578 BigInt a9 = a8;
1579 a9 /= 2;
1580 if ( a7.IsNeg() )
1581 a7 -= a9;
1582 else
1583 a7 += a9;
1585 a7 /= a8;
1586 } // of if
1587 else
1589 long n8 = n4 * n5;
1591 if ( a7.IsNeg() )
1592 a7 -= n8 / 2;
1593 else
1594 a7 += n8 / 2;
1596 a7 /= n8;
1597 } // of else
1598 return static_cast<long>(a7);
1599 } // of if
1600 else
1602 long n7 = n1 * n6;
1604 if ( LONG_MAX / std::abs(n4) < std::abs(n5) )
1606 BigInt a7 = n7;
1607 BigInt a8 = n4;
1608 a8 *= n5;
1610 BigInt a9 = a8;
1611 a9 /= 2;
1612 if ( a7.IsNeg() )
1613 a7 -= a9;
1614 else
1615 a7 += a9;
1617 a7 /= a8;
1618 return static_cast<long>(a7);
1619 } // of if
1620 else
1622 const long n8 = n4 * n5;
1623 const long n8_2 = n8 / 2;
1625 if( n7 < 0 )
1627 if( ( n7 - LONG_MIN ) >= n8_2 )
1628 n7 -= n8_2;
1630 else if( ( LONG_MAX - n7 ) >= n8_2 )
1631 n7 += n8_2;
1633 return n7 / n8;
1634 } // of else
1635 } // of else
1636 } // of else
1639 // return (n1 * n2) / n3
1640 static long fn3( const long n1, const long n2, const long n3 )
1642 if ( n1 == 0 || n2 == 0 || n3 == 0 )
1643 return 0;
1644 if ( LONG_MAX / std::abs(n1) < std::abs(n2) )
1646 BigInt a4 = n1;
1647 a4 *= n2;
1649 if ( a4.IsNeg() )
1650 a4 -= n3 / 2;
1651 else
1652 a4 += n3 / 2;
1654 a4 /= n3;
1655 return static_cast<long>(a4);
1656 } // of if
1657 else
1659 long n4 = n1 * n2;
1660 const long n3_2 = n3 / 2;
1662 if( n4 < 0 )
1664 if( ( n4 - LONG_MIN ) >= n3_2 )
1665 n4 -= n3_2;
1667 else if( ( LONG_MAX - n4 ) >= n3_2 )
1668 n4 += n3_2;
1670 return n4 / n3;
1671 } // of else
1674 Point OutputDevice::LogicToLogic( const Point& rPtSource,
1675 const MapMode* pMapModeSource,
1676 const MapMode* pMapModeDest ) const
1678 ENTER1( rPtSource, pMapModeSource, pMapModeDest );
1680 return Point( fn5( rPtSource.X() + aMapResSource.mnMapOfsX,
1681 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1682 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
1683 aMapResDest.mnMapOfsX,
1684 fn5( rPtSource.Y() + aMapResSource.mnMapOfsY,
1685 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1686 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
1687 aMapResDest.mnMapOfsY );
1690 Size OutputDevice::LogicToLogic( const Size& rSzSource,
1691 const MapMode* pMapModeSource,
1692 const MapMode* pMapModeDest ) const
1694 ENTER1( rSzSource, pMapModeSource, pMapModeDest );
1696 return Size( fn5( rSzSource.Width(),
1697 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1698 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ),
1699 fn5( rSzSource.Height(),
1700 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1701 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) );
1704 tools::Rectangle OutputDevice::LogicToLogic( const tools::Rectangle& rRectSource,
1705 const MapMode* pMapModeSource,
1706 const MapMode* pMapModeDest ) const
1708 ENTER1( rRectSource, pMapModeSource, pMapModeDest );
1710 return tools::Rectangle( fn5( rRectSource.Left() + aMapResSource.mnMapOfsX,
1711 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1712 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
1713 aMapResDest.mnMapOfsX,
1714 fn5( rRectSource.Top() + aMapResSource.mnMapOfsY,
1715 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1716 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
1717 aMapResDest.mnMapOfsY,
1718 fn5( rRectSource.Right() + aMapResSource.mnMapOfsX,
1719 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1720 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
1721 aMapResDest.mnMapOfsX,
1722 fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY,
1723 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1724 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
1725 aMapResDest.mnMapOfsY );
1728 Point OutputDevice::LogicToLogic( const Point& rPtSource,
1729 const MapMode& rMapModeSource,
1730 const MapMode& rMapModeDest )
1732 if ( rMapModeSource == rMapModeDest )
1733 return rPtSource;
1735 MapUnit eUnitSource = rMapModeSource.GetMapUnit();
1736 MapUnit eUnitDest = rMapModeDest.GetMapUnit();
1737 verifyUnitSourceDest( eUnitSource, eUnitDest );
1739 if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple())
1741 ENTER3( eUnitSource, eUnitDest );
1743 return Point( fn3( rPtSource.X(), nNumerator, nDenominator ),
1744 fn3( rPtSource.Y(), nNumerator, nDenominator ) );
1746 else
1748 ENTER4( rMapModeSource, rMapModeDest );
1750 return Point( fn5( rPtSource.X() + aMapResSource.mnMapOfsX,
1751 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1752 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
1753 aMapResDest.mnMapOfsX,
1754 fn5( rPtSource.Y() + aMapResSource.mnMapOfsY,
1755 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1756 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
1757 aMapResDest.mnMapOfsY );
1761 Size OutputDevice::LogicToLogic( const Size& rSzSource,
1762 const MapMode& rMapModeSource,
1763 const MapMode& rMapModeDest )
1765 if ( rMapModeSource == rMapModeDest )
1766 return rSzSource;
1768 MapUnit eUnitSource = rMapModeSource.GetMapUnit();
1769 MapUnit eUnitDest = rMapModeDest.GetMapUnit();
1770 verifyUnitSourceDest( eUnitSource, eUnitDest );
1772 if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple())
1774 ENTER3( eUnitSource, eUnitDest );
1776 return Size( fn3( rSzSource.Width(), nNumerator, nDenominator ),
1777 fn3( rSzSource.Height(), nNumerator, nDenominator ) );
1779 else
1781 ENTER4( rMapModeSource, rMapModeDest );
1783 return Size( fn5( rSzSource.Width(),
1784 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1785 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ),
1786 fn5( rSzSource.Height(),
1787 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1788 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) );
1792 basegfx::B2DPolygon OutputDevice::LogicToLogic( const basegfx::B2DPolygon& rPolySource,
1793 const MapMode& rMapModeSource,
1794 const MapMode& rMapModeDest )
1796 if(rMapModeSource == rMapModeDest)
1798 return rPolySource;
1801 const basegfx::B2DHomMatrix aTransform(LogicToLogic(rMapModeSource, rMapModeDest));
1802 basegfx::B2DPolygon aPoly(rPolySource);
1804 aPoly.transform(aTransform);
1805 return aPoly;
1808 basegfx::B2DHomMatrix OutputDevice::LogicToLogic(const MapMode& rMapModeSource, const MapMode& rMapModeDest)
1810 basegfx::B2DHomMatrix aTransform;
1812 if(rMapModeSource == rMapModeDest)
1814 return aTransform;
1817 MapUnit eUnitSource = rMapModeSource.GetMapUnit();
1818 MapUnit eUnitDest = rMapModeDest.GetMapUnit();
1819 verifyUnitSourceDest(eUnitSource, eUnitDest);
1821 if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple())
1823 ENTER3(eUnitSource, eUnitDest);
1825 const double fScaleFactor(static_cast<double>(nNumerator) / static_cast<double>(nDenominator));
1826 aTransform.set(0, 0, fScaleFactor);
1827 aTransform.set(1, 1, fScaleFactor);
1829 else
1831 ENTER4(rMapModeSource, rMapModeDest);
1833 const double fScaleFactorX((double(aMapResSource.mnMapScNumX) * double(aMapResDest.mnMapScDenomX)) / (double(aMapResSource.mnMapScDenomX) * double(aMapResDest.mnMapScNumX)));
1834 const double fScaleFactorY((double(aMapResSource.mnMapScNumY) * double(aMapResDest.mnMapScDenomY)) / (double(aMapResSource.mnMapScDenomY) * double(aMapResDest.mnMapScNumY)));
1835 const double fZeroPointX(double(aMapResSource.mnMapOfsX) * fScaleFactorX - double(aMapResDest.mnMapOfsX));
1836 const double fZeroPointY(double(aMapResSource.mnMapOfsY) * fScaleFactorY - double(aMapResDest.mnMapOfsY));
1838 aTransform.set(0, 0, fScaleFactorX);
1839 aTransform.set(1, 1, fScaleFactorY);
1840 aTransform.set(0, 2, fZeroPointX);
1841 aTransform.set(1, 2, fZeroPointY);
1844 return aTransform;
1847 tools::Rectangle OutputDevice::LogicToLogic( const tools::Rectangle& rRectSource,
1848 const MapMode& rMapModeSource,
1849 const MapMode& rMapModeDest )
1851 if ( rMapModeSource == rMapModeDest )
1852 return rRectSource;
1854 MapUnit eUnitSource = rMapModeSource.GetMapUnit();
1855 MapUnit eUnitDest = rMapModeDest.GetMapUnit();
1856 verifyUnitSourceDest( eUnitSource, eUnitDest );
1858 if (rMapModeSource.IsSimple() && rMapModeDest.IsSimple())
1860 ENTER3( eUnitSource, eUnitDest );
1862 auto left = fn3( rRectSource.Left(), nNumerator, nDenominator );
1863 auto top = fn3( rRectSource.Top(), nNumerator, nDenominator );
1864 if (rRectSource.IsEmpty())
1865 return tools::Rectangle( left, top );
1867 auto right = fn3( rRectSource.Right(), nNumerator, nDenominator );
1868 auto bottom = fn3( rRectSource.Bottom(), nNumerator, nDenominator );
1869 return tools::Rectangle(left, top, right, bottom);
1871 else
1873 ENTER4( rMapModeSource, rMapModeDest );
1875 auto left = fn5( rRectSource.Left() + aMapResSource.mnMapOfsX,
1876 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1877 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
1878 aMapResDest.mnMapOfsX;
1879 auto top = fn5( rRectSource.Top() + aMapResSource.mnMapOfsY,
1880 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1881 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
1882 aMapResDest.mnMapOfsY;
1883 if (rRectSource.IsEmpty())
1884 return tools::Rectangle(left, top);
1886 auto right = fn5( rRectSource.Right() + aMapResSource.mnMapOfsX,
1887 aMapResSource.mnMapScNumX, aMapResDest.mnMapScDenomX,
1888 aMapResSource.mnMapScDenomX, aMapResDest.mnMapScNumX ) -
1889 aMapResDest.mnMapOfsX;
1890 auto bottom = fn5( rRectSource.Bottom() + aMapResSource.mnMapOfsY,
1891 aMapResSource.mnMapScNumY, aMapResDest.mnMapScDenomY,
1892 aMapResSource.mnMapScDenomY, aMapResDest.mnMapScNumY ) -
1893 aMapResDest.mnMapOfsY;
1894 return tools::Rectangle(left, top, right, bottom);
1898 long OutputDevice::LogicToLogic( long nLongSource,
1899 MapUnit eUnitSource, MapUnit eUnitDest )
1901 if ( eUnitSource == eUnitDest )
1902 return nLongSource;
1904 verifyUnitSourceDest( eUnitSource, eUnitDest );
1905 ENTER3( eUnitSource, eUnitDest );
1907 return fn3( nLongSource, nNumerator, nDenominator );
1910 void OutputDevice::SetPixelOffset( const Size& rOffset )
1912 mnOutOffOrigX = rOffset.Width();
1913 mnOutOffOrigY = rOffset.Height();
1915 mnOutOffLogicX = ImplPixelToLogic( mnOutOffOrigX, mnDPIX,
1916 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1917 maThresRes.mnThresPixToLogX );
1918 mnOutOffLogicY = ImplPixelToLogic( mnOutOffOrigY, mnDPIY,
1919 maMapRes.mnMapScNumY, maMapRes.mnMapScDenomY,
1920 maThresRes.mnThresPixToLogY );
1922 if( mpAlphaVDev )
1923 mpAlphaVDev->SetPixelOffset( rOffset );
1927 DeviceCoordinate OutputDevice::LogicWidthToDeviceCoordinate( long nWidth ) const
1929 if ( !mbMap )
1930 return static_cast<DeviceCoordinate>(nWidth);
1932 #if VCL_FLOAT_DEVICE_PIXEL
1933 return (double)nWidth * maMapRes.mfScaleX * mnDPIX;
1934 #else
1936 return ImplLogicToPixel( nWidth, mnDPIX,
1937 maMapRes.mnMapScNumX, maMapRes.mnMapScDenomX,
1938 maThresRes.mnThresLogToPixX );
1939 #endif
1942 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */