[Libreoffice-commits] core.git: oox/source sw/qa

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Aug 24 13:07:42 UTC 2018


 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 <marklh9 at gmail.com>
AuthorDate: Sun Aug 19 23:49:26 2018 +0800
Commit:     Mark Hung <marklh9 at 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 <marklh9 at 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: */


More information about the Libreoffice-commits mailing list