oox/source/drawingml/lineproperties.cxx | 86 +++++++++-------------- oox/source/export/drawingml.cxx | 11 +- sw/qa/extras/ooxmlexport/data/tdf73547-dash.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport12.cxx | 11 ++ 4 files changed, 52 insertions(+), 56 deletions(-)
New commits: commit 34dff8df7b9fc46fed6e6ffbaa8b6847ad6ed1b1 Author: Mark Hung <mark...@gmail.com> AuthorDate: Sun Aug 19 23:49:26 2018 +0800 Commit: Mark Hung <mark...@gmail.com> CommitDate: Fri Aug 24 15:07:14 2018 +0200 tdf#73547 fix ooxml export / import custom dashes. Fix import logic as well as arithmatic precion of both import and export. Change-Id: I97e9bde847e0a2425421af2f2175d4d0b7af0cab Reviewed-on: https://gerrit.libreoffice.org/59306 Tested-by: Jenkins Reviewed-by: Mark Hung <mark...@gmail.com> diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx index 25bbbcd25f1e..2b5de7a1f8c0 100644 --- a/oox/source/drawingml/lineproperties.cxx +++ b/oox/source/drawingml/lineproperties.cxx @@ -55,11 +55,8 @@ void lclSetDashData( LineDash& orLineDash, sal_Int16 nDots, sal_Int32 nDotLen, } /** Converts the specified preset dash to API dash. - - Line length and dot length are set relative to line width and have to be - multiplied by the actual line width after this function. */ -void lclConvertPresetDash( LineDash& orLineDash, sal_Int32 nPresetDash ) +void lclConvertPresetDash(LineDash& orLineDash, sal_Int32 nPresetDash, sal_Int32 nLineWidth) { switch( nPresetDash ) { @@ -80,54 +77,41 @@ void lclConvertPresetDash( LineDash& orLineDash, sal_Int32 nPresetDash ) OSL_FAIL( "lclConvertPresetDash - unsupported preset dash" ); lclSetDashData( orLineDash, 0, 0, 1, 4, 3 ); } + // convert relative dash/dot length to absolute length + orLineDash.DotLen *= nLineWidth; + orLineDash.DashLen *= nLineWidth; + orLineDash.Distance *= nLineWidth; } -/** Converts the passed custom dash to API dash. - - Line length and dot length are set relative to line width and have to be - multiplied by the actual line width after this function. +/** Converts the passed custom dash to API dash. rCustomDash should not be empty. */ -void lclConvertCustomDash( LineDash& orLineDash, const LineProperties::DashStopVector& rCustomDash ) +void lclConvertCustomDash(LineDash& orLineDash, const LineProperties::DashStopVector& rCustomDash, sal_Int32 nLineWidth) { - if( rCustomDash.empty() ) + OSL_ASSERT(!rCustomDash.empty()); + orLineDash.Dashes = 0; + // Follow the order we export custDash: dashes first. + orLineDash.DashLen = rCustomDash[0].first; + // Also assume dash and dot have the same sp values. + orLineDash.Distance = rCustomDash[0].second; + orLineDash.DotLen = 0; + + for(const auto& rIt : rCustomDash) { - OSL_FAIL( "lclConvertCustomDash - unexpected empty custom dash" ); - lclSetDashData( orLineDash, 0, 0, 1, 4, 3 ); - return; - } - - // count dashes and dots (stops equal or less than 2 are assumed to be dots) - sal_Int16 nDots = 0; - sal_Int32 nDotLen = 0; - sal_Int16 nDashes = 0; - sal_Int32 nDashLen = 0; - sal_Int32 nDistance = 0; - sal_Int32 nConvertedLen = 0; - sal_Int32 nConvertedDistance = 0; - for( LineProperties::DashStopVector::const_iterator aIt = rCustomDash.begin(), aEnd = rCustomDash.end(); aIt != aEnd; ++aIt ) - { - // Get from "1000th of percent" ==> percent ==> multiplier - nConvertedLen = aIt->first / 1000 / 100; - nConvertedDistance = aIt->second / 1000 / 100; - - // Check if it is a dot (100% = dot) - if( nConvertedLen == 1 ) - { - ++nDots; - nDotLen += nConvertedLen; - } - else + sal_Int32 nLen = rIt.first; + if (nLen != orLineDash.DashLen) { - ++nDashes; - nDashLen += nConvertedLen; + orLineDash.DotLen = nLen; + break; } - nDistance += nConvertedDistance; + ++orLineDash.Dashes; } - orLineDash.DotLen = (nDots > 0) ? ::std::max< sal_Int32 >( nDotLen / nDots, 1 ) : 0; - orLineDash.Dots = nDots; - orLineDash.DashLen = (nDashes > 0) ? ::std::max< sal_Int32 >( nDashLen / nDashes, 1 ) : 0; - orLineDash.Dashes = nDashes; - orLineDash.Distance = ::std::max< sal_Int32 >( nDistance / rCustomDash.size(), 1 ); + // TODO: verify the assumption and approximate complex line patterns. + + // Assume we only have two types of dash stops, the rest are all dots. + orLineDash.Dots = rCustomDash.size() - orLineDash.Dashes; + orLineDash.DashLen = orLineDash.DashLen / 100000.0 * nLineWidth; + orLineDash.DotLen = orLineDash.DotLen / 100000.0 * nLineWidth; + orLineDash.Distance = orLineDash.Distance / 100000.0 * nLineWidth; } DashStyle lclGetDashStyle( sal_Int32 nToken ) @@ -386,16 +370,14 @@ void LineProperties::pushToPropMap( ShapePropertyMap& rPropMap, aLineDash.Style = lclGetDashStyle( moLineCap.get( XML_rnd ) ); // convert preset dash or custom dash - if( moPresetDash.differsFrom( XML_solid ) ) - lclConvertPresetDash( aLineDash, moPresetDash.get() ); + if(moPresetDash.differsFrom(XML_solid) || maCustomDash.empty()) + { + sal_Int32 nBaseLineWidth = ::std::max<sal_Int32>(nLineWidth, 35); + lclConvertPresetDash(aLineDash, moPresetDash.get(XML_dash), nBaseLineWidth); + } else - lclConvertCustomDash( aLineDash, maCustomDash ); + lclConvertCustomDash(aLineDash, maCustomDash, nLineWidth); - // convert relative dash/dot length to absolute length - sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 35 ); - aLineDash.DotLen *= nBaseLineWidth; - aLineDash.DashLen *= nBaseLineWidth; - aLineDash.Distance *= nBaseLineWidth; if( rPropMap.setProperty( ShapeProperty::LineDash, aLineDash ) ) eLineStyle = drawing::LineStyle_DASH; diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 6536798be85b..b42bdb67caad 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -738,23 +738,26 @@ void DrawingML::WriteOutline( const Reference<XPropertySet>& rXPropSet ) { // Write 'dashes' first, and then 'dots' int i; + sal_Int32 nSp = aLineDash.Distance * 100 / nLineWidth; if ( aLineDash.Dashes > 0 ) { + sal_Int32 nD = aLineDash.DashLen * 100 / nLineWidth; for( i = 0; i < aLineDash.Dashes; i ++ ) { mpFS->singleElementNS( XML_a , XML_ds, - XML_d , write1000thOfAPercent( aLineDash.DashLen > 0 ? aLineDash.DashLen / nLineWidth * 100 : 100 ), - XML_sp, write1000thOfAPercent( aLineDash.Distance > 0 ? aLineDash.Distance / nLineWidth * 100 : 100 ), + XML_d , write1000thOfAPercent(nD), + XML_sp, write1000thOfAPercent(nSp), FSEND ); } } if ( aLineDash.Dots > 0 ) { + sal_Int32 nD = aLineDash.DotLen * 100 / nLineWidth; for( i = 0; i < aLineDash.Dots; i ++ ) { mpFS->singleElementNS( XML_a, XML_ds, - XML_d , write1000thOfAPercent( aLineDash.DotLen > 0 ? aLineDash.DotLen / nLineWidth * 100 : 100 ), - XML_sp, write1000thOfAPercent( aLineDash.Distance > 0 ? aLineDash.Distance / nLineWidth * 100 : 100 ), + XML_d , write1000thOfAPercent(nD), + XML_sp, write1000thOfAPercent(nSp), FSEND ); } } diff --git a/sw/qa/extras/ooxmlexport/data/tdf73547-dash.docx b/sw/qa/extras/ooxmlexport/data/tdf73547-dash.docx new file mode 100644 index 000000000000..40e741ebb377 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf73547-dash.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx index d45284d67a4e..f115420d0361 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx @@ -766,6 +766,17 @@ DECLARE_OOXMLEXPORT_TEST(testWatermarkTrim, "tdf114308.docx") CPPUNIT_ASSERT_MESSAGE(ss.str(), nDifference >= -4); } +DECLARE_OOXMLEXPORT_TEST(testTdf73547, "tdf73547-dash.docx") +{ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + if (!pXmlDoc) + return; + double nD = getXPath(pXmlDoc, "//a:custDash/a:ds[1]", "d").toDouble(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(105000.0, nD, 5000.0); // was 100000 + double nSp = getXPath(pXmlDoc, "//a:custDash/a:ds[1]", "sp").toDouble(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(35000.0, nSp, 5000.0); // was 100000 +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits