summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennard Wasserthal <Wasserthal@nefkom.net>2013-02-09 13:47:38 +0100
committerTor Lillqvist <tml@iki.fi>2013-02-19 15:49:52 +0000
commit3998d1abb291309ddbbc2c9869736ebb1ea608f0 (patch)
tree0f5a015e6673bdc3cad19beca67ae793e5608626
parentbee8ed6772f420f9eefc57fee01da29ff466a8e9 (diff)
fdo#56886 EMF: Fixes some scaling problems of clipped regions, Twips
If a Metafile's scaling is incompletely defined, there are some arbitrary values used. This bug is just filed as regression because aoo 3.3 used the WMF part and Lo the EMF part! Please use environment variable EMF_PLUS_DISABLE if you have further problems with EMF files. This Patch also adds an (untested) TWIPS scaling, which was missing. known issue: vertical text ratio still scaled differently than lineart. Change-Id: I7c0139853961eb338476a9e3a5e08d3f87225f2e Signed-off-by: Lennard Wasserthal <Wasserthal@nefkom.net> Reviewed-on: https://gerrit.libreoffice.org/1886 Reviewed-by: Tor Lillqvist <tml@iki.fi> Tested-by: Tor Lillqvist <tml@iki.fi>
-rw-r--r--vcl/source/filter/wmf/enhwmf.cxx14
-rw-r--r--vcl/source/filter/wmf/winmtf.cxx123
-rw-r--r--vcl/source/filter/wmf/winmtf.hxx19
3 files changed, 127 insertions, 29 deletions
diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx
index f8b98845be4e..541d68dbe48c 100644
--- a/vcl/source/filter/wmf/enhwmf.cxx
+++ b/vcl/source/filter/wmf/enhwmf.cxx
@@ -485,8 +485,8 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
EMFP_DEBUG(printf ("\t\tunknown id: 0x%x\n",(unsigned int) id));
}
}
- } else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
-
+ }
+ else if( !bEMFPlus || bHaveDC || nRecType == EMR_EOF )
switch( nRecType )
{
case EMR_POLYBEZIERTO :
@@ -518,14 +518,14 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
case EMR_SETWINDOWEXTEX :
{ // #75383#
*pWMF >> nW >> nH;
- pOut->SetWinExt( Size( nW, nH ) );
+ pOut->SetWinExt( Size( nW, nH ), true);
}
break;
case EMR_SETWINDOWORGEX :
{
*pWMF >> nX32 >> nY32;
- pOut->SetWinOrg( Point( nX32, nY32 ) );
+ pOut->SetWinOrg( Point( nX32, nY32 ), true);
}
break;
@@ -917,7 +917,7 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
PolyPolygon aPolyPoly;
if ( cbRgnData )
ImplReadRegion( aPolyPoly, *pWMF, nRecSize );
- pOut->SetClipPath( aPolyPoly, iMode, sal_False );
+ pOut->SetClipPath( aPolyPoly, iMode, sal_True );
}
break;
@@ -1352,7 +1352,7 @@ sal_Bool EnhWMFReader::ReadHeader()
return sal_False;
// bound size
- Rectangle rclBounds; // rectangle in logical units 1/100th mm
+ Rectangle rclBounds; // rectangle in logical units
*pWMF >> nLeft >> nTop >> nRight >> nBottom;
rclBounds.Left() = nLeft;
rclBounds.Top() = nTop;
@@ -1360,7 +1360,7 @@ sal_Bool EnhWMFReader::ReadHeader()
rclBounds.Bottom() = nBottom;
// picture frame size
- Rectangle rclFrame; // rectangle in device units
+ Rectangle rclFrame; // rectangle in device units 1/100th mm
*pWMF >> nLeft >> nTop >> nRight >> nBottom;
rclFrame.Left() = nLeft;
rclFrame.Top() = nTop;
diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx
index 0adca65d678b..fcfd07f4911b 100644
--- a/vcl/source/filter/wmf/winmtf.cxx
+++ b/vcl/source/filter/wmf/winmtf.cxx
@@ -350,6 +350,20 @@ Color WinMtf::ReadColor()
//-----------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------
+Point WinMtfOutput::ImplScale( const Point& rPt)//Hack to set varying defaults for incompletely defined files.
+{
+ if (mbIsMapDevSet && mbIsMapWinSet)
+ {
+ return Point((rPt.X())*mnWinExtX/mnDevWidth-mrclFrame.Left(),(rPt.Y())*mnWinExtY/mnDevHeight-mrclFrame.Top());
+ }
+ else
+ {
+ return Point((rPt.X())*UNDOCUMENTED_WIN_RCL_RELATION-mrclFrame.Left(),(rPt.Y())*UNDOCUMENTED_WIN_RCL_RELATION-mrclFrame.Top());
+ }
+}
+
+//-----------------------------------------------------------------------------------
+
Point WinMtfOutput::ImplMap( const Point& rPt )
{
if ( mnWinExtX && mnWinExtY )
@@ -368,8 +382,8 @@ Point WinMtfOutput::ImplMap( const Point& rPt )
fX2 -= mnWinOrgX;
fY2 -= mnWinOrgY;
if( mnDevWidth != 1 || mnDevHeight != 1 ) {
- fX2 *= 2540.0/mnUnitsPerInch;
- fY2 *= 2540.0/mnUnitsPerInch;
+ fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
+ fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
}
fX2 += mnDevOrgX;
fY2 += mnDevOrgY;
@@ -381,8 +395,8 @@ Point WinMtfOutput::ImplMap( const Point& rPt )
{
fX2 -= mnWinOrgX;
fY2 = mnWinOrgY-fY2;
- fX2 *= 25.40;
- fY2 *= 25.40;
+ fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
+ fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
fX2 += mnDevOrgX;
fY2 += mnDevOrgY;
}
@@ -391,8 +405,18 @@ Point WinMtfOutput::ImplMap( const Point& rPt )
{
fX2 -= mnWinOrgX;
fY2 = mnWinOrgY-fY2;
- fX2 *= 2.540;
- fY2 *= 2.540;
+ fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
+ fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
+ fX2 += mnDevOrgX;
+ fY2 += mnDevOrgY;
+ }
+ break;
+ case MM_TWIPS:
+ {
+ fX2 -= mnWinOrgX;
+ fY2 = mnWinOrgY-fY2;
+ fX2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
+ fY2 *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
fX2 += mnDevOrgX;
fY2 += mnDevOrgY;
}
@@ -407,7 +431,7 @@ Point WinMtfOutput::ImplMap( const Point& rPt )
fY2 += mnDevOrgY;
}
break;
- case MM_HIMETRIC :
+ case MM_HIMETRIC : //in hundredth of a millimeter
{
fX2 -= mnWinOrgX;
fY2 = mnWinOrgY-fY2;
@@ -454,8 +478,8 @@ Size WinMtfOutput::ImplMap( const Size& rSz )
{
case MM_TEXT:
if( mnDevWidth != 1 && mnDevHeight != 1 ) {
- fWidth *= 2540.0/mnUnitsPerInch;
- fHeight*= 2540.0/mnUnitsPerInch;
+ fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
+ fHeight*= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*1000/mnUnitsPerInch;
} else {
fWidth *= (double)mnMillX * 100 / (double)mnPixX;
fHeight *= (double)mnMillY * 100 / (double)mnPixY;
@@ -463,14 +487,14 @@ Size WinMtfOutput::ImplMap( const Size& rSz )
break;
case MM_LOENGLISH :
{
- fWidth *= 25.40;
- fHeight*=-25.40;
+ fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
+ fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH*10;
}
break;
case MM_HIENGLISH :
{
- fWidth *= 2.540;
- fHeight*=-2.540;
+ fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
+ fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH;
}
break;
case MM_LOMETRIC :
@@ -479,11 +503,17 @@ Size WinMtfOutput::ImplMap( const Size& rSz )
fHeight*=-10;
}
break;
- case MM_HIMETRIC :
+ case MM_HIMETRIC : //in hundredth of millimeters
{
fHeight *= -1;
}
break;
+ case MM_TWIPS:
+ {
+ fWidth *= HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
+ fHeight*=-HUNDREDTH_MILLIMETERS_PER_MILLIINCH/MILLIINCH_PER_TWIPS;
+ }
+ break;
default :
{
fWidth /= mnWinExtX;
@@ -541,6 +571,27 @@ Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon )
//-----------------------------------------------------------------------------------
+Polygon& WinMtfOutput::ImplScale( Polygon& rPolygon )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ rPolygon[ i ] = ImplScale( rPolygon[ i ] );
+ }
+ return rPolygon;
+}
+
+//-----------------------------------------------------------------------------------
+
+PolyPolygon& WinMtfOutput::ImplScale( PolyPolygon& rPolyPolygon )
+{
+ sal_uInt16 nPolys = rPolyPolygon.Count();
+ for ( sal_uInt16 i = 0; i < nPolys; ImplScale( rPolyPolygon[ i++ ] ) ) ;
+ return rPolyPolygon;
+}
+
+//-----------------------------------------------------------------------------------
+
PolyPolygon& WinMtfOutput::ImplMap( PolyPolygon& rPolyPolygon )
{
sal_uInt16 nPolys = rPolyPolygon.Count();
@@ -836,6 +887,10 @@ void WinMtfOutput::DeleteObject( sal_Int32 nIndex )
void WinMtfOutput::IntersectClipRect( const Rectangle& rRect )
{
mbClipNeedsUpdate=true;
+ if ((rRect.Left()-rRect.Right()==0) && (rRect.Top()-rRect.Bottom()==0))
+ {
+ return; // empty rectangles cause trouble
+ }
aClipPath.intersectClipRect( ImplMap( rRect ) );
}
@@ -859,7 +914,10 @@ void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClip
{
mbClipNeedsUpdate=true;
if ( bIsMapped )
- aClipPath.setClipPath( rPolyPolygon, nClippingMode );
+ {
+ PolyPolygon aPP( rPolyPolygon );
+ aClipPath.setClipPath( ImplScale( aPP ), nClippingMode );
+ }
else
{
PolyPolygon aPP( rPolyPolygon );
@@ -904,6 +962,8 @@ WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) :
mnMillY ( 1 ),
mpGDIMetaFile ( &rGDIMetaFile )
{
+ mbIsMapWinSet = sal_False;
+ mbIsMapDevSet = sal_False;
mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // The original clipregion has to be on top
// of the stack so it can always be restored
// this is necessary to be able to support
@@ -1114,7 +1174,6 @@ void WinMtfOutput::MoveTo( const Point& rPoint, sal_Bool bRecordPath )
void WinMtfOutput::LineTo( const Point& rPoint, sal_Bool bRecordPath )
{
UpdateClipRegion();
-
Point aDest( ImplMap( rPoint ) );
if ( bRecordPath )
aPathObj.AddPoint( aDest );
@@ -1894,7 +1953,7 @@ void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
//-----------------------------------------------------------------------------------
-void WinMtfOutput::SetDevExt( const Size& rSize )
+void WinMtfOutput::SetDevExt( const Size& rSize ,sal_Bool regular)
{
if ( rSize.Width() && rSize.Height() )
{
@@ -1907,6 +1966,10 @@ void WinMtfOutput::SetDevExt( const Size& rSize )
mnDevHeight = rSize.Height();
}
}
+ if (regular)
+ {
+ mbIsMapDevSet=sal_True;
+ }
}
}
@@ -1920,10 +1983,15 @@ void WinMtfOutput::ScaleDevExt( double fX, double fY )
//-----------------------------------------------------------------------------------
-void WinMtfOutput::SetWinOrg( const Point& rPoint )
+void WinMtfOutput::SetWinOrg( const Point& rPoint , sal_Bool bIsEMF)
{
mnWinOrgX = rPoint.X();
mnWinOrgY = rPoint.Y();
+ if (bIsEMF)
+ {
+ SetDevByWin();
+ }
+ mbIsMapWinSet=sal_True;
}
//-----------------------------------------------------------------------------------
@@ -1936,9 +2004,21 @@ void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd )
//-----------------------------------------------------------------------------------
-void WinMtfOutput::SetWinExt( const Size& rSize )
+void WinMtfOutput::SetDevByWin() //mnWinExt...-stuff has to be assigned before.
{
+ if (!mbIsMapDevSet)
+ {
+ if ((mnMapMode == MM_ISOTROPIC) ) //TODO: WHAT ABOUT ANISOTROPIC???
+ {
+ SetDevExt(Size((mnWinExtX+mnWinOrgX)>>MS_FIXPOINT_BITCOUNT_28_4,-((mnWinExtY-mnWinOrgY)>>MS_FIXPOINT_BITCOUNT_28_4)),sal_False);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------------
+void WinMtfOutput::SetWinExt( const Size& rSize, sal_Bool bIsEMF )
+{
if( rSize.Width() && rSize.Height() )
{
switch( mnMapMode )
@@ -1948,6 +2028,11 @@ void WinMtfOutput::SetWinExt( const Size& rSize )
{
mnWinExtX = rSize.Width();
mnWinExtY = rSize.Height();
+ if (bIsEMF)
+ {
+ SetDevByWin();
+ }
+ mbIsMapWinSet=sal_True;
}
}
}
diff --git a/vcl/source/filter/wmf/winmtf.hxx b/vcl/source/filter/wmf/winmtf.hxx
index bc368e6e6baa..146493eda72c 100644
--- a/vcl/source/filter/wmf/winmtf.hxx
+++ b/vcl/source/filter/wmf/winmtf.hxx
@@ -278,6 +278,13 @@ struct WMF_EXTERNALHEADER;
#define PRIVATE_ESCAPE_UNICODE 2
+//Scalar constants
+
+#define UNDOCUMENTED_WIN_RCL_RELATION 32
+#define MS_FIXPOINT_BITCOUNT_28_4 4
+#define HUNDREDTH_MILLIMETERS_PER_MILLIINCH 2.54
+#define MILLIINCH_PER_TWIPS 1.44
+
//============================ WMFReader ==================================
#ifdef WIN_MTF_ASSERT
@@ -624,6 +631,8 @@ class WinMtfOutput
sal_Int32 mnDevWidth, mnDevHeight;
sal_Int32 mnWinOrgX, mnWinOrgY; // aktuelles Window-Origin
sal_Int32 mnWinExtX, mnWinExtY; // aktuelles Window-Extent
+ sal_Bool mbIsMapWinSet;
+ sal_Bool mbIsMapDevSet;
sal_Int32 mnPixX, mnPixY; // Reference Device in pixel
sal_Int32 mnMillX, mnMillY; // Reference Device in Mill
@@ -636,11 +645,14 @@ class WinMtfOutput
void UpdateFillStyle();
Point ImplMap( const Point& rPt );
+ Point ImplScale( const Point& rPt );
Size ImplMap( const Size& rSz );
Rectangle ImplMap( const Rectangle& rRectangle );
void ImplMap( Font& rFont );
Polygon& ImplMap( Polygon& rPolygon );
PolyPolygon& ImplMap( PolyPolygon& rPolyPolygon );
+ Polygon& ImplScale( Polygon& rPolygon );
+ PolyPolygon& ImplScale( PolyPolygon& rPolyPolygon );
void ImplResizeObjectArry( sal_uInt32 nNewEntry );
void ImplSetNonPersistentLineColorTransparenz();
void ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly );
@@ -648,14 +660,15 @@ class WinMtfOutput
public:
+ void SetDevByWin(); //Hack to set varying defaults for incompletely defined files.
void SetDevOrg( const Point& rPoint );
void SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd );
- void SetDevExt( const Size& rSize );
+ void SetDevExt( const Size& rSize ,sal_Bool regular = true);
void ScaleDevExt( double fX, double fY );
- void SetWinOrg( const Point& rPoint );
+ void SetWinOrg( const Point& rPoint , sal_Bool bIsEMF = false);
void SetWinOrgOffset( sal_Int32 nX, sal_Int32 nY );
- void SetWinExt( const Size& rSize );
+ void SetWinExt( const Size& rSize , sal_Bool bIsEMF = false);
void ScaleWinExt( double fX, double fY );
void SetrclBounds( const Rectangle& rRect );