include/svx/svddef.hxx | 4 ++ oox/source/drawingml/table/tablecell.cxx | 38 ++++++++++++++++++++++---- oox/source/export/shapes.cxx | 14 +++++++++ sd/qa/unit/data/pptx/tcPr-vert-roundtrip.pptx |binary sd/qa/unit/export-tests-ooxml3.cxx | 16 ++++++++++ svx/source/inc/cell.hxx | 3 ++ svx/source/svdraw/svdattr.cxx | 3 ++ svx/source/table/cell.cxx | 21 ++++++++++++++ 8 files changed, 93 insertions(+), 6 deletions(-)
New commits: commit e87a5b20dd73a3333e1e19cd43198bb7c8ba9ec2 Author: Sarper Akdemir <sarper.akde...@collabora.com> AuthorDate: Wed Mar 29 19:44:18 2023 +0300 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Apr 19 12:57:59 2023 +0200 oox: tcPr vert roundtrip, introduce interopability grab bag for table cell To properly roundtrip all possible values of <a:tcPr vert="..."> + Introduce grab bag for table cell + on import: Store the unsupported values in the grab bag: + (e.g. wordArtVert, mongolianVert, wordArtVertRtl) + on export: if nothing is being exported from the doc model, export the value from the grabbag Also adds a unit test covering this behavior. Change-Id: I791ed2d992b0a554ef6da37200f027cffd8c5f2f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149737 Tested-by: Jenkins Reviewed-by: Sarper Akdemir <sarper.akde...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150521 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/include/svx/svddef.hxx b/include/svx/svddef.hxx index 9b3b1a358369..2bb5068f5661 100644 --- a/include/svx/svddef.hxx +++ b/include/svx/svddef.hxx @@ -138,6 +138,7 @@ class SdrVertShearAllItem; class SdrVertShearOneItem; class SdrYesNoItem; class SfxBoolItem; +class SfxGrabBagItem; class SfxInt16Item; class SfxUInt16Item; class SfxUInt32Item; @@ -416,7 +417,8 @@ constexpr TypedWhichId<SvxBoxInfoItem> SDRATTR_TABLE_BORDER_INNER (SDRATTR_T constexpr TypedWhichId<SvxLineItem> SDRATTR_TABLE_BORDER_TLBR (SDRATTR_TABLE_FIRST+2); constexpr TypedWhichId<SvxLineItem> SDRATTR_TABLE_BORDER_BLTR (SDRATTR_TABLE_FIRST+3); constexpr TypedWhichId<SvxTextRotateItem> SDRATTR_TABLE_TEXT_ROTATION (SDRATTR_TABLE_FIRST+4); -constexpr sal_uInt16 SDRATTR_TABLE_LAST (SDRATTR_TABLE_TEXT_ROTATION); +constexpr TypedWhichId<SfxGrabBagItem> SDRATTR_TABLE_GRABBAG (SDRATTR_TABLE_FIRST+5); +constexpr sal_uInt16 SDRATTR_TABLE_LAST (SDRATTR_TABLE_GRABBAG); constexpr sal_uInt16 SDRATTR_GLOW_FIRST (SDRATTR_TABLE_LAST+1); constexpr TypedWhichId<SdrMetricItem> SDRATTR_GLOW_RADIUS (SDRATTR_GLOW_FIRST+0); diff --git a/oox/source/drawingml/table/tablecell.cxx b/oox/source/drawingml/table/tablecell.cxx index 19347db21539..37408aaf4ba5 100644 --- a/oox/source/drawingml/table/tablecell.cxx +++ b/oox/source/drawingml/table/tablecell.cxx @@ -29,12 +29,15 @@ #include <oox/helper/propertyset.hxx> #include <oox/token/properties.hxx> #include <oox/token/tokens.hxx> +#include <oox/token/tokenmap.hxx> #include <tools/color.hxx> #include <com/sun/star/table/BorderLineStyle.hpp> #include <com/sun/star/table/BorderLine2.hpp> #include <com/sun/star/drawing/TextVerticalAdjust.hpp> #include <com/sun/star/text/XText.hpp> #include <com/sun/star/text/WritingMode.hpp> +#include <comphelper/propertysequence.hxx> +#include <comphelper/propertyvalue.hxx> using namespace ::oox::core; using namespace ::com::sun::star; @@ -550,6 +553,36 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons { xPropSet->setPropertyValue("TextWritingMode", Any(css::text::WritingMode_TB_RL)); } + else if ( getVertToken() == XML_vert ) + { + xPropSet->setPropertyValue("RotateAngle", Any(short(27000))); + } + else if ( getVertToken() == XML_vert270 ) + { + xPropSet->setPropertyValue("RotateAngle", Any(short(9000))); + } + else if ( getVertToken() != XML_horz ) + { + // put the vert value in the grab bag for roundtrip + const Sequence<sal_Int8>& aTokenNameSeq = StaticTokenMap().getUtf8TokenName(getVertToken()); + const OUString aTokenName{ reinterpret_cast<const char*>(aTokenNameSeq.getConstArray()), + aTokenNameSeq.getLength(), RTL_TEXTENCODING_UTF8 }; + + Sequence<PropertyValue> aGrabBag; + xPropSet->getPropertyValue("CellInteropGrabBag") >>= aGrabBag; + PropertyValue aPropertyValue = comphelper::makePropertyValue("mso-tcPr-vert-value", aTokenName); + if (aGrabBag.hasElements()) + { + sal_Int32 nLength = aGrabBag.getLength(); + aGrabBag.realloc(nLength + 1); + aGrabBag.getArray()[nLength] = aPropertyValue; + } + else + { + aGrabBag = { aPropertyValue }; + } + xPropSet->setPropertyValue("CellInteropGrabBag", Any(aGrabBag)); + } getTextBody()->insertAt( rFilterBase, xText, xAt, aTextStyleProps, pMasterTextListStyle ); @@ -566,11 +599,6 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, cons aTextCharacterProps.pushToPropSet(aPropSet, rFilterBase); } } - - if (getVertToken() == XML_vert) - xPropSet->setPropertyValue("RotateAngle", Any(short(27000))); - else if (getVertToken() == XML_vert270) - xPropSet->setPropertyValue("RotateAngle", Any(short(9000))); } } diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index d82ac51a36b8..f0630f988dd1 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -1956,6 +1956,20 @@ void ShapeExport::WriteTableCellProperties(const Reference< XPropertySet>& xCell aRotateAngle >>= nRotateAngle; std::optional<OString> aTextVerticalValue = GetTextVerticalType(nRotateAngle); + Sequence<PropertyValue> aGrabBag; + if( !aTextVerticalValue && + (xCellPropSet->getPropertyValue("CellInteropGrabBag") >>= aGrabBag) ) + { + for (auto const& rIt : std::as_const(aGrabBag)) + { + if (rIt.Name == "mso-tcPr-vert-value") + { + aTextVerticalValue = rIt.Value.get<OUString>().toUtf8(); + break; + } + } + } + mpFS->startElementNS(XML_a, XML_tcPr, XML_anchor, sVerticalAlignment, XML_vert, aTextVerticalValue, XML_marL, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nLeftMargin)), nLeftMargin > 0), diff --git a/sd/qa/unit/data/pptx/tcPr-vert-roundtrip.pptx b/sd/qa/unit/data/pptx/tcPr-vert-roundtrip.pptx new file mode 100644 index 000000000000..9600f5ec1d98 Binary files /dev/null and b/sd/qa/unit/data/pptx/tcPr-vert-roundtrip.pptx differ diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx index a69c45ca3e55..d9da7ea8b395 100644 --- a/sd/qa/unit/export-tests-ooxml3.cxx +++ b/sd/qa/unit/export-tests-ooxml3.cxx @@ -2089,6 +2089,22 @@ void SdOOXMLExportTest3::testTdf94122_autoColor() "val", "000000"); } +CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTableCellVerticalPropertyRoundtrip) +{ + ::sd::DrawDocShellRef xDocShRef = loadURL( + m_directories.getURLFromSrc(u"sd/qa/unit/data/pptx/tcPr-vert-roundtrip.pptx"), PPTX); + + utl::TempFile tempFile; + xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile); + xDocShRef->DoClose(); + + xmlDocUniquePtr pXml = parseExport(tempFile, "ppt/slides/slide1.xml"); + + assertXPath(pXml, "(//a:tcPr)[1]", "vert", "vert270"); + assertXPath(pXml, "(//a:tcPr)[2]", "vert", "vert"); + assertXPath(pXml, "(//a:tcPr)[3]", "vert", "wordArtVert"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest3); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/svx/source/inc/cell.hxx b/svx/source/inc/cell.hxx index 36ce254d1aa7..8682f4de0752 100644 --- a/svx/source/inc/cell.hxx +++ b/svx/source/inc/cell.hxx @@ -27,6 +27,7 @@ #include <rtl/ref.hxx> #include <svl/style.hxx> +#include <svl/grabbagitem.hxx> #include <svx/sdtaitm.hxx> #include "tablemodel.hxx" #include <editeng/unotext.hxx> @@ -210,6 +211,8 @@ private: tools::Rectangle maCellRect; css::uno::Reference< css::table::XTable > mxTable; + + std::unique_ptr<SfxGrabBagItem> mpGrabBagItem = {}; }; diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx index b71ac9919f4a..e6ae60c877c8 100644 --- a/svx/source/svdraw/svdattr.cxx +++ b/svx/source/svdraw/svdattr.cxx @@ -43,6 +43,8 @@ #include <vcl/svapp.hxx> #include <vcl/settings.hxx> +#include <svl/grabbagitem.hxx> + #include <svx/strings.hrc> #include <svx/dialmgr.hxx> #include <svx/sdgcpitm.hxx> @@ -326,6 +328,7 @@ SdrItemPool::SdrItemPool( rPoolDefaults[ SDRATTR_TABLE_BORDER_TLBR - SDRATTR_START ] = new SvxLineItem( SDRATTR_TABLE_BORDER_TLBR ); rPoolDefaults[ SDRATTR_TABLE_BORDER_BLTR - SDRATTR_START ] = new SvxLineItem( SDRATTR_TABLE_BORDER_BLTR ); rPoolDefaults[ SDRATTR_TABLE_TEXT_ROTATION - SDRATTR_START ] = new SvxTextRotateItem(0_deg10, SDRATTR_TABLE_TEXT_ROTATION); + rPoolDefaults[ SDRATTR_TABLE_GRABBAG - SDRATTR_START ] = new SfxGrabBagItem(SDRATTR_TABLE_GRABBAG); rPoolDefaults[ SDRATTR_GLOW_RADIUS - SDRATTR_START ] = new SdrMetricItem(SDRATTR_GLOW_RADIUS, 0); rPoolDefaults[ SDRATTR_GLOW_COLOR - SDRATTR_START ] = new XColorItem(SDRATTR_GLOW_COLOR, aNullCol); diff --git a/svx/source/table/cell.cxx b/svx/source/table/cell.cxx index 8aef7510e45a..b4a246b73ea5 100644 --- a/svx/source/table/cell.cxx +++ b/svx/source/table/cell.cxx @@ -27,6 +27,7 @@ #include <comphelper/sequence.hxx> #include <o3tl/any.hxx> +#include <svl/grabbagitem.hxx> #include <svl/style.hxx> #include <svl/itemset.hxx> @@ -95,6 +96,7 @@ static const SvxItemPropertySet* ImplGetSvxCellPropertySet() { u"LeftBorder", SDRATTR_TABLE_BORDER, cppu::UnoType<BorderLine>::get(), 0, LEFT_BORDER }, { u"RightBorder", SDRATTR_TABLE_BORDER, cppu::UnoType<BorderLine>::get(), 0, RIGHT_BORDER }, { u"RotateAngle", SDRATTR_TABLE_TEXT_ROTATION, cppu::UnoType<sal_Int32>::get(), 0, 0 }, + { u"CellInteropGrabBag", SDRATTR_TABLE_GRABBAG, cppu::UnoType<css::uno::Sequence<css::beans::PropertyValue>>::get(), 0, 0}, SVX_UNOEDIT_OUTLINER_PROPERTIES, SVX_UNOEDIT_CHAR_PROPERTIES, @@ -1102,6 +1104,14 @@ void SAL_CALL Cell::setPropertyValue( const OUString& rPropertyName, const Any& mpProperties->SetObjectItem(SvxTextRotateItem(Degree10(nRotVal/10), SDRATTR_TABLE_TEXT_ROTATION)); return; } + case SDRATTR_TABLE_GRABBAG: + { + if (mpGrabBagItem == nullptr) + mpGrabBagItem.reset(new SfxGrabBagItem); + + mpGrabBagItem->PutValue(rValue, 0); + return; + } default: { SfxItemSet aSet(GetObject().getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID); @@ -1222,6 +1232,17 @@ Any SAL_CALL Cell::getPropertyValue( const OUString& PropertyName ) const SvxTextRotateItem& rTextRotate = mpProperties->GetItem(SDRATTR_TABLE_TEXT_ROTATION); return Any(sal_Int32(to<Degree100>(rTextRotate.GetValue()))); } + case SDRATTR_TABLE_GRABBAG: + { + if (mpGrabBagItem != nullptr) + { + Any aGrabBagSequence; + mpGrabBagItem->QueryValue(aGrabBagSequence); + return aGrabBagSequence; + } + else + return Any{css::uno::Sequence<css::beans::PropertyValue>()}; + } default: { SfxItemSet aSet(GetObject().getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID);