chart2/qa/extras/chart2import2.cxx | 49 +++++++++++++++++++++ chart2/qa/extras/data/pptx/tdf136754.pptx |binary chart2/qa/extras/data/pptx/tdf60316.pptx |binary oox/source/drawingml/chart/objectformatter.cxx | 18 +++++-- oox/source/drawingml/chart/plotareacontext.cxx | 2 oox/source/drawingml/chart/plotareamodel.cxx | 3 - sw/qa/extras/layout/data/tdf166181.fodt | 58 +++++++++++++++++++++++++ sw/qa/extras/layout/layout5.cxx | 22 +++++++++ sw/source/core/layout/tabfrm.cxx | 12 +++-- 9 files changed, 152 insertions(+), 12 deletions(-)
New commits: commit 5e1037975edc4594b364f740df080603d3581946 Author: Markus Mohrhard <markus.mohrh...@googlemail.com> AuthorDate: Wed Jul 9 02:53:09 2025 +0200 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Jul 20 13:29:54 2025 +0200 tdf#136754: handle pptx chart backgrounds provided by the themes correctly It seems that there is a small undocumented quirk in the OOXML spec regarding pptx files. The first 32 themes are handled as if they would be specifying a transparent background whereas the spec seems to agree with the xlsx/docx handling of using a solid background based on the theme colors. This corresponds to table 3 in 21.2.3.46 ST_Style of the OOXML spec. This commit also reverts the fix for tdf#60316. Change-Id: I4187b5740898435941647056a5820fa47a2b3dba Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187759 Tested-by: Jenkins Reviewed-by: Markus Mohrhard <markus.mohrh...@googlemail.com> (cherry picked from commit 87350de8737ca91ba71b356ca9f33fea99e74591) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187844 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/chart2/qa/extras/chart2import2.cxx b/chart2/qa/extras/chart2import2.cxx index cdfe94093e4b..f8b17a4f9116 100644 --- a/chart2/qa/extras/chart2import2.cxx +++ b/chart2/qa/extras/chart2import2.cxx @@ -18,6 +18,7 @@ #include <com/sun/star/chart/XAxisXSupplier.hpp> #include <com/sun/star/chart/DataLabelPlacement.hpp> #include <com/sun/star/text/XText.hpp> +#include <com/sun/star/drawing/FillStyle.hpp> class Chart2ImportTest2 : public ChartTest { @@ -958,6 +959,54 @@ CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf166428) CPPUNIT_ASSERT(xDataSeq.is()); } +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf60316) +{ + loadFromFile(u"pptx/tdf60316.pptx"); + + // 1st chart + Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle + = xPropSet->getPropertyValue(u"FillStyle"_ustr).get<drawing::FillStyle>(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "'Automatic' chart background fill in pptx should be loaded as no fill (transparent).", + drawing::FillStyle_NONE, eStyle); + + Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram(); + Reference<beans::XPropertySet> xWallPropSet = xDiagram->getWall(); + + eStyle = xWallPropSet->getPropertyValue(u"FillStyle"_ustr).get<drawing::FillStyle>(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Wall background for styles below 32 shoujld be transparent in pptx", + drawing::FillStyle_NONE, eStyle); +} + +CPPUNIT_TEST_FIXTURE(Chart2ImportTest2, testTdf136754) +{ + loadFromFile(u"pptx/tdf136754.pptx"); + + // 1st chart + Reference<chart2::XChartDocument> xChartDoc(getChartDocFromDrawImpress(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xChartDoc.is()); + + Reference<beans::XPropertySet> xPropSet = xChartDoc->getPageBackground(); + CPPUNIT_ASSERT(xPropSet.is()); + drawing::FillStyle eStyle + = xPropSet->getPropertyValue(u"FillStyle"_ustr).get<drawing::FillStyle>(); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "'Automatic' chart background fill in pptx should be loaded as no fill (transparent).", + drawing::FillStyle_NONE, eStyle); + + Reference<chart2::XDiagram> xDiagram = xChartDoc->getFirstDiagram(); + Reference<beans::XPropertySet> xWallPropSet = xDiagram->getWall(); + eStyle = xWallPropSet->getPropertyValue(u"FillStyle"_ustr).get<drawing::FillStyle>(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Wall background for styles above 32 should be solid in pptx", + drawing::FillStyle_SOLID, eStyle); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/chart2/qa/extras/data/pptx/tdf136754.pptx b/chart2/qa/extras/data/pptx/tdf136754.pptx new file mode 100644 index 000000000000..48927e54eba7 Binary files /dev/null and b/chart2/qa/extras/data/pptx/tdf136754.pptx differ diff --git a/chart2/qa/extras/data/pptx/tdf60316.pptx b/chart2/qa/extras/data/pptx/tdf60316.pptx index d1da03e5fa46..638d7e371b39 100644 Binary files a/chart2/qa/extras/data/pptx/tdf60316.pptx and b/chart2/qa/extras/data/pptx/tdf60316.pptx differ diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx index 0d746ab783f8..698da92fe8bf 100644 --- a/oox/source/drawingml/chart/objectformatter.cxx +++ b/oox/source/drawingml/chart/objectformatter.cxx @@ -636,6 +636,8 @@ public: const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ); + void setAutoFill(sal_Int32 nAutoFill); + private: FillPropertiesPtr mxAutoFill; /// Automatic fill properties. }; @@ -871,11 +873,6 @@ FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* if( const Theme* pTheme = mrData.mrFilter.getCurrentTheme() ) if( const FillProperties* pFillProps = pTheme->getFillStyle( pAutoFormatEntry->mnThemedIdx ) ) *mxAutoFill = *pFillProps; - - if (eObjType == OBJECTTYPE_CHARTSPACE) - { - mxAutoFill->moFillType = rData.mrFilter.getGraphicHelper().getDefaultChartAreaFillStyle(); - } } void FillFormatter::convertFormatting( ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) @@ -890,6 +887,11 @@ void FillFormatter::convertFormatting( ShapePropertyMap& rPropMap, const ModelRe aFillProps.pushToPropMap( rPropMap, mrData.mrFilter.getGraphicHelper(), 0, getPhColor( nSeriesIdx ) ); } +void FillFormatter::setAutoFill(sal_Int32 nFillStyle) +{ + mxAutoFill->moFillType = nFillStyle; +} + namespace { const TextCharacterProperties* lclGetTextProperties( const ModelRef< TextBody >& rxTextProp ) @@ -948,6 +950,12 @@ ObjectTypeFormatter::ObjectTypeFormatter( ObjectFormatterData& rData, const Obje mrModelObjHelper( rData.maModelObjHelper ), mrEntry( rEntry ) { + // this seems to be an undocumented quirk in the OOXML spec. Only for pptx files the first 32 theme entries + // force a transparent background + if (rChartSpace.mnStyle <= 32 && (eObjType == OBJECTTYPE_CHARTSPACE || eObjType == OBJECTTYPE_PLOTAREA2D)) + { + maFillFormatter.setAutoFill(rData.mrFilter.getGraphicHelper().getDefaultChartAreaFillStyle()); + } } void ObjectTypeFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) diff --git a/oox/source/drawingml/chart/plotareacontext.cxx b/oox/source/drawingml/chart/plotareacontext.cxx index 00a6a47bde3b..731c23368933 100644 --- a/oox/source/drawingml/chart/plotareacontext.cxx +++ b/oox/source/drawingml/chart/plotareacontext.cxx @@ -162,7 +162,7 @@ ContextHandlerRef PlotAreaContext::onCreateContext( sal_Int32 nElement, [[maybe_ case C_TOKEN( layout ): return new LayoutContext( *this, mrModel.mxLayout.create() ); case C_TOKEN( spPr ): - return new ShapePropertiesContext( *this, mrModel.mxShapeProp.getOrCreate() ); + return new ShapePropertiesContext( *this, mrModel.mxShapeProp.create() ); case C_TOKEN(dTable): return new DataTableContext( *this, mrModel.mxDataTable.create() ); } diff --git a/oox/source/drawingml/chart/plotareamodel.cxx b/oox/source/drawingml/chart/plotareamodel.cxx index cb4f6383ddfa..cdc3af7f8fef 100644 --- a/oox/source/drawingml/chart/plotareamodel.cxx +++ b/oox/source/drawingml/chart/plotareamodel.cxx @@ -18,8 +18,6 @@ */ #include <drawingml/chart/plotareamodel.hxx> -#include <drawingml/fillproperties.hxx> -#include <oox/token/tokens.hxx> namespace oox::drawingml::chart { @@ -40,7 +38,6 @@ WallFloorModel::~WallFloorModel() PlotAreaModel::PlotAreaModel() { - mxShapeProp.create().getFillProperties().moFillType = XML_noFill; } PlotAreaModel::~PlotAreaModel() commit 619265ffb4da3ae67578b9ea9db3cfa5170fdbc4 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Jul 13 22:38:40 2025 +0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Sun Jul 20 13:29:41 2025 +0200 tdf#166181: partial revert of 223a51801f0b75ae5036a8bcecc6eb81d99b113e A newly created follow row frame for a split row would be passed into lcl_GetHeightOfRows with Y position of 0, while the next row frames would have Y positions from their previous placement (below the last row frame kept on the previous page). Thus we can't use a difference between top ot first row and bottom of last row to get sum of heights. Change-Id: Ia96cd3ec488a6c3e6fb768fb1346bc8d61696118 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187818 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins (cherry picked from commit 6a074bd78322d8a8ca3eddd5ea4d4edf8f796a80) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187857 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/extras/layout/data/tdf166181.fodt b/sw/qa/extras/layout/data/tdf166181.fodt new file mode 100644 index 000000000000..2da431f4918f --- /dev/null +++ b/sw/qa/extras/layout/data/tdf166181.fodt @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + </office:styles> + <office:automatic-styles> + <style:style style:name="Table1" style:family="table"> + <style:table-properties style:width="170mm" table:align="margins"/> + </style:style> + <style:style style:name="Table1.1" style:family="table-row"> + <style:table-row-properties style:min-row-height="248mm"/> + </style:style> + <style:style style:name="Table1.A1" style:family="table-cell"> + <style:table-cell-properties fo:padding="1mm" fo:border="0.5pt solid #000000"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm"/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text> + <table:table table:name="Table1" table:style-name="Table1"> + <table:table-column/> + <table:table-column/> + <table:table-row table:style-name="Table1.1"> + <table:table-cell table:style-name="Table1.A1" table:number-columns-spanned="2" office:value-type="string"> + <text:p>A1</text:p> + </table:table-cell> + <table:covered-table-cell/> + </table:table-row> + <table:table-row> + <table:table-cell table:style-name="Table1.A1" table:number-rows-spanned="2" office:value-type="string"> + <text:p>A2 (merged cell)</text:p> + </table:table-cell> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>B2</text:p> + </table:table-cell> + </table:table-row> + <table:table-row> + <table:covered-table-cell table:style-name="Table1.A1"/> + <table:table-cell table:style-name="Table1.A1" office:value-type="string"> + <text:p>B3</text:p> + </table:table-cell> + </table:table-row> + </table:table> + <text:p/> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/layout5.cxx b/sw/qa/extras/layout/layout5.cxx index 21c022b10b16..1b6addbfd638 100644 --- a/sw/qa/extras/layout/layout5.cxx +++ b/sw/qa/extras/layout/layout5.cxx @@ -1934,6 +1934,28 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf167540) verify_me(); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf166181) +{ + // Given a document with a table with a merged cell, which gets split across pages: + createSwDoc("tdf166181.fodt"); + CPPUNIT_ASSERT_EQUAL(2, getPages()); + + // Make sure that the follow cell has the correct height + auto pXmlDoc = parseLayoutDump(); + assertXPath(pXmlDoc, "//page", 2); + assertXPath(pXmlDoc, "//page[2]/body/tab", 1); + assertXPath(pXmlDoc, "//page[2]/body/tab/row", 2); + assertXPath(pXmlDoc, "//page[2]/body/tab/row[1]/infos/bounds", "height", u"0"); + // Check that the first cell of the row is a follow (it has a precede) + (void)getXPath(pXmlDoc, "//page[2]/body/tab/row[1]/cell[1]", "precede"); + // Check that it is merged + assertXPath(pXmlDoc, "//page[2]/body/tab/row[1]/cell[1]", "rowspan", u"2"); + // Get cell height + OUString height = getXPath(pXmlDoc, "//page[2]/body/tab/row[1]/cell[1]/infos/bounds", "height"); + // Without a fix, this was greater than 16000; it is expected around 400 + CPPUNIT_ASSERT_LESS(sal_Int32(500), height.toInt32()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 5163661fd3bb..2610815ca2a4 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -225,15 +225,21 @@ static SwTwips lcl_GetHeightOfRows( const SwFrame* pStart, tools::Long nCount ) if ( !nCount || !pStart) return 0; + // There are moments when some rows have correct size, but wrong position: e.g., when a merged + // cell is split, the 0-height follow of the previous row is inserted, and arrives here with a + // correct height, but positioned at [0, 0]; the following rows have correct position (offset + // to the new page's starting Y coordinate). This disallows to simplify the height calculation + // to just difference between top row's top and bottom row's bottom. + SwTwips nRet = 0; SwRectFnSet aRectFnSet(pStart); - SwTwips nTop = aRectFnSet.GetTop(pStart->getFrameArea()); - while (pStart->GetNext() && nCount > 1) + while (pStart && nCount > 0) { + nRet += aRectFnSet.GetHeight(pStart->getFrameArea()); pStart = pStart->GetNext(); --nCount; } - return -aRectFnSet.BottomDist(pStart->getFrameArea(), nTop); + return nRet; } // Local helper function to insert a new follow flow line