sw/qa/extras/rtfexport/data/tdf121493.rtf | 21 +++++ sw/qa/extras/rtfexport/rtfexport8.cxx | 46 ++++++++++++ sw/source/writerfilter/rtftok/rtfdispatchvalue.cxx | 79 +++++++++++++-------- 3 files changed, 118 insertions(+), 28 deletions(-)
New commits: commit a06689b1711e1f200afd4a4492341f337ba99082 Author: Mike Kaganski <[email protected]> AuthorDate: Sun Jun 22 02:49:05 2025 +0500 Commit: Mike Kaganski <[email protected]> CommitDate: Sun Jun 22 09:11:31 2025 +0200 tdf#121493: handle rleftN after I took an easy path, and just fixed the possible pre-existing value when rleftN is handled. But the proper fix would be to avoid the cell widths calculations altogether, until ow is handled. At that point, all information is already gathered. Search for the first instance of LN_CT_TblGridBase_gridCol, that is not -1 (the special value inserted in RTFDocumentImpl::resetTableRowProperties, and used in DomainMapperTableManager::sprm); and if found, correct it by the calculated TRLeft value. When there was no previous Change-Id: Ie6cf64d594e166abb1ed3e939207101d96f75c63 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186790 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/sw/qa/extras/rtfexport/data/tdf121493.rtf b/sw/qa/extras/rtfexport/data/tdf121493.rtf new file mode 100644 index 000000000000..79f115430deb --- /dev/null +++ b/sw/qa/extras/rtfexport/data/tdf121493.rtf @@ -0,0 +1,21 @@ +{ tf1 +{ rowd+aaa ++bbb ++ ow} +\par +{ rowd rleft1000+aaa ++bbb ++ ow} +\par +{ rowd rleft0+aaa ++bbb ++ ow}} \ No newline at end of file diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx b/sw/qa/extras/rtfexport/rtfexport8.cxx index f255fbde2a20..5675cf61910b 100644 --- a/sw/qa/extras/rtfexport/rtfexport8.cxx +++ b/sw/qa/extras/rtfexport/rtfexport8.cxx @@ -12,6 +12,7 @@ #include <com/sun/star/awt/FontWeight.hpp> #include <com/sun/star/awt/Gradient2.hpp> #include <com/sun/star/drawing/FillStyle.hpp> +#include <com/sun/star/table/XTableColumns.hpp> #include <com/sun/star/text/GraphicCrop.hpp> #include <com/sun/star/text/XFootnote.hpp> #include <com/sun/star/text/XFootnotesSupplier.hpp> @@ -749,6 +750,51 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf155835) } } +CPPUNIT_TEST_FIXTURE(Test, testTdf121493) +{ + // Given a document with three tables, having different order of a row's cellxN and trleftN: + createSwDoc("tdf121493.rtf"); + { + xmlDocUniquePtr pLayout = parseLayoutDump(); + // 1st table, having + assertXPath(pLayout, "//tab[1]['pass 1']/infos/prtBounds", "left", u"1000"); + assertXPath(pLayout, "//tab[1]['pass 1']/row/cell[1]/infos/bounds", "width", u"7000"); + assertXPath(pLayout, "//tab[1]['pass 1']/row/cell[2]/infos/bounds", "width", u"1000"); + // 2nd table, having rleft1000+ assertXPath(pLayout, "//tab[2]['pass 1']/infos/prtBounds", "left", u"1000"); + assertXPath(pLayout, "//tab[2]['pass 1']/row/cell[1]/infos/bounds", "width", u"7000"); + assertXPath(pLayout, "//tab[2]['pass 1']/row/cell[2]/infos/bounds", "width", u"1000"); + // 3rd table, having rleft0+ assertXPath(pLayout, "//tab[3]['pass 1']/infos/prtBounds", "left", u"0"); + assertXPath(pLayout, "//tab[3]['pass 1']/row/cell[1]/infos/bounds", "width", u"8000"); + assertXPath(pLayout, "//tab[3]['pass 1']/row/cell[2]/infos/bounds", "width", u"1000"); + } + // Check export, too + saveAndReload(mpFilter); + { + xmlDocUniquePtr pLayout = parseLayoutDump(); + // Rounding (or maybe off-by-one?) errors sadly hit the test + // 1st table + assertXPath(pLayout, "//tab[1]['pass 2']/infos/prtBounds", "left", u"1000"); + OUString width = getXPath(pLayout, "//tab[1]['pass 2']/row/cell[1]/infos/bounds", "width"); + CPPUNIT_ASSERT_DOUBLES_EQUAL(7000, width.toInt32(), 1); + width = getXPath(pLayout, "//tab[1]['pass 2']/row/cell[2]/infos/bounds", "width"); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1000, width.toInt32(), 1); + // 2nd table + assertXPath(pLayout, "//tab[2]['pass 2']/infos/prtBounds", "left", u"1000"); + width = getXPath(pLayout, "//tab[2]['pass 2']/row/cell[1]/infos/bounds", "width"); + CPPUNIT_ASSERT_DOUBLES_EQUAL(7000, width.toInt32(), 1); + width = getXPath(pLayout, "//tab[2]['pass 2']/row/cell[2]/infos/bounds", "width"); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1000, width.toInt32(), 1); + // 3rd table + assertXPath(pLayout, "//tab[3]['pass 2']/infos/prtBounds", "left", u"0"); + width = getXPath(pLayout, "//tab[3]['pass 2']/row/cell[1]/infos/bounds", "width"); + CPPUNIT_ASSERT_DOUBLES_EQUAL(8000, width.toInt32(), 1); + width = getXPath(pLayout, "//tab[3]['pass 2']/row/cell[2]/infos/bounds", "width"); + CPPUNIT_ASSERT_DOUBLES_EQUAL(1000, width.toInt32(), 1); + } +} + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/writerfilter/rtftok/rtfdispatchvalue.cxx b/sw/source/writerfilter/rtftok/rtfdispatchvalue.cxx index d89c3420017a..a5999fbcde25 100644 --- a/sw/source/writerfilter/rtftok/rtfdispatchvalue.cxx +++ b/sw/source/writerfilter/rtftok/rtfdispatchvalue.cxx @@ -386,6 +386,32 @@ bool RTFDocumentImpl::dispatchFrameValue(RTFKeyword nKeyword, int nParam) return false; } +static int GetCellWidth(int thisCellX, int prevCellX, RTFSprms& tableRowSprms) +{ + thisCellX -= prevCellX; + if (thisCellX == 0 && prevCellX > 0) + { + // If width of cell is 0, BUT there is a value for + // possible width. But if + // try to resolve this. + + // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells. + const int COL_DFLT_WIDTH = 41; + thisCellX = COL_DFLT_WIDTH; + } + // If there is a negative left margin, then the first cellx is relative to that. + if (prevCellX == 0) + { + if (RTFValue::Pointer_t pTblInd = tableRowSprms.find(NS_ooxml::LN_CT_TblPrBase_tblInd)) + { + RTFValue::Pointer_t pWidth = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w); + if (pWidth && pWidth->getInt() < 0) + thisCellX = -1 * (pWidth->getInt() - prevCellX); + } + } + return thisCellX; +} + bool RTFDocumentImpl::dispatchTableValue(RTFKeyword nKeyword, int nParam) { int nSprm = 0; @@ -399,30 +425,7 @@ bool RTFDocumentImpl::dispatchTableValue(RTFKeyword nKeyword, int nParam) (Destination::NESTEDTABLEPROPERTIES == m_aStates.top().getDestination()) ? m_nNestedCurrentCellX : m_nTopLevelCurrentCellX); - int nCellX = nParam - rCurrentCellX; - - if (!nCellX && nParam > 0) - { - // If width of cell is 0, BUT there is a value for - // possible width. But if - // try to resolve this. - - // sw/source/filter/inc/wrtswtbl.hxx, minimal possible width of cells. - const int COL_DFLT_WIDTH = 41; - nCellX = COL_DFLT_WIDTH; - } - - // If there is a negative left margin, then the first cellx is relative to that. - RTFValue::Pointer_t pTblInd - = m_aStates.top().getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblInd); - if (rCurrentCellX == 0 && pTblInd) - { - RTFValue::Pointer_t pWidth - = pTblInd->getAttributes().find(NS_ooxml::LN_CT_TblWidth_w); - if (pWidth && pWidth->getInt() < 0) - nCellX = -1 * (pWidth->getInt() - nParam); - } - + int nCellX = GetCellWidth(nParam, rCurrentCellX, m_aStates.top().getTableRowSprms()); rCurrentCellX = nParam; auto pXValue = new RTFValue(nCellX); m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue, @@ -512,11 +515,31 @@ bool RTFDocumentImpl::dispatchTableValue(RTFKeyword nKeyword, int nParam) .find(NS_ooxml::LN_CT_TblWidth_w) ->getInt(); } - rCurrentTRLeft = nParam; } - else - rCurrentTRLeft = rCurrentCellX = nParam; - + rCurrentTRLeft = nParam; + // Correct the first cellX, if already pushed before these. + // FIXME: this whole convoluted processing of CELLX, TRLEFT, TBLIND should be replaced + // with simple pushing of the respective values as is; and all that should eventually + // be processed in RTFKeyword::ROW handler (RTFDocumentImpl::dispatchSymbol), where all + // information would already be available. There we could know the table indent, row + // left offset, all right cell boundaries; and could calculate correct widths (likely + // in prepareProperties call). + bool hadCellX = false; + for (auto & [ id, pValue ] : m_aStates.top().getTableRowSprms()) + { + if (id == NS_ooxml::LN_CT_TblGridBase_gridCol) + { + if (int val = pValue->getInt(); val != -1) + { + val = GetCellWidth(val, nParam, m_aStates.top().getTableRowSprms()); + pValue = new RTFValue(val); + hadCellX = true; + break; + } + } + } + if (!hadCellX) + rCurrentCellX = rCurrentTRLeft; putNestedAttribute(m_aStates.top().getTableRowSprms(), NS_ooxml::LN_CT_TblPrBase_tblInd, +NS_ooxml::LN_CT_TblWidth_w, new RTFValue(nParam)); return true;
