diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2017-07-24 13:43:28 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2017-07-24 16:30:48 +0200 |
commit | 8c7c72c8f8a1c8c09ee7cd4f413611c456f336b2 (patch) | |
tree | 90a76ce5930d6b5ece590e276f5768791f328e10 | |
parent | 26dd5d4614e5968f111b77a3f03129a6a2a7c0c7 (diff) |
tdf#109306: consider percent unit specification for table sizes
According to ECMA-376-1:2016, ST_MeasurementOrPercent (the type of
"w:w" attribute of table sizes) is allowed to have this specification
(and then is expected to be a floating-point value). First edition
of the standard (of 2006) only defined this attribute to contain
int32 value (of fiftieths of percent when holding relative widths).
Unit test included.
Change-Id: I700912e4eb07430e55fe1d169d99e8e7e0e1a00b
Reviewed-on: https://gerrit.libreoffice.org/40361
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r-- | sw/qa/extras/ooxmlimport/data/tdf109306.docx | bin | 0 -> 1343 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 13 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFactory.cxx | 9 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFactory.hxx | 3 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLPropertySet.cxx | 34 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLPropertySet.hxx | 17 | ||||
-rw-r--r-- | writerfilter/source/ooxml/factoryimpl.py | 2 | ||||
-rw-r--r-- | writerfilter/source/ooxml/model.xml | 6 |
8 files changed, 81 insertions, 3 deletions
diff --git a/sw/qa/extras/ooxmlimport/data/tdf109306.docx b/sw/qa/extras/ooxmlimport/data/tdf109306.docx Binary files differnew file mode 100644 index 000000000000..c13f0d6fd8e5 --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/tdf109306.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index 6d1b831b8ddb..6b4dc9a81216 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -1405,6 +1405,19 @@ DECLARE_OOXMLIMPORT_TEST(testTdf108849, "tdf108849.docx") CPPUNIT_ASSERT_EQUAL_MESSAGE("Misplaced body-level sectPr's create extra sections!", 2, getPages()); } +DECLARE_OOXMLIMPORT_TEST(testTdf109306, "tdf109306.docx") +{ + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); + // Both types of relative width specification (pct): simple integers (in fiftieths of percent) + // and floats with "%" unit specification must be treated correctly + CPPUNIT_ASSERT_EQUAL(true, bool(getProperty<bool>(xTables->getByIndex(0), "IsWidthRelative"))); + CPPUNIT_ASSERT_EQUAL(sal_Int16(90), getProperty<sal_Int16>(xTables->getByIndex(0), "RelativeWidth")); + + CPPUNIT_ASSERT_EQUAL(true, bool(getProperty<bool>(xTables->getByIndex(1), "IsWidthRelative"))); + CPPUNIT_ASSERT_EQUAL(sal_Int16(80), getProperty<sal_Int16>(xTables->getByIndex(1), "RelativeWidth")); +} + // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/writerfilter/source/ooxml/OOXMLFactory.cxx b/writerfilter/source/ooxml/OOXMLFactory.cxx index 12f6237ea996..c164ff949757 100644 --- a/writerfilter/source/ooxml/OOXMLFactory.cxx +++ b/writerfilter/source/ooxml/OOXMLFactory.cxx @@ -114,6 +114,15 @@ void OOXMLFactory::attributes(OOXMLFastContextHandler * pHandler, pFactory->attributeAction(pHandler, nToken, xValue); } break; + case ResourceType::MeasurementOrPercent: + { + const char *pValue = ""; + pAttribs->getAsChar(nToken, pValue); + OOXMLValue::Pointer_t xValue(new OOXMLMeasurementOrPercentValue(pValue)); + pHandler->newProperty(nId, xValue); + pFactory->attributeAction(pHandler, nToken, xValue); + } + break; case ResourceType::List: { sal_uInt32 nValue; diff --git a/writerfilter/source/ooxml/OOXMLFactory.hxx b/writerfilter/source/ooxml/OOXMLFactory.hxx index a3318d1da045..dce03696185c 100644 --- a/writerfilter/source/ooxml/OOXMLFactory.hxx +++ b/writerfilter/source/ooxml/OOXMLFactory.hxx @@ -52,7 +52,8 @@ enum class ResourceType { Math, Any, TwipsMeasure, - HpsMeasure + HpsMeasure, + MeasurementOrPercent }; struct AttributeInfo diff --git a/writerfilter/source/ooxml/OOXMLPropertySet.cxx b/writerfilter/source/ooxml/OOXMLPropertySet.cxx index 0b353dfb8039..b7b50d1bf20f 100644 --- a/writerfilter/source/ooxml/OOXMLPropertySet.cxx +++ b/writerfilter/source/ooxml/OOXMLPropertySet.cxx @@ -647,6 +647,40 @@ string OOXMLUniversalMeasureValue::toString() const } #endif +// OOXMLMeasurementOrPercentValue +// ECMA-376 5th ed. Part 1 , 17.18.107; 17.18.11 +OOXMLMeasurementOrPercentValue::OOXMLMeasurementOrPercentValue(const char * pValue) +{ + double val = rtl_str_toDouble(pValue); // will ignore the trailing unit + + int nLen = strlen(pValue); + if (nLen > 2 && + pValue[nLen - 1] == '%') + { + mnValue = static_cast<int>(val * 50); + } + else + { + // TODO: also allow units. For that, we need to know + // how to represent the number to converter or store + // the value in the type as number + unit and have + // getter with unit specification + mnValue = static_cast<int>(val); + } +} + +int OOXMLMeasurementOrPercentValue::getInt() const +{ + return mnValue; +} + +#ifdef DEBUG_WRITERFILTER +string OOXMLMeasurementOrPercentValue::toString() const +{ + return OString::number(mnValue).getStr(); +} +#endif + /* class OOXMLShapeValue */ diff --git a/writerfilter/source/ooxml/OOXMLPropertySet.hxx b/writerfilter/source/ooxml/OOXMLPropertySet.hxx index 45aba15e2ccc..59df4d3ecbb2 100644 --- a/writerfilter/source/ooxml/OOXMLPropertySet.hxx +++ b/writerfilter/source/ooxml/OOXMLPropertySet.hxx @@ -261,6 +261,23 @@ typedef OOXMLNthPtMeasureValue<20> OOXMLTwipsMeasureValue; /// Handles OOXML's ST_HpsMeasure value. typedef OOXMLNthPtMeasureValue<2> OOXMLHpsMeasureValue; +class OOXMLMeasurementOrPercentValue : public OOXMLValue +{ +protected: + int mnValue; +public: + explicit OOXMLMeasurementOrPercentValue(const char * pValue); + + virtual int getInt() const override; + virtual OOXMLValue* clone() const override + { + return new OOXMLMeasurementOrPercentValue(*this); + } +#ifdef DEBUG_WRITERFILTER + virtual std::string toString() const override; +#endif +}; + class OOXMLShapeValue : public OOXMLValue { protected: diff --git a/writerfilter/source/ooxml/factoryimpl.py b/writerfilter/source/ooxml/factoryimpl.py index d718f5a09fda..2168fff556d7 100644 --- a/writerfilter/source/ooxml/factoryimpl.py +++ b/writerfilter/source/ooxml/factoryimpl.py @@ -37,7 +37,7 @@ def createFastChildContextFromFactory(model): switch (nResource) {""") - resources = ["List", "Integer", "Hex", "String", "TwipsMeasure", "HpsMeasure", "Boolean"] + resources = ["List", "Integer", "Hex", "String", "TwipsMeasure", "HpsMeasure", "Boolean", "MeasurementOrPercent"] for resource in [r.getAttribute("resource") for r in model.getElementsByTagName("resource")]: if resource not in resources: resources.append(resource) diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 92e8677a8ecb..49fe6f8f44ad 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -14204,6 +14204,9 @@ <value>auto</value> </choice> </define> + <define name="ST_MeasurementOrPercent"> + <data type="string"/> + </define> <define name="CT_Height"> <attribute name="val"> <data type="string"/> @@ -14214,7 +14217,7 @@ </define> <define name="CT_TblWidth"> <attribute name="w"> - <ref name="ST_DecimalNumber"/> + <ref name="ST_MeasurementOrPercent"/> </attribute> <attribute name="type"> <ref name="ST_TblWidth"/> @@ -16667,6 +16670,7 @@ <attribute name="val" tokenid="ooxml:CT_SignedHpsMeasure_val" action="setValue"/> <action name="start" action="setDefaultIntegerValue"/> </resource> + <resource name="ST_MeasurementOrPercent" resource="MeasurementOrPercent"/> <resource name="ST_DateTime" resource="String"/> <resource name="CT_MacroName" resource="Value"> <attribute name="val" tokenid="ooxml:CT_MacroName_val" action="setValue"/> |