From c893c0e359b82be71107e064bd2266c6daff81d7 Mon Sep 17 00:00:00 2001 From: Regina Henschel Date: Mon, 21 Feb 2022 23:08:10 +0100 Subject: tdf#147580 use valid values for extrusion-specularity The fix for tdf#145700 has changed the internal handling so, that values larger than 100% from MS binary import are now kept und correctly used. But ODF 1.2 and 1.3 have the range restricted to zeroToHundredPercent. The patch writes values larger than 100% in extended namespace for our 'ODF 1.3 extended'. It writes draw:extrusion-specularity in any case, so that older versions get a meaninful value, but clamps it to [0,100] if necessary to get valid files. Change-Id: I98298d5c3e3367ffe4a45cdc051be23679308119 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130306 Tested-by: Jenkins Reviewed-by: Michael Stahl --- xmloff/inc/EnhancedCustomShapeToken.hxx | 1 + .../unit/data/tdf147580_extrusion-specularity.doc | Bin 0 -> 27136 bytes xmloff/qa/unit/draw.cxx | 72 +++++++++++++++++++-- xmloff/source/core/xmltoken.cxx | 1 + xmloff/source/draw/EnhancedCustomShapeToken.cxx | 1 + xmloff/source/draw/shapeexport.cxx | 20 ++++++ xmloff/source/draw/ximpcustomshape.cxx | 9 ++- xmloff/source/token/tokens.txt | 1 + 8 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 xmloff/qa/unit/data/tdf147580_extrusion-specularity.doc (limited to 'xmloff') diff --git a/xmloff/inc/EnhancedCustomShapeToken.hxx b/xmloff/inc/EnhancedCustomShapeToken.hxx index 7fd86f5a5126..4438ba1260e5 100644 --- a/xmloff/inc/EnhancedCustomShapeToken.hxx +++ b/xmloff/inc/EnhancedCustomShapeToken.hxx @@ -54,6 +54,7 @@ namespace xmloff::EnhancedCustomShapeToken { EAS_extrusion_shininess, EAS_extrusion_skew, EAS_extrusion_specularity, + EAS_extrusion_specularity_loext, EAS_projection, EAS_extrusion_viewpoint, EAS_extrusion_origin, diff --git a/xmloff/qa/unit/data/tdf147580_extrusion-specularity.doc b/xmloff/qa/unit/data/tdf147580_extrusion-specularity.doc new file mode 100644 index 000000000000..9efe793d3d56 Binary files /dev/null and b/xmloff/qa/unit/data/tdf147580_extrusion-specularity.doc differ diff --git a/xmloff/qa/unit/draw.cxx b/xmloff/qa/unit/draw.cxx index 04c7178ca6bf..ac0801dce72b 100644 --- a/xmloff/qa/unit/draw.cxx +++ b/xmloff/qa/unit/draw.cxx @@ -296,9 +296,6 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testExtrusionMetalTypeExtended) // Test, that new attribute is written with loext namespace. Adapt when attribute is added to ODF. utl::TempFile aTempFile; - // The file has set c3DSpecularAmt="65536" to prevent validation error in attribute - // draw:extrusion-specularity. The error, that 122% is written in case of c3DSpecularAmt="80000" is - // not yet fixed. save("writer8", aTempFile); // assert XML. @@ -327,9 +324,6 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testExtrusionMetalTypeStrict) // added to ODF. const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion(GetODFDefaultVersion()); SetODFDefaultVersion(SvtSaveOptions::ODFVER_013); - // The file has set c3DSpecularAmt="65536" to prevent validation error in attribute - // draw:extrusion-specularity. The error, that 122% is written in case of c3DSpecularAmt="80000" is - // not yet fixed. utl::TempFile aTempFile; save("writer8", aTempFile); @@ -342,6 +336,72 @@ CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testExtrusionMetalTypeStrict) SetODFDefaultVersion(nCurrentODFVersion); } +namespace +{ +void lcl_assertSpecularityProperty(std::string_view sInfo, uno::Reference& rxShape) +{ + uno::Reference xShapeProps(rxShape, uno::UNO_QUERY); + uno::Sequence aGeoPropSeq; + xShapeProps->getPropertyValue("CustomShapeGeometry") >>= aGeoPropSeq; + comphelper::SequenceAsHashMap aGeoPropMap(aGeoPropSeq); + uno::Sequence aExtrusionSeq; + aGeoPropMap.getValue("Extrusion") >>= aExtrusionSeq; + comphelper::SequenceAsHashMap aExtrusionPropMap(aExtrusionSeq); + + double fSpecularity(-1.0); + aExtrusionPropMap.getValue("Specularity") >>= fSpecularity; + OString sMsg = OString::Concat(sInfo) + "Specularity"; + CPPUNIT_ASSERT_EQUAL_MESSAGE(sMsg.getStr(), 122.0703125, fSpecularity); +} +} + +CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testExtrusionSpecularityExtended) +{ + // import + getComponent() = loadFromDesktop(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "tdf147580_extrusion-specularity.doc", + "com.sun.star.text.TextDocument"); + // verify property + uno::Reference xShape(getShape(0)); + lcl_assertSpecularityProperty("from doc", xShape); + + // Test, that attribute is written in draw namespace with value 100% and in loext namespace with + // value 122.0703125%. + utl::TempFile aTempFile; + save("writer8", aTempFile); + + // assert XML. + std::unique_ptr pStream = parseExportStream(aTempFile, "content.xml"); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + assertXPath(pXmlDoc, "//draw:enhanced-geometry[@draw:extrusion-specularity='100%']"); + assertXPath(pXmlDoc, + "//draw:enhanced-geometry[@loext:extrusion-specularity-loext='122.0703125%']"); + + // reload and verify, that the loext value is used + getComponent()->dispose(); + getComponent() = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument"); + // verify properties + uno::Reference xShapeReload(getShape(0)); + lcl_assertSpecularityProperty("from ODF 1.3 extended", xShapeReload); +} + +CPPUNIT_TEST_FIXTURE(XmloffDrawTest, testExtrusionSpecularity) +{ + // import + getComponent() = loadFromDesktop(m_directories.getURLFromSrc(DATA_DIRECTORY) + + "tdf147580_extrusion-specularity.doc", + "com.sun.star.text.TextDocument"); + + // The file has c3DSpecularAmt="80000" which results internally in specularity=122%. + // Save to ODF 1.3 strict and make sure it does not produce a validation error. + const SvtSaveOptions::ODFDefaultVersion nCurrentODFVersion(GetODFDefaultVersion()); + SetODFDefaultVersion(SvtSaveOptions::ODFVER_013); + utl::TempFile aTempFile; + save("writer8", aTempFile); + + SetODFDefaultVersion(nCurrentODFVersion); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/core/xmltoken.cxx b/xmloff/source/core/xmltoken.cxx index f3ae86566e43..c7db64b00174 100644 --- a/xmloff/source/core/xmltoken.cxx +++ b/xmloff/source/core/xmltoken.cxx @@ -2479,6 +2479,7 @@ namespace xmloff::token { TOKEN( "extrusion-shininess" , XML_EXTRUSION_SHININESS ), TOKEN( "extrusion-skew" , XML_EXTRUSION_SKEW ), TOKEN( "extrusion-specularity" , XML_EXTRUSION_SPECULARITY ), + TOKEN( "extrusion-specularity-loext", XML_EXTRUSION_SPECULARITY_LOEXT ), TOKEN( "extrusion-projection-mode" , XML_EXTRUSION_PROJECTION_MODE ), TOKEN( "extrusion-viewpoint" , XML_EXTRUSION_VIEWPOINT ), TOKEN( "extrusion-origin" , XML_EXTRUSION_ORIGIN ), diff --git a/xmloff/source/draw/EnhancedCustomShapeToken.cxx b/xmloff/source/draw/EnhancedCustomShapeToken.cxx index 700e29fc71fd..bd0613e9e4b4 100644 --- a/xmloff/source/draw/EnhancedCustomShapeToken.cxx +++ b/xmloff/source/draw/EnhancedCustomShapeToken.cxx @@ -66,6 +66,7 @@ const TokenTable pTokenTableArray[] = { "extrusion-shininess", EAS_extrusion_shininess }, { "extrusion-skew", EAS_extrusion_skew }, { "extrusion-specularity", EAS_extrusion_specularity }, + { "extrusion-specularity-loext", EAS_extrusion_specularity_loext }, { "projection", EAS_projection }, { "extrusion-viewpoint", EAS_extrusion_viewpoint }, { "extrusion-origin", EAS_extrusion_origin }, diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx index ea33330994b1..bc642d344e68 100644 --- a/xmloff/source/draw/shapeexport.cxx +++ b/xmloff/source/draw/shapeexport.cxx @@ -4556,6 +4556,26 @@ static void ImpExportEnhancedGeometry( SvXMLExport& rExport, const uno::Referenc double fExtrusionSpecularity = 0; if ( rProp.Value >>= fExtrusionSpecularity ) { + SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion(); + if (fExtrusionSpecularity > 100.0 && eVersion >= SvtSaveOptions::ODFSVER_012 + && (eVersion & SvtSaveOptions::ODFSVER_EXTENDED)) + { + // tdf#147580 write values > 100% in loext + ::sax::Converter::convertDouble( + aStrBuffer, + fExtrusionSpecularity, + false, + util::MeasureUnit::PERCENT, + util::MeasureUnit::PERCENT); + aStrBuffer.append( '%' ); + aStr = aStrBuffer.makeStringAndClear(); + rExport.AddAttribute( XML_NAMESPACE_LO_EXT, XML_EXTRUSION_SPECULARITY_LOEXT, aStr ); + } + // tdf#147580 ODF 1 allows arbitrary percent, later versions not + if (eVersion >= SvtSaveOptions::ODFSVER_012) + { + fExtrusionSpecularity = std::clamp(fExtrusionSpecularity, 0.0, 100.0); + } ::sax::Converter::convertDouble( aStrBuffer, fExtrusionSpecularity, diff --git a/xmloff/source/draw/ximpcustomshape.cxx b/xmloff/source/draw/ximpcustomshape.cxx index df86901b9635..ab567b6bd178 100644 --- a/xmloff/source/draw/ximpcustomshape.cxx +++ b/xmloff/source/draw/ximpcustomshape.cxx @@ -866,6 +866,7 @@ void XMLEnhancedCustomShapeContext::startFastElement( const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) { sal_Int32 nAttrNumber; + std::optional oSpecularityValue; // for postpone extrusion-specularity for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) { switch( EASGet( aIter.getToken() ) ) @@ -1024,7 +1025,11 @@ void XMLEnhancedCustomShapeContext::startFastElement( GetEnhancedParameterPair( maExtrusion, aIter.toString(), EAS_Skew ); break; case EAS_extrusion_specularity : - GetDoublePercentage( maExtrusion, aIter.toView(), EAS_Specularity ); + if (!oSpecularityValue) + oSpecularityValue = aIter.toView(); + break; + case EAS_extrusion_specularity_loext : + oSpecularityValue = aIter.toView(); break; case EAS_projection : { @@ -1125,6 +1130,8 @@ void XMLEnhancedCustomShapeContext::startFastElement( break; } } + if (oSpecularityValue) + GetDoublePercentage( maExtrusion, *oSpecularityValue, EAS_Specularity ); } static void SdXMLCustomShapePropertyMerge( std::vector< css::beans::PropertyValue >& rPropVec, diff --git a/xmloff/source/token/tokens.txt b/xmloff/source/token/tokens.txt index f610bfbff47e..ec591c072789 100644 --- a/xmloff/source/token/tokens.txt +++ b/xmloff/source/token/tokens.txt @@ -2326,6 +2326,7 @@ extrusion-rotation-center extrusion-shininess extrusion-skew extrusion-specularity +extrusion-specularity-loext extrusion-projection-mode extrusion-viewpoint extrusion-origin -- cgit