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);

Reply via email to