From a05f5238fc3811cf2c56f343a3015d5a58180677 Mon Sep 17 00:00:00 2001 From: Chris Sherlock Date: Thu, 3 Mar 2016 21:52:49 +1100 Subject: tdf#79679 vcl: dashed lines show as solid lines when importing EMF files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backported to 5.1 Issue is a regression in commit 09c722873b2d378d2d155f5f1dd7d8f3fb2012e9. (EMF/WMF: fix rendering of pen styles (dash, dot, dashdot, dashdotdot). I've looked at how the latest version of Word on the Mac works, and it turns out that the spacings for the PenStyle enumerations in the LogPen objects for all the create pen EMF records are as follows: * PS_DOT - ■ □ ■ □ ■ □ ■ □ ■ □ ■ * PS_DASHDOT - ■ ■ ■ □ ■ □ ■ ■ ■ □ ■ * PS_DASHDOTDOT - ■ ■ ■ □ ■ □ ■ □ ■ ■ ■ (where ■ is the actual filled in area, and □ is the space between the filled in areas) In other words, each dash fills in the space of three dots, and there is the one dot worth of empty space between the dashes and dots. Each "dot" has a width and height equal to the width specified in the pen. So basically, we seem to be arbitrarily setting the dot, dash and distance lengths arbitrarily, which were reasonable guesses but tended to produce very odd lines at different zoom levels. Change-Id: Ie8b5fa396e4fb0f480cb3594c8129a59f472c1b8 Reviewed-on: https://gerrit.libreoffice.org/22886 Reviewed-by: Chris Sherlock Tested-by: Chris Sherlock Reviewed-on: https://gerrit.libreoffice.org/22923 Reviewed-by: jan iversen Tested-by: Jenkins Reviewed-by: Christian Lohmaier --- vcl/qa/cppunit/wmf/wmfimporttest.cxx | 24 ++++++++++++------------ vcl/source/filter/wmf/enhwmf.cxx | 26 ++++---------------------- vcl/source/filter/wmf/winmtf.cxx | 15 +++++++++++---- vcl/source/filter/wmf/winmtf.hxx | 2 +- vcl/source/filter/wmf/winwmf.cxx | 11 +---------- 5 files changed, 29 insertions(+), 49 deletions(-) diff --git a/vcl/qa/cppunit/wmf/wmfimporttest.cxx b/vcl/qa/cppunit/wmf/wmfimporttest.cxx index 2c6a6e30e9bd..855c42739f56 100644 --- a/vcl/qa/cppunit/wmf/wmfimporttest.cxx +++ b/vcl/qa/cppunit/wmf/wmfimporttest.cxx @@ -146,36 +146,36 @@ void WmfTest::testEmfLineStyles() assertXPath(pDoc, "/metafile/linecolor[5]", "color", "#0000ff"); assertXPath(pDoc, "/metafile/line[1]", "style", "dash"); - assertXPath(pDoc, "/metafile/line[1]", "dashlen", "225"); + assertXPath(pDoc, "/metafile/line[1]", "dashlen", "528"); assertXPath(pDoc, "/metafile/line[1]", "dashcount", "1"); - assertXPath(pDoc, "/metafile/line[1]", "dotlen", "0"); + assertXPath(pDoc, "/metafile/line[1]", "dotlen", "176"); assertXPath(pDoc, "/metafile/line[1]", "dotcount", "0"); - assertXPath(pDoc, "/metafile/line[1]", "distance", "100"); + assertXPath(pDoc, "/metafile/line[1]", "distance", "176"); assertXPath(pDoc, "/metafile/line[1]", "join", "miter"); assertXPath(pDoc, "/metafile/line[1]", "cap", "butt"); assertXPath(pDoc, "/metafile/line[2]", "style", "dash"); - assertXPath(pDoc, "/metafile/line[2]", "dashlen", "0"); + assertXPath(pDoc, "/metafile/line[2]", "dashlen", "528"); assertXPath(pDoc, "/metafile/line[2]", "dashcount", "0"); - assertXPath(pDoc, "/metafile/line[2]", "dotlen", "30"); + assertXPath(pDoc, "/metafile/line[2]", "dotlen", "176"); assertXPath(pDoc, "/metafile/line[2]", "dotcount", "1"); - assertXPath(pDoc, "/metafile/line[2]", "distance", "50"); + assertXPath(pDoc, "/metafile/line[2]", "distance", "176"); assertXPath(pDoc, "/metafile/line[2]", "join", "miter"); assertXPath(pDoc, "/metafile/line[2]", "cap", "butt"); assertXPath(pDoc, "/metafile/line[3]", "style", "dash"); - assertXPath(pDoc, "/metafile/line[3]", "dashlen", "150"); + assertXPath(pDoc, "/metafile/line[3]", "dashlen", "528"); assertXPath(pDoc, "/metafile/line[3]", "dashcount", "1"); - assertXPath(pDoc, "/metafile/line[3]", "dotlen", "30"); + assertXPath(pDoc, "/metafile/line[3]", "dotlen", "176"); assertXPath(pDoc, "/metafile/line[3]", "dotcount", "1"); - assertXPath(pDoc, "/metafile/line[3]", "distance", "90"); + assertXPath(pDoc, "/metafile/line[3]", "distance", "176"); assertXPath(pDoc, "/metafile/line[4]", "style", "dash"); - assertXPath(pDoc, "/metafile/line[4]", "dashlen", "150"); + assertXPath(pDoc, "/metafile/line[4]", "dashlen", "528"); assertXPath(pDoc, "/metafile/line[4]", "dashcount", "1"); - assertXPath(pDoc, "/metafile/line[4]", "dotlen", "30"); + assertXPath(pDoc, "/metafile/line[4]", "dotlen", "176"); assertXPath(pDoc, "/metafile/line[4]", "dotcount", "2"); - assertXPath(pDoc, "/metafile/line[4]", "distance", "50"); + assertXPath(pDoc, "/metafile/line[4]", "distance", "176"); assertXPath(pDoc, "/metafile/line[4]", "join", "miter"); assertXPath(pDoc, "/metafile/line[4]", "cap", "butt"); }; diff --git a/vcl/source/filter/wmf/enhwmf.cxx b/vcl/source/filter/wmf/enhwmf.cxx index c1c8160286b3..185e2fab9086 100644 --- a/vcl/source/filter/wmf/enhwmf.cxx +++ b/vcl/source/filter/wmf/enhwmf.cxx @@ -17,10 +17,12 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#include "winmtf.hxx" #include #include #include + +#include "winmtf.hxx" + #include #ifdef DBG_UTIL @@ -912,37 +914,27 @@ bool EnhWMFReader::ReadEnhWMF() aLineInfo.SetWidth( aSize.Width() ); bool bTransparent = false; - switch( nStyle & 0xFF ) + switch( nStyle & PS_STYLE_MASK ) { case PS_DASHDOTDOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 2 ); - aLineInfo.SetDashLen( 150 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 50 ); break; case PS_DASHDOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 1 ); - aLineInfo.SetDashLen( 150 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 90 ); break; case PS_DOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 0 ); aLineInfo.SetDotCount( 1 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 50 ); break; case PS_DASH : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 0 ); - aLineInfo.SetDashLen( 225 ); - aLineInfo.SetDistance( 100 ); break; case PS_NULL : bTransparent = true; @@ -1015,31 +1007,21 @@ bool EnhWMFReader::ReadEnhWMF() aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 2 ); - aLineInfo.SetDashLen( 150 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 50 ); break; case PS_DASHDOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 1 ); - aLineInfo.SetDashLen( 150 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 90 ); break; case PS_DOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 0 ); aLineInfo.SetDotCount( 1 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 50 ); break; case PS_DASH : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 0 ); - aLineInfo.SetDashLen( 225 ); - aLineInfo.SetDistance( 100 ); break; case PS_NULL : bTransparent = true; diff --git a/vcl/source/filter/wmf/winmtf.cxx b/vcl/source/filter/wmf/winmtf.cxx index e87234b614de..711b6fa8d0dc 100644 --- a/vcl/source/filter/wmf/winmtf.cxx +++ b/vcl/source/filter/wmf/winmtf.cxx @@ -503,14 +503,13 @@ tools::Polygon& WinMtfOutput::ImplMap( tools::Polygon& rPolygon ) return rPolygon; } -tools::Polygon& WinMtfOutput::ImplScale( tools::Polygon& rPolygon ) +void WinMtfOutput::ImplScale( tools::Polygon& rPolygon ) { sal_uInt16 nPoints = rPolygon.GetSize(); for ( sal_uInt16 i = 0; i < nPoints; i++ ) { rPolygon[ i ] = ImplScale( rPolygon[ i ] ); } - return rPolygon; } tools::PolyPolygon& WinMtfOutput::ImplScale( tools::PolyPolygon& rPolyPolygon ) @@ -730,8 +729,16 @@ void WinMtfOutput::CreateObject( sal_Int32 nIndex, GDIObjectType eType, void* pS { WinMtfLineStyle* pLineStyle = static_cast(pStyle); Size aSize(pLineStyle->aLineInfo.GetWidth(), 0); - aSize = ImplMap(aSize); - pLineStyle->aLineInfo.SetWidth(aSize.Width()); + pLineStyle->aLineInfo.SetWidth( ImplMap(aSize).Width() ); + + if ( pLineStyle->aLineInfo.GetStyle() == LINE_DASH ) + { + aSize.Width() += 1; + long nDotLen = ImplMap( aSize ).Width(); + pLineStyle->aLineInfo.SetDistance( nDotLen ); + pLineStyle->aLineInfo.SetDotLen( nDotLen ); + pLineStyle->aLineInfo.SetDashLen( nDotLen * 3 ); + } } } if ( (sal_uInt32)nIndex >= vGDIObj.size() ) diff --git a/vcl/source/filter/wmf/winmtf.hxx b/vcl/source/filter/wmf/winmtf.hxx index 7bd5f7db6329..79b375709945 100644 --- a/vcl/source/filter/wmf/winmtf.hxx +++ b/vcl/source/filter/wmf/winmtf.hxx @@ -610,7 +610,7 @@ class WinMtfOutput void ImplMap( vcl::Font& rFont ); tools::Polygon& ImplMap( tools::Polygon& rPolygon ); tools::PolyPolygon& ImplMap( tools::PolyPolygon& rPolyPolygon ); - tools::Polygon& ImplScale( tools::Polygon& rPolygon ); + void ImplScale( tools::Polygon& rPolygon ); tools::PolyPolygon& ImplScale( tools::PolyPolygon& rPolyPolygon ); void ImplResizeObjectArry( sal_uInt32 nNewEntry ); void ImplSetNonPersistentLineColorTransparenz(); diff --git a/vcl/source/filter/wmf/winwmf.cxx b/vcl/source/filter/wmf/winwmf.cxx index 1b590e4cca15..86c21124e284 100644 --- a/vcl/source/filter/wmf/winwmf.cxx +++ b/vcl/source/filter/wmf/winwmf.cxx @@ -811,37 +811,28 @@ void WMFReader::ReadRecordParams( sal_uInt16 nFunc ) aLineInfo.SetWidth(nWidth); bool bTransparent = false; + switch( nStyle & 0xFF ) { case PS_DASHDOTDOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 2 ); - aLineInfo.SetDashLen( 150 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 50 ); break; case PS_DASHDOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 1 ); - aLineInfo.SetDashLen( 150 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 90 ); break; case PS_DOT : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 0 ); aLineInfo.SetDotCount( 1 ); - aLineInfo.SetDotLen( 30 ); - aLineInfo.SetDistance( 50 ); break; case PS_DASH : aLineInfo.SetStyle( LINE_DASH ); aLineInfo.SetDashCount( 1 ); aLineInfo.SetDotCount( 0 ); - aLineInfo.SetDashLen( 225 ); - aLineInfo.SetDistance( 100 ); break; case PS_NULL : bTransparent = true; -- cgit