From 33eb9fdb61033b3fd35d923900b1f5791f4b71c8 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Tue, 17 Oct 2017 17:24:03 +0200 Subject: 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 --- 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 | 67 +- 7 files changed, 900 insertions(+), 11 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 7e5e3e1460df..ee7dfe17b36b 100644 --- a/filter/source/msfilter/escherex.cxx +++ b/filter/source/msfilter/escherex.cxx @@ -3450,7 +3450,8 @@ void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeT { drawing::TextFitToSizeType const eFTS( static_cast(pCustoShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() ); - if (eFTS == drawing::TextFitToSizeType_ALLLINES) + if (eFTS == drawing::TextFitToSizeType_ALLLINES || + eFTS == drawing::TextFitToSizeType_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 055d79bdf03e..e7c2ba532d33 100644 --- a/sd/qa/unit/export-tests.cxx +++ b/sd/qa/unit/export-tests.cxx @@ -79,6 +79,7 @@ public: void testN821567(); void testMediaEmbedding(); void testFdo84043(); + void testTdf97630(); void testSwappedOutImageExport(); void testOOoXMLAnimations(); void testTdf80020(); @@ -96,6 +97,7 @@ public: CPPUNIT_TEST(testN821567); CPPUNIT_TEST(testMediaEmbedding); CPPUNIT_TEST(testFdo84043); + CPPUNIT_TEST(testTdf97630); CPPUNIT_TEST(testSwappedOutImageExport); CPPUNIT_TEST(testOOoXMLAnimations); CPPUNIT_TEST(testTdf80020); @@ -126,6 +128,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) { @@ -247,6 +250,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 486dd9aff0a7..3211065f868b 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 == drawing::TextFitToSizeType_ALLLINES) + if (eFTS == drawing::TextFitToSizeType_ALLLINES || + // tdf#97630 interpret PROPORTIONAL same as ALLLINES so we don't + // need another ODF attribute! + eFTS == drawing::TextFitToSizeType_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 71a2c5653a92..ed9f00b333b1 100644 --- a/svx/source/toolbars/fontworkbar.cxx +++ b/svx/source/toolbars/fontworkbar.cxx @@ -73,10 +73,16 @@ void SetAlignmentState( SdrView const * pSdrView, SfxItemSet& rSet ) case SDRTEXTHORZADJUST_RIGHT : nAlignment = 2; break; case SDRTEXTHORZADJUST_BLOCK : { - if (rTextFitToSizeTypeItem.GetValue() == drawing::TextFitToSizeType_NONE) + auto const fit(rTextFitToSizeTypeItem.GetValue()); + if (fit == drawing::TextFitToSizeType_NONE) + { nAlignment = 3; - else if (rTextFitToSizeTypeItem.GetValue() == drawing::TextFitToSizeType_ALLLINES) + } + else if (fit == drawing::TextFitToSizeType_ALLLINES || + fit == drawing::TextFitToSizeType_PROPORTIONAL) + { nAlignment = 4; + } } } if ( ( nOldAlignment != -1 ) && ( nOldAlignment != nAlignment ) ) diff --git a/xmloff/inc/xmlsdtypes.hxx b/xmloff/inc/xmlsdtypes.hxx index 86e81ba3ea5b..b49639d43a94 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 7e1473199aef..163cc7a6a991 100644 --- a/xmloff/source/draw/sdpropls.cxx +++ b/xmloff/source/draw/sdpropls.cxx @@ -129,7 +129,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 ), @@ -614,12 +615,13 @@ static SvXMLEnumMapEntry const pXML_VerticalAlign_E { XML_TOKEN_INVALID, (drawing::TextVerticalAdjust)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, (drawing::TextFitToSizeType)0 } }; @@ -632,6 +634,15 @@ static SvXMLEnumMapEntry const pXML_FitToSize_Enum[] { XML_TOKEN_INVALID, (drawing::TextFitToSizeType)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 }, @@ -892,6 +903,38 @@ bool XMLSdRotationAngleTypeHdl::exportXML( return bRet; } +class XMLFitToSizeEnumPropertyHdl : public XMLEnumPropertyHdl +{ +public: + XMLFitToSizeEnumPropertyHdl( + const SvXMLEnumMapEntry *const pMap) + : XMLEnumPropertyHdl(pMap) {} + + 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 ) { @@ -1086,17 +1129,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); + pHdl = new XMLFitToSizeEnumPropertyHdl(pXML_FitToSize_Enum_Odf12); } else - { - pHdl = new XMLEnumPropertyHdl(pXML_FitToSize_Enum); + { // 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 ); break; -- cgit v1.2.3