diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2017-06-08 11:55:18 +0300 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2017-06-09 07:46:34 +0200 |
commit | ea890b1d4bcd6dd59db9f52dce1609c020804e24 (patch) | |
tree | c3eb894389ae12d36d7815670c591e5cccffe9c0 | |
parent | fdfdea4d5af51a68f2d497cc5c3359d74c385fd5 (diff) |
tdf#108408: support unit specifications for ST_HpsMeasure
w:ST_HpsMeasure is defined in ECMA-376 5th ed. Part 1, 17.18.42 as
This simple type specifies that its contents contain either:
* A positive whole number, whose contents consist of a measurement in
half-points (equivalent to 1/144th of an inch), or
* A positive decimal number immediately followed by a unit identifier.
...
This simple type is a union of the following types:
* The ST_PositiveUniversalMeasure simple type (§22.9.2.12).
* The ST_UnsignedDecimalNumber simple type (§22.9.2.16).
This patch generalizes OOXMLUniversalMeasureValue to handle standard-
defined units, and introduces two typedefed specifications:
OOXMLTwipsMeasureValue (which is used where UniversalMeasure was
previously used), and new OOXMLHpsMeasureValue.
Unit test included.
Change-Id: Iccc6d46f717cb618381baf89dfd3e4bbb844b4af
Reviewed-on: https://gerrit.libreoffice.org/38562
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r-- | sw/qa/extras/ooxmlimport/data/tdf108408.docx | bin | 0 -> 1298 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlimport/ooxmlimport.cxx | 9 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFactory.cxx | 13 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFactory.hxx | 3 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLPropertySet.cxx | 41 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLPropertySet.hxx | 24 | ||||
-rw-r--r-- | writerfilter/source/ooxml/factoryimpl.py | 2 | ||||
-rw-r--r-- | writerfilter/source/ooxml/model.xml | 8 |
8 files changed, 79 insertions, 21 deletions
diff --git a/sw/qa/extras/ooxmlimport/data/tdf108408.docx b/sw/qa/extras/ooxmlimport/data/tdf108408.docx Binary files differnew file mode 100644 index 000000000000..dcd1ecf8bd2e --- /dev/null +++ b/sw/qa/extras/ooxmlimport/data/tdf108408.docx diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx index 9c61378ae245..2d4804e937af 100644 --- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx +++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx @@ -1284,6 +1284,15 @@ DECLARE_OOXMLIMPORT_TEST(testTdf108350, "tdf108350.docx") CPPUNIT_ASSERT_EQUAL(double(11), getProperty<double>(xRun, "CharHeight")); } +DECLARE_OOXMLIMPORT_TEST(testTdf108408, "tdf108408.docx") +{ + // Font size must consider units specifications; previously ignored and only used + // integer part as half-pt size, i.e. 10 pt (20 half-pt) instead of 20 pt + uno::Reference<text::XTextRange> xPara(getParagraph(1)); + uno::Reference<beans::XPropertySet> xRun(getRun(xPara, 1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(double(20), getProperty<double>(xRun, "CharHeight")); +} + // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT diff --git a/writerfilter/source/ooxml/OOXMLFactory.cxx b/writerfilter/source/ooxml/OOXMLFactory.cxx index b951245ba376..3d28d2eafa4c 100644 --- a/writerfilter/source/ooxml/OOXMLFactory.cxx +++ b/writerfilter/source/ooxml/OOXMLFactory.cxx @@ -98,15 +98,24 @@ void OOXMLFactory::attributes(OOXMLFastContextHandler * pHandler, pFactory->attributeAction(pHandler, nToken, xValue); } break; - case ResourceType::UniversalMeasure: + case ResourceType::TwipsMeasure: { const char *pValue = ""; pAttribs->getAsChar(nToken, pValue); - OOXMLValue::Pointer_t xValue(new OOXMLUniversalMeasureValue(pValue)); + OOXMLValue::Pointer_t xValue(new OOXMLTwipsMeasureValue(pValue)); pHandler->newProperty(nId, xValue); pFactory->attributeAction(pHandler, nToken, xValue); } break; + case ResourceType::HpsMeasure: + { + const char *pValue = ""; + pAttribs->getAsChar(nToken, pValue); + OOXMLValue::Pointer_t xValue(new OOXMLHpsMeasureValue(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 9e4b495fd0fc..a3318d1da045 100644 --- a/writerfilter/source/ooxml/OOXMLFactory.hxx +++ b/writerfilter/source/ooxml/OOXMLFactory.hxx @@ -51,7 +51,8 @@ enum class ResourceType { PropertyTable, Math, Any, - UniversalMeasure + TwipsMeasure, + HpsMeasure }; struct AttributeInfo diff --git a/writerfilter/source/ooxml/OOXMLPropertySet.cxx b/writerfilter/source/ooxml/OOXMLPropertySet.cxx index 9a095913e082..3ef7a30b11ff 100644 --- a/writerfilter/source/ooxml/OOXMLPropertySet.cxx +++ b/writerfilter/source/ooxml/OOXMLPropertySet.cxx @@ -589,17 +589,45 @@ string OOXMLHexValue::toString() const #endif // OOXMLUniversalMeasureValue - -OOXMLUniversalMeasureValue::OOXMLUniversalMeasureValue(const char * pValue) +// ECMA-376 5th ed. Part 1 , 22.9.2.15 +OOXMLUniversalMeasureValue::OOXMLUniversalMeasureValue(const char * pValue, sal_uInt32 npPt) { - mnValue = rtl_str_toInt32(pValue, 10); // will ignore the trailing 'pt' + double val = rtl_str_toDouble(pValue); // will ignore the trailing unit int nLen = strlen(pValue); if (nLen > 2 && pValue[nLen-2] == 'p' && pValue[nLen-1] == 't') { - mnValue = mnValue * 20; + mnValue = static_cast<sal_uInt32>(val * npPt); + } + else if (nLen > 2 && + pValue[nLen - 2] == 'c' && + pValue[nLen - 1] == 'm') + { + mnValue = static_cast<sal_uInt32>(val * npPt * 72 / 2.54); + } + else if (nLen > 2 && + pValue[nLen - 2] == 'm' && + pValue[nLen - 1] == 'm') + { + mnValue = static_cast<sal_uInt32>(val * npPt * 72 / 25.4); + } + else if (nLen > 2 && + pValue[nLen - 2] == 'i' && + pValue[nLen - 1] == 'n') + { + mnValue = static_cast<sal_uInt32>(val * npPt * 72); + } + else if (nLen > 2 && + pValue[nLen - 2] == 'p' && + ( pValue[nLen - 1] == 'c' || pValue[nLen - 1] == 'i' )) + { + mnValue = static_cast<sal_uInt32>(val * npPt * 12); + } + else + { + mnValue = static_cast<sal_uInt32>(val); } } @@ -612,11 +640,6 @@ int OOXMLUniversalMeasureValue::getInt() const return mnValue; } -OOXMLValue* OOXMLUniversalMeasureValue::clone() const -{ - return new OOXMLUniversalMeasureValue(*this); -} - #ifdef DEBUG_WRITERFILTER string OOXMLUniversalMeasureValue::toString() const { diff --git a/writerfilter/source/ooxml/OOXMLPropertySet.hxx b/writerfilter/source/ooxml/OOXMLPropertySet.hxx index 8aa7c92a4ee3..73889a4abb9b 100644 --- a/writerfilter/source/ooxml/OOXMLPropertySet.hxx +++ b/writerfilter/source/ooxml/OOXMLPropertySet.hxx @@ -229,22 +229,38 @@ public: virtual OOXMLValue * clone() const override; }; -/// Handles OOXML's ST_UniversalMeasure value. class OOXMLUniversalMeasureValue : public OOXMLValue { -protected: +private: sal_uInt32 mnValue; public: - explicit OOXMLUniversalMeasureValue(const char * pValue); + OOXMLUniversalMeasureValue(const char * pValue, sal_uInt32 npPt); virtual ~OOXMLUniversalMeasureValue() override; virtual int getInt() const override; #ifdef DEBUG_WRITERFILTER virtual std::string toString() const override; #endif - virtual OOXMLValue* clone() const override; }; +/// npPt is quotient defining how much units are in 1 pt +template <sal_uInt32 npPt> class OOXMLNthPtMeasureValue : public OOXMLUniversalMeasureValue +{ +public: + explicit OOXMLNthPtMeasureValue(const char * pValue) + : OOXMLUniversalMeasureValue(pValue, npPt) {} + virtual OOXMLValue* clone() const override + { + return new OOXMLNthPtMeasureValue<npPt>(*this); + } +}; + +/// Handles OOXML's ST_TwipsMeasure value. +typedef OOXMLNthPtMeasureValue<20> OOXMLTwipsMeasureValue; + +/// Handles OOXML's ST_HpsMeasure value. +typedef OOXMLNthPtMeasureValue<2> OOXMLHpsMeasureValue; + class OOXMLShapeValue : public OOXMLValue { protected: diff --git a/writerfilter/source/ooxml/factoryimpl.py b/writerfilter/source/ooxml/factoryimpl.py index 1e172c589ea1..d718f5a09fda 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", "UniversalMeasure", "Boolean"] + resources = ["List", "Integer", "Hex", "String", "TwipsMeasure", "HpsMeasure", "Boolean"] 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 ae89c4ba5c54..05fb53f08729 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -8236,7 +8236,7 @@ <resource name="CT_OMathJc" resource="Value"> <attribute name="val" tokenid="ooxml:CT_OMathJc_val" action="setValue"/> </resource> - <resource name="ST_TwipsMeasure" resource="UniversalMeasure"/> + <resource name="ST_TwipsMeasure" resource="TwipsMeasure"/> <resource name="CT_TwipsMeasure" resource="Value"> <attribute name="val" tokenid="ooxml:CT_TwipsMeasure_val" action="setValue"/> <action name="start" action="setDefaultIntegerValue"/> @@ -16616,12 +16616,12 @@ <action name="start" action="setDefaultIntegerValue"/> </resource> <resource name="ST_UnsignedDecimalNumber" resource="Integer"/> - <resource name="ST_TwipsMeasure" resource="UniversalMeasure"/> + <resource name="ST_TwipsMeasure" resource="TwipsMeasure"/> <resource name="CT_TwipsMeasure" resource="Value"> <attribute name="val" tokenid="ooxml:CT_TwipsMeasure_val" action="setValue"/> <action name="start" action="setDefaultIntegerValue"/> </resource> - <resource name="ST_SignedTwipsMeasure" resource="UniversalMeasure"/> + <resource name="ST_SignedTwipsMeasure" resource="TwipsMeasure"/> <resource name="CT_SignedTwipsMeasure" resource="Value"> <attribute name="val" tokenid="ooxml:CT_SignedTwipsMeasure_val" action="setValue"/> <action name="start" action="setDefaultIntegerValue"/> @@ -16631,7 +16631,7 @@ <attribute name="val" tokenid="ooxml:CT_PixelsMeasure_val" action="setValue"/> <action name="start" action="setDefaultIntegerValue"/> </resource> - <resource name="ST_HpsMeasure" resource="Integer"/> + <resource name="ST_HpsMeasure" resource="HpsMeasure"/> <resource name="CT_HpsMeasure" resource="Value"> <attribute name="val" tokenid="ooxml:CT_HpsMeasure_val" action="setValue"/> <action name="start" action="setDefaultIntegerValue"/> |