summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2018-08-19 23:49:26 +0800
committerMark Hung <marklh9@gmail.com>2018-08-24 15:07:14 +0200
commit34dff8df7b9fc46fed6e6ffbaa8b6847ad6ed1b1 (patch)
tree01dc2f3d9d3bbcc0a9fad2b0bd783c06f1712a22
parent80d6cba424439803704dbddf4fc832bd73e90e97 (diff)
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 <marklh9@gmail.com>
-rw-r--r--oox/source/drawingml/lineproperties.cxx86
-rw-r--r--oox/source/export/drawingml.cxx11
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf73547-dash.docxbin0 -> 7308 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport12.cxx11
4 files changed, 52 insertions, 56 deletions
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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf73547-dash.docx
Binary files 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: */