From e2aea006ba385dfbbfde27997372c4d941561b2c Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Tue, 17 Oct 2017 17:24:03 +0200 Subject: [PATCH] tdf#97630 xmloff: ODF extended draw:fit-to-size mess The plan: 1. As Regina points out, there is already (in ODF 1.2, but not ODF 1.1) a style:shrink-to-fit attribute for shapes, so use this to represent the AUTOFIT value. The fallback from AUTOFIT to draw:fit-to-size="true" was a stupid idea anyway, probably "false" is less annoying in practice. There are 2 different shapes that implement TextFitToSize property: a) text shapes already interpret ALLLINES and PROPORTIONAL exactly the same b) fontwork custom shapes interpret ALLLINES but do nothing for PROPORTIONAL As Regina points out, there is no shape that needs to distinguish between ALLLINES and PROPORTIONAL, so we do a minor behavioral API CHANGE and from now on interpret PROPORTIONAL as ALLLINES on fontwork custom shapes. This obviates the need to distinguish the values in ODF and so we don't need a new attribute, just use draw:fit-to-size="true" for both. On import, use MID_FLAG_MERGE_PROPERTY to combine the 2 attributes into one value. 2. Restrict the export of draw:fit-to-size to only the standard values "true"/"false". This implements step 1, the step 2 will be done in the future when most users have the import of the style:shrink-to-fit. Change-Id: I4a378aa110fdb82db7a99a839d7ff207248a73e7 Reviewed-on: https://gerrit.libreoffice.org/43521 Tested-by: Jenkins Reviewed-by: Michael Stahl (cherry picked from commit 33eb9fdb61033b3fd35d923900b1f5791f4b71c8) --- filter/source/msfilter/escherex.cxx | 3 +- sd/qa/unit/data/fit-to-size.fodp | 724 +++++++++++++++++++++ sd/qa/unit/export-tests.cxx | 101 +++ .../customshapes/EnhancedCustomShapeFontWork.cxx | 5 +- svx/source/toolbars/fontworkbar.cxx | 10 +- xmloff/inc/xmlsdtypes.hxx | 1 + xmloff/source/draw/sdpropls.cxx | 71 +- 7 files changed, 902 insertions(+), 13 deletions(-) create mode 100644 sd/qa/unit/data/fit-to-size.fodp diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx index b8b5b831bd99..4285bcd04c14 100644 --- a/filter/source/msfilter/escherex.cxx +++ b/filter/source/msfilter/escherex.cxx @@ -3470,7 +3470,8 @@ void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeT case drawing::TextHorizontalAdjust_BLOCK: { SdrFitToSizeType eFTS( static_cast(pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() ); - if ( eFTS == SdrFitToSizeType::AllLines) + if (eFTS == SdrFitToSizeType::AllLines || + eFTS == SdrFitToSizeType::Proportional) { gTextAlign = mso_alignTextStretch; } diff --git a/sd/qa/unit/data/fit-to-size.fodp b/sd/qa/unit/data/fit-to-size.fodp new file mode 100644 index 000000000000..734cf8a3a6c6 --- /dev/null +++ b/sd/qa/unit/data/fit-to-size.fodp @@ -0,0 +1,724 @@ + + + 2017-10-18T22:06:17.2032716482017-10-19T22:51:45.845520353PT31M43S4LibreOfficeDev/5.3.8.0.0$Linux_X86_64 LibreOffice_project/a0fae00a2d52960eebbb14f08d2de251e0a8ff3f + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number><number> + + + + + + + + + + + + + + + + + + + + + + + + + + <number><number> + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number><number> + + + + + + + + + + + 1 + foo + + + + + 2 + foo + + + + + 3 + foo + + + + + 4 + foo + + + + 5 + Fontwork + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 + Fontwork + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx index 3f2882384031..6bbb2a53648b 100644 --- a/sd/qa/unit/export-tests.cxx +++ b/sd/qa/unit/export-tests.cxx @@ -84,6 +84,7 @@ public: void testN821567(); void testMediaEmbedding(); void testFdo84043(); + void testTdf97630(); void testSwappedOutImageExport(); void testOOoXMLAnimations(); void testTdf80020(); @@ -98,6 +99,7 @@ public: CPPUNIT_TEST(testN821567); CPPUNIT_TEST(testMediaEmbedding); CPPUNIT_TEST(testFdo84043); + CPPUNIT_TEST(testTdf97630); CPPUNIT_TEST(testSwappedOutImageExport); CPPUNIT_TEST(testOOoXMLAnimations); CPPUNIT_TEST(testTdf80020); @@ -125,6 +127,7 @@ public: { "table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0" }, { "text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0" }, { "xlink", "http://www.w3c.org/1999/xlink" }, + { "loext", "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" }, }; for (size_t i = 0; i < SAL_N_ELEMENTS(namespaces); ++i) { @@ -246,6 +249,104 @@ void SdExportTest::testFdo84043() xDocShRef->DoClose(); } +void SdExportTest::testTdf97630() +{ + ::sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/fit-to-size.fodp"), FODP); + + { + uno::Reference xDPS(xDocShRef->GetModel(), uno::UNO_QUERY); + uno::Reference xDP(xDPS->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + + drawing::TextFitToSizeType tmp; + // text shapes + uno::Reference xShape0(xDP->getByIndex(0), uno::UNO_QUERY); + xShape0->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_NONE, tmp); + uno::Reference xShape1(xDP->getByIndex(1), uno::UNO_QUERY); + xShape1->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_PROPORTIONAL, tmp); + uno::Reference xShape2(xDP->getByIndex(2), uno::UNO_QUERY); + xShape2->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_ALLLINES, tmp); + uno::Reference xShape3(xDP->getByIndex(3), uno::UNO_QUERY); + xShape3->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_AUTOFIT, tmp); + + // fontworks + uno::Reference xShape4(xDP->getByIndex(4), uno::UNO_QUERY); + xShape4->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_NONE, tmp); + uno::Reference xShape5(xDP->getByIndex(5), uno::UNO_QUERY); + xShape5->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_ALLLINES, tmp); + + } + + utl::TempFile aTempFile; + xDocShRef = saveAndReload(xDocShRef.get(), ODP, &aTempFile); + + { + uno::Reference xDPS(xDocShRef->GetModel(), uno::UNO_QUERY); + uno::Reference xDP(xDPS->getDrawPages()->getByIndex(0), uno::UNO_QUERY); + + drawing::TextFitToSizeType tmp; + // text shapes + uno::Reference xShape0(xDP->getByIndex(0), uno::UNO_QUERY); + xShape0->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_NONE, tmp); + uno::Reference xShape1(xDP->getByIndex(1), uno::UNO_QUERY); + xShape1->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_PROPORTIONAL, tmp); + uno::Reference xShape2(xDP->getByIndex(2), uno::UNO_QUERY); + xShape2->getPropertyValue("TextFitToSize") >>= tmp; +#if 1 +// TODO see TODO in sdpropls.cxx + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_ALLLINES, tmp); +#else + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_PROPORTIONAL, tmp); +#endif + uno::Reference xShape3(xDP->getByIndex(3), uno::UNO_QUERY); + xShape3->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_AUTOFIT, tmp); + + // fontworks + uno::Reference xShape4(xDP->getByIndex(4), uno::UNO_QUERY); + xShape4->getPropertyValue("TextFitToSize") >>= tmp; + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_NONE, tmp); + uno::Reference xShape5(xDP->getByIndex(5), uno::UNO_QUERY); + xShape5->getPropertyValue("TextFitToSize") >>= tmp; +#if 1 +// TODO see TODO in sdpropls.cxx + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_ALLLINES, tmp); +#else + CPPUNIT_ASSERT_EQUAL(drawing::TextFitToSizeType_PROPORTIONAL, tmp); +#endif + } + + xmlDocPtr pXmlDoc = parseExport(aTempFile, "content.xml"); + // text shapes + assertXPath(pXmlDoc, "//style:style[@style:family='presentation']/style:graphic-properties[@draw:fit-to-size='false' and @style:shrink-to-fit='false']", 1); +#if 1 +// TODO see TODO in sdpropls.cxx + assertXPath(pXmlDoc, "//style:style[@style:family='presentation']/style:graphic-properties[@draw:fit-to-size='true' and @style:shrink-to-fit='false']", 1); + assertXPath(pXmlDoc, "//style:style[@style:family='presentation']/style:graphic-properties[@draw:fit-to-size='all' and @style:shrink-to-fit='false']", 1); + assertXPath(pXmlDoc, "//style:style[@style:family='presentation']/style:graphic-properties[@draw:fit-to-size='shrink-to-fit' and @style:shrink-to-fit='true']", 1); +#else + assertXPath(pXmlDoc, "//style:style[@style:family='presentation']/style:graphic-properties[@draw:fit-to-size='true' and @style:shrink-to-fit='false']", 2); + assertXPath(pXmlDoc, "//style:style[@style:family='presentation']/style:graphic-properties[@draw:fit-to-size='false' and @style:shrink-to-fit='true']", 1); +#endif + // fontworks + assertXPath(pXmlDoc, "//style:style[@style:family='graphic']/style:graphic-properties[@draw:fit-to-size='false' and @style:shrink-to-fit='false']", 1); +#if 1 +// TODO see TODO in sdpropls.cxx + assertXPath(pXmlDoc, "//style:style[@style:family='graphic']/style:graphic-properties[@draw:fit-to-size='all' and @style:shrink-to-fit='false']", 1); +#else + assertXPath(pXmlDoc, "//style:style[@style:family='graphic']/style:graphic-properties[@draw:fit-to-size='true' and @style:shrink-to-fit='false']", 1); +#endif + + xDocShRef->DoClose(); +} + void SdExportTest::testSwappedOutImageExport() { // Problem was with the swapped out images, which were not swapped in during export. diff --git a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx index a999791a5c5a..26f227e8b9a4 100644 --- a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx +++ b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx @@ -433,7 +433,10 @@ void GetFontWorkOutline( FWData& rFWData, const SdrObject* pCustomShape ) while ( aTextAreaIter != aTextAreaIEnd ) { GetTextAreaOutline( rFWData, pCustomShape, *aTextAreaIter, bSameLetterHeights ); - if ( eFTS == SdrFitToSizeType::AllLines ) + if (eFTS == SdrFitToSizeType::AllLines || + // tdf#97630 interpret PROPORTIONAL same as ALLLINES so we don't + // need another ODF attribute! + eFTS == SdrFitToSizeType::Proportional) { std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() ); std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() ); diff --git a/svx/source/toolbars/fontworkbar.cxx b/svx/source/toolbars/fontworkbar.cxx index a148de31cf13..329cd2bcb006 100644 --- a/svx/source/toolbars/fontworkbar.cxx +++ b/svx/source/toolbars/fontworkbar.cxx @@ -73,10 +73,16 @@ void SetAlignmentState( SdrView* pSdrView, SfxItemSet& rSet ) case SDRTEXTHORZADJUST_RIGHT : nAlignment = 2; break; case SDRTEXTHORZADJUST_BLOCK : { - if ( rTextFitToSizeTypeItem.GetValue() == SdrFitToSizeType::NONE ) + auto const fit(rTextFitToSizeTypeItem.GetValue()); + if (fit == SdrFitToSizeType::NONE) + { nAlignment = 3; - else if ( rTextFitToSizeTypeItem.GetValue() == SdrFitToSizeType::AllLines ) + } + else if (fit == SdrFitToSizeType::AllLines || + fit == SdrFitToSizeType::Proportional) + { nAlignment = 4; + } } } if ( ( nOldAlignment != -1 ) && ( nOldAlignment != nAlignment ) ) diff --git a/xmloff/inc/xmlsdtypes.hxx b/xmloff/inc/xmlsdtypes.hxx index 8e388cf032c7..675b16fc1377 100644 --- a/xmloff/inc/xmlsdtypes.hxx +++ b/xmloff/inc/xmlsdtypes.hxx @@ -67,6 +67,7 @@ #define XML_SD_TYPE_CONTROL_BORDER_COLOR (XML_SD_TYPES_START + 33 ) #define XML_SD_TYPE_IMAGE_SCALE_MODE (XML_SD_TYPES_START + 34 ) #define XML_SD_TYPE_LINECAP (XML_SD_TYPES_START + 35 ) +#define XML_SD_TYPE_FITTOSIZE_AUTOFIT (XML_SD_TYPES_START + 36 ) ////////////////////////////////////////////////////////////////////////////// // 3D property types diff --git a/xmloff/source/draw/sdpropls.cxx b/xmloff/source/draw/sdpropls.cxx index 72d6315fa088..12c900eb50cc 100644 --- a/xmloff/source/draw/sdpropls.cxx +++ b/xmloff/source/draw/sdpropls.cxx @@ -131,7 +131,8 @@ const XMLPropertyMapEntry aXMLSDProperties[] = GMAP( "TextVerticalAdjust", XML_NAMESPACE_DRAW, XML_TEXTAREA_VERTICAL_ALIGN, XML_SD_TYPE_VERTICAL_ALIGN, 0 ), GMAP( "TextAutoGrowHeight", XML_NAMESPACE_DRAW, XML_AUTO_GROW_HEIGHT, XML_TYPE_BOOL, 0 ), GMAP( "TextAutoGrowWidth", XML_NAMESPACE_DRAW, XML_AUTO_GROW_WIDTH, XML_TYPE_BOOL, 0 ), - GMAP( "TextFitToSize", XML_NAMESPACE_DRAW, XML_FIT_TO_SIZE, XML_SD_TYPE_FITTOSIZE, 0 ), + GMAP( "TextFitToSize", XML_NAMESPACE_DRAW, XML_FIT_TO_SIZE, XML_SD_TYPE_FITTOSIZE|MID_FLAG_MERGE_PROPERTY, 0), + GMAPV( "TextFitToSize", XML_NAMESPACE_STYLE, XML_SHRINK_TO_FIT, XML_SD_TYPE_FITTOSIZE_AUTOFIT|MID_FLAG_MERGE_PROPERTY, 0, SvtSaveOptions::ODFVER_012 ), GMAP( "TextContourFrame", XML_NAMESPACE_DRAW, XML_FIT_TO_CONTOUR, XML_TYPE_BOOL, 0 ), GMAP( "TextMaximumFrameHeight", XML_NAMESPACE_FO, XML_MAX_HEIGHT, XML_TYPE_MEASURE, 0 ), GMAP( "TextMaximumFrameWidth", XML_NAMESPACE_FO, XML_MAX_WIDTH, XML_TYPE_MEASURE, 0 ), @@ -615,12 +616,13 @@ static SvXMLEnumMapEntry const pXML_VerticalAlign_Enum[] = { XML_TOKEN_INVALID, 0 } }; +// note: PROPORTIONAL and ALLLINES are the same thing now! static SvXMLEnumMapEntry const pXML_FitToSize_Enum_Odf12[] = { { XML_FALSE, drawing::TextFitToSizeType_NONE }, { XML_TRUE, drawing::TextFitToSizeType_PROPORTIONAL }, { XML_TRUE, drawing::TextFitToSizeType_ALLLINES }, - { XML_TRUE, drawing::TextFitToSizeType_AUTOFIT }, + { XML_FALSE, drawing::TextFitToSizeType_AUTOFIT }, { XML_TOKEN_INVALID, 0 } }; @@ -633,6 +635,15 @@ static SvXMLEnumMapEntry const pXML_FitToSize_Enum[] = { XML_TOKEN_INVALID, 0 } }; +static SvXMLEnumMapEntry const pXML_ShrinkToFit_Enum[] = +{ + { XML_FALSE, drawing::TextFitToSizeType_NONE }, + { XML_FALSE, drawing::TextFitToSizeType_PROPORTIONAL }, + { XML_FALSE, drawing::TextFitToSizeType_ALLLINES }, + { XML_TRUE, drawing::TextFitToSizeType_AUTOFIT }, + { XML_TOKEN_INVALID, (drawing::TextFitToSizeType)0 } +}; + static SvXMLEnumMapEntry const pXML_MeasureUnit_Enum[] = { { XML_AUTOMATIC, 0 }, @@ -853,6 +864,40 @@ bool XMLSdHeaderFooterVisibilityTypeHdl::exportXML( return bRet; } +class XMLFitToSizeEnumPropertyHdl : public XMLEnumPropertyHdl +{ +public: + XMLFitToSizeEnumPropertyHdl( + const SvXMLEnumMapEntry *const pMap) + : XMLEnumPropertyHdl(pMap, cppu::UnoType::get()) + { + } + + virtual bool importXML(const OUString& rStrImpValue, uno::Any& rValue, + const SvXMLUnitConverter& rUC) const override + { + // we don't know here what the actual attribute name is - + // but we can combine the 2 attributes by just taking the + // "largest" result value; this can never result in ALLLINES + // so the implementation has to interpret PROPORTIONAL as ALLLINES; + // both "true" is invalid anyway. + Any any; + auto const bRet = XMLEnumPropertyHdl::importXML(rStrImpValue, any, rUC); + if (!bRet) + { + return false; + } + assert(any.hasValue()); + if (!rValue.hasValue() || + rValue.get() < any.get()) + { + rValue = any; + } + return true; + } +}; + + XMLSdPropHdlFactory::XMLSdPropHdlFactory( uno::Reference< frame::XModel > const & xModel, SvXMLImport& rImport ) : mxModel( xModel ), mpExport(nullptr), mpImport( &rImport ) { @@ -1047,19 +1092,27 @@ const XMLPropertyHandler* XMLSdPropHdlFactory::GetPropertyHandler( sal_Int32 nTy break; case XML_SD_TYPE_FITTOSIZE: { - if (mpExport && (mpExport->getDefaultVersion() - <= SvtSaveOptions::ODFVER_012)) + if (mpExport +#if 1 +// TODO: remove in a couple releases, when users have the import of style:shrink-to-fit + && (mpExport->getDefaultVersion() + <= SvtSaveOptions::ODFVER_012) +#endif + ) { - pHdl = new XMLEnumPropertyHdl(pXML_FitToSize_Enum_Odf12, - cppu::UnoType::get()); + pHdl = new XMLFitToSizeEnumPropertyHdl(pXML_FitToSize_Enum_Odf12); } else - { - pHdl = new XMLEnumPropertyHdl(pXML_FitToSize_Enum, - cppu::UnoType::get()); + { // import all values written by old LO + pHdl = new XMLFitToSizeEnumPropertyHdl(pXML_FitToSize_Enum); } } break; + case XML_SD_TYPE_FITTOSIZE_AUTOFIT: + { + pHdl = new XMLFitToSizeEnumPropertyHdl(pXML_ShrinkToFit_Enum); + } + break; case XML_SD_TYPE_MEASURE_UNIT: pHdl = new XMLEnumPropertyHdl( pXML_MeasureUnit_Enum, ::cppu::UnoType::get() ); break; -- 2.14.1