diff options
author | Adam Co <rattles2013@gmail.com> | 2014-06-08 16:35:32 +0300 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-06-10 17:22:40 +0000 |
commit | 2211a67cc5e577f8abdcc96c9c63865be5fb988d (patch) | |
tree | c015c5ef53b56044e5ce28f37c5a353ab5883c2c | |
parent | 93152e2633c3da2b1993c69857baf11edada705e (diff) |
Rewrite import and export of custom dashes in ooxml filter (fix)
The import mechanism of custom-dash (a:custDash) was wrong, and imported
wrong values, which causes that if you would import-export-import-export -
you would get inflated values, which might cause a corruption.
The attributes for custom-dash nodes (a:ds) are of type 'PositivePercentage'.
Office will read percentages formatted with a trailing percent sign or
formatted as 1000th of a percent without a trailing percent sign, but only
write percentages as 1000th's of a percent without a trailing percent sign.
During import - LO did not check if it was in '%' format or in
'1000th of a percent' format. So that was fixed. Also - when exporting -
it always exports now in '1000th of a percent' format.
Change-Id: I6bd74df26951974f85173227c832386c70034afb
Reviewed-on: https://gerrit.libreoffice.org/9681
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r-- | include/oox/export/utils.hxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/lineproperties.cxx | 15 | ||||
-rw-r--r-- | oox/source/drawingml/linepropertiescontext.cxx | 46 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 51 | ||||
-rwxr-xr-x | sw/qa/extras/ooxmlexport/data/dashed_line_custdash_1000th_of_percent.docx | bin | 0 -> 18538 bytes | |||
-rwxr-xr-x | sw/qa/extras/ooxmlexport/data/dashed_line_custdash_percentage.docx | bin | 0 -> 18532 bytes | |||
-rwxr-xr-x | sw/qa/extras/ooxmlexport/data/dashed_line_preset.docx | bin | 0 -> 18511 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx | 62 |
8 files changed, 155 insertions, 23 deletions
diff --git a/include/oox/export/utils.hxx b/include/oox/export/utils.hxx index 06ddfe3391e5..b6bafddd78cb 100644 --- a/include/oox/export/utils.hxx +++ b/include/oox/export/utils.hxx @@ -49,9 +49,9 @@ static inline sal_Int64 TwipsToEMU( sal_Int32 nTwips ) } template <typename T> -OString writePercentage(T number) +OString write1000thOfAPercent(T number) { - return OString::number(number) + "%"; + return OString::number( number * 1000 ); } #endif diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx index 2044095c484b..372740b36006 100644 --- a/oox/source/drawingml/lineproperties.cxx +++ b/oox/source/drawingml/lineproperties.cxx @@ -107,19 +107,26 @@ void lclConvertCustomDash( LineDash& orLineDash, const LineProperties::DashStopV 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 ) { - if( aIt->first <= 2 ) + // 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 += aIt->first; + nDotLen += nConvertedLen; } else { ++nDashes; - nDashLen += aIt->first; + nDashLen += nConvertedLen; } - nDistance += aIt->second; + nDistance += nConvertedDistance; } orLineDash.DotLen = (nDots > 0) ? ::std::max< sal_Int32 >( nDotLen / nDots, 1 ) : 0; orLineDash.Dots = nDots; diff --git a/oox/source/drawingml/linepropertiescontext.cxx b/oox/source/drawingml/linepropertiescontext.cxx index 3195e569881b..ee49fbaddbb5 100644 --- a/oox/source/drawingml/linepropertiescontext.cxx +++ b/oox/source/drawingml/linepropertiescontext.cxx @@ -66,8 +66,50 @@ ContextHandlerRef LinePropertiesContext::onCreateContext( sal_Int32 nElement, co return this; break; case A_TOKEN( ds ): - mrLineProperties.maCustomDash.push_back( LineProperties::DashStop( - rAttribs.getInteger( XML_d, 0 ), rAttribs.getInteger( XML_sp, 0 ) ) ); + { + // 'a:ds' has 2 attributes : 'd' and 'sp' + // both are of type 'a:ST_PositivePercentage' + // according to the specs Office will read percentages formatted with a trailing percent sign + // or formatted as 1000th of a percent without a trailing percent sign, but only write percentages + // as 1000th's of a percent without a trailing percent sign. + // The code below takes care of both scenarios by converting to '1000th of a percent' always + OUString aStr; + sal_Int32 nDash = 0; + aStr = rAttribs.getString( XML_d, "" ); + if ( aStr.endsWith("%") ) + { + // Ends with a '%' + aStr = aStr.copy(0, aStr.getLength() - 1); + aStr = aStr.trim(); + nDash = aStr.toInt32(); + + // Convert to 1000th of a percent + nDash *= 1000; + } + else + { + nDash = rAttribs.getInteger( XML_d, 0 ); + } + + sal_Int32 nSp = 0; + aStr = rAttribs.getString( XML_sp, "" ); + if ( aStr.endsWith("%") ) + { + // Ends with a '%' + aStr = aStr.copy(0, aStr.getLength() - 1); + aStr = aStr.trim(); + nSp = aStr.toInt32(); + + // Convert to 1000th of a percent + nSp *= 1000; + } + else + { + nSp = rAttribs.getInteger( XML_sp, 0 ); + } + + mrLineProperties.maCustomDash.push_back( LineProperties::DashStop( nDash, nSp ) ); + } break; // LineJoinPropertiesGroup diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 42d007a7aa5f..6340b6e9c051 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -626,24 +626,45 @@ void DrawingML::WriteOutline( Reference< XPropertySet > rXPropSet ) if( bDashSet && aStyleLineStyle != drawing::LineStyle_DASH ) { // line style is a dash and it was not set by the shape style - // TODO: the XML_d and XML_sp values seem insane + mpFS->startElementNS( XML_a, XML_custDash, FSEND ); - aLineDash.DotLen = aLineDash.DotLen / nLineWidth; - aLineDash.DashLen = aLineDash.DashLen / nLineWidth; - aLineDash.Distance = aLineDash.Distance / nLineWidth; + // Check that line-width is positive and distance between dashes\dots is positive + if ( nLineWidth > 0 && aLineDash.Distance > 0 ) + { + // Write 'dashes' first, and then 'dots' + int i; + if ( aLineDash.Dashes > 0 ) + { + 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 ), + FSEND ); + } + if ( aLineDash.Dots > 0 ) + { + 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 ), + FSEND ); + } + } + + if ( nLineWidth <= 0 ) + SAL_WARN("oox", "while writing outline - custom dash - line width was < 0 : " << nLineWidth); + if ( aLineDash.Dashes < 0 ) + SAL_WARN("oox", "while writing outline - custom dash - number of dashes was < 0 : " << aLineDash.Dashes); + if ( aLineDash.Dashes > 0 && aLineDash.DashLen <= 0 ) + SAL_WARN("oox", "while writing outline - custom dash - dash length was < 0 : " << aLineDash.DashLen); + if ( aLineDash.Dots < 0 ) + SAL_WARN("oox", "while writing outline - custom dash - number of dots was < 0 : " << aLineDash.Dots); + if ( aLineDash.Dots > 0 && aLineDash.DotLen <= 0 ) + SAL_WARN("oox", "while writing outline - custom dash - dot length was < 0 : " << aLineDash.DotLen); + if ( aLineDash.Distance <= 0 ) + SAL_WARN("oox", "while writing outline - custom dash - distance was < 0 : " << aLineDash.Distance); - int i; - for( i = 0; i < aLineDash.Dots; i ++ ) - mpFS->singleElementNS( XML_a, XML_ds, - XML_d, aLineDash.DotLen ? writePercentage( aLineDash.DotLen*1000 ) : "100000%", - XML_sp, writePercentage( aLineDash.Distance*1000 ), - FSEND ); - for( i = 0; i < aLineDash.Dashes; i ++ ) - mpFS->singleElementNS( XML_a, XML_ds, - XML_d, aLineDash.DashLen ? writePercentage( aLineDash.DashLen*1000 ) : "100000%", - XML_sp, writePercentage( aLineDash.Distance*1000 ), - FSEND ); mpFS->endElementNS( XML_a, XML_custDash ); } diff --git a/sw/qa/extras/ooxmlexport/data/dashed_line_custdash_1000th_of_percent.docx b/sw/qa/extras/ooxmlexport/data/dashed_line_custdash_1000th_of_percent.docx Binary files differnew file mode 100755 index 000000000000..d9a922819f68 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/dashed_line_custdash_1000th_of_percent.docx diff --git a/sw/qa/extras/ooxmlexport/data/dashed_line_custdash_percentage.docx b/sw/qa/extras/ooxmlexport/data/dashed_line_custdash_percentage.docx Binary files differnew file mode 100755 index 000000000000..a1d0e7db6d63 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/dashed_line_custdash_percentage.docx diff --git a/sw/qa/extras/ooxmlexport/data/dashed_line_preset.docx b/sw/qa/extras/ooxmlexport/data/dashed_line_preset.docx Binary files differnew file mode 100755 index 000000000000..923360b496c8 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/dashed_line_preset.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx index 0eccae333b16..ee40f9ee3928 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx @@ -1642,6 +1642,68 @@ DECLARE_OOXMLEXPORT_TEST(testfdo79256, "fdo79256.docx") CPPUNIT_ASSERT(d <= maxLimit ); } +DECLARE_OOXMLEXPORT_TEST(testDashedLinePreset, "dashed_line_preset.docx") +{ + /* Make sure that preset line is exported correctly as "1000th of a percent". + * This test-file has a PRESET dash-line which will be converted by LO import + * to a custom-dash (dash-dot-dot). This test-case makes sure that the exporter + * outputs the correct values. + */ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + if (!pXmlDoc) + return; + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[1]", "d" , "800000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[1]", "sp", "300000"); + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[2]", "d" , "100000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[2]", "sp", "300000"); + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[3]", "d" , "100000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[3]", "sp", "300000"); +} + +DECLARE_OOXMLEXPORT_TEST(testDashedLine_CustDash1000thOfPercent, "dashed_line_custdash_1000th_of_percent.docx") +{ + /* Make sure that preset line is exported correctly as "1000th of a percent". + * This test-file has a CUSTOM dash-line that is defined as '1000th of a percent'. + * This should be imported by LO as-is, and exported back with the same values. + */ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + if (!pXmlDoc) + return; + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[1]", "d" , "800000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[1]", "sp", "300000"); + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[2]", "d" , "100000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[2]", "sp", "300000"); + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[3]", "d" , "100000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[3]", "sp", "300000"); +} + +DECLARE_OOXMLEXPORT_TEST(testDashedLine_CustDashPercentage, "dashed_line_custdash_percentage.docx") +{ + /* Make sure that preset line is exported correctly as "1000th of a percent". + * This test-file has a CUSTOM dash-line that is defined as percentages. + * This should be imported by LO as '1000th of a percent', and exported back + * as '1000th of a percent'. + */ + xmlDocPtr pXmlDoc = parseExport("word/document.xml"); + if (!pXmlDoc) + return; + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[1]", "d" , "800000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[1]", "sp", "300000"); + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[2]", "d" , "100000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[2]", "sp", "300000"); + + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[3]", "d" , "100000"); + assertXPath(pXmlDoc,"/w:document/w:body/w:p[1]/w:r[1]/mc:AlternateContent[1]/mc:Choice[1]/w:drawing[1]/wp:anchor[1]/a:graphic[1]/a:graphicData[1]/wps:wsp[1]/wps:spPr[1]/a:ln[1]/a:custDash[1]/a:ds[3]", "sp", "300000"); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); |