sw/qa/extras/ww8export/data/tdf91632_layoutInCellD.doc |binary sw/qa/extras/ww8export/ww8export4.cxx | 65 +++++++++++++++++ sw/source/filter/ww8/ww8graf.cxx | 20 ++++- 3 files changed, 82 insertions(+), 3 deletions(-)
New commits: commit 183f4e8f1b8dc405e3febd2f0a82769403730a4d Author: Justin Luth <jl...@mail.com> AuthorDate: Fri Aug 9 12:45:33 2024 -0400 Commit: Justin Luth <jl...@mail.com> CommitDate: Sat Aug 10 00:20:44 2024 +0200 tdf#91632 doc import layoutInCell: vert page->margin, *->top The same thing was done early in this series of patches for DOCX Microsoft's layoutInCell is very buggy for vertical orientation. So, instead of making our own implementation just as buggy, instead, alter the document so that the settings match the implementation. That way if MSO ever decides to re-fix layoutInCell, we are in a position to easily avoid the mapping to accommodate a new compat version. make CppunitTest_sw_ww8export4 \ CPPUNIT_TEST_NAME=testTdf91632_layoutInCellD Change-Id: I1a8ad18872ba7c0f08cc5dff517be6e6079e8b11 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171705 Tested-by: Jenkins Reviewed-by: Justin Luth <jl...@mail.com> diff --git a/sw/qa/extras/ww8export/data/tdf91632_layoutInCellD.doc b/sw/qa/extras/ww8export/data/tdf91632_layoutInCellD.doc new file mode 100644 index 000000000000..106d172c38f4 Binary files /dev/null and b/sw/qa/extras/ww8export/data/tdf91632_layoutInCellD.doc differ diff --git a/sw/qa/extras/ww8export/ww8export4.cxx b/sw/qa/extras/ww8export/ww8export4.cxx index 798e3e52da75..507f51c874a9 100644 --- a/sw/qa/extras/ww8export/ww8export4.cxx +++ b/sw/qa/extras/ww8export/ww8export4.cxx @@ -125,6 +125,71 @@ DECLARE_WW8EXPORT_TEST(testTdf141649_conditionalText, "tdf141649_conditionalText getParagraph(1, u"trueResult"_ustr); } +DECLARE_WW8EXPORT_TEST(testTdf91632_layoutInCellD, "tdf91632_layoutInCellD.doc") +{ + // given a table with two layoutInCell images, and cell A1 has 1/2 inch border padding (margin) + // - A1 contains an image, vertically aligned to the outside of the page (aka cell) + // - B1 contains an image, vertically aligned from top of the page (aka cell) + + // In Microsoft's layoutInCell implementation, vertical "page" is identical to "margin", + // and everything (including center/bottom) actually is oriented to the top of the margin. + + xmlDocUniquePtr pDump = parseLayoutDump(); + // Cell A1 + sal_Int32 nShapeTop + = getXPath(pDump, "//tab/row[1]/cell[1]/txt[1]/anchored/fly/SwAnchoredObject/bounds"_ostr, + "top"_ostr) + .toInt32(); + sal_Int32 nShapeBottom + = getXPath(pDump, "//tab/row[1]/cell[1]/txt[1]/anchored/fly/SwAnchoredObject/bounds"_ostr, + "bottom"_ostr) + .toInt32(); + // use paragraph 1 to indicate where the cell spacing/padding ends, and the text starts. + sal_Int32 nPara1Top + = getXPath(pDump, "//tab/row[1]/cell[1]/txt[1]/infos/bounds"_ostr, "top"_ostr).toInt32(); + // use paragraph 5 to prove the image is not at the bottom. + CPPUNIT_ASSERT_EQUAL(OUString("Below logo"), + getXPathContent(pDump, "//tab/row[1]/cell[1]/txt[5]"_ostr)); + sal_Int32 nPara5Top + = getXPath(pDump, "//tab/row[1]/cell[1]/txt[5]/infos/bounds"_ostr, "top"_ostr).toInt32(); + CPPUNIT_ASSERT_EQUAL(nShapeTop, nPara1Top); + CPPUNIT_ASSERT(nPara5Top > nShapeBottom); // ShapeBottom is higher than Para5Top + + // In the file it is specified as "page" (PAGE_FRAME), but implemented as if it were "margin" + // so on import we intentionally changed it to match the closest setting to the implementation. + const auto& xShape = getShape(1); + CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_PRINT_AREA, + getProperty<sal_Int16>(xShape, u"VertOrientRelation"_ustr)); + + CPPUNIT_ASSERT(getProperty<bool>(xShape, u"IsFollowingTextFlow"_ustr)); + + // Cell B1 + nShapeTop + = getXPath(pDump, "//tab/row[1]/cell[2]/txt[1]/anchored/fly/SwAnchoredObject/bounds"_ostr, + "top"_ostr) + .toInt32(); + nShapeBottom + = getXPath(pDump, "//tab/row[1]/cell[2]/txt[1]/anchored/fly/SwAnchoredObject/bounds"_ostr, + "bottom"_ostr) + .toInt32(); + // use paragraph 1 to indicate where the cell spacing/padding ends, and the text starts. + nPara1Top + = getXPath(pDump, "//tab/row[1]/cell[2]/txt[1]/infos/bounds"_ostr, "top"_ostr).toInt32(); + // use paragraph 5 to prove the image is not at the bottom. + CPPUNIT_ASSERT_EQUAL(OUString("Below image"), + getXPathContent(pDump, "//tab/row[1]/cell[2]/txt[5]"_ostr)); + nPara5Top + = getXPath(pDump, "//tab[1]/row/cell[2]/txt[5]/infos/bounds"_ostr, "top"_ostr).toInt32(); + CPPUNIT_ASSERT_EQUAL(nShapeTop, nPara1Top); + CPPUNIT_ASSERT(nPara5Top > nShapeBottom); // ShapeBottom is higher than Para5Top + + const auto& xShape2 = getShape(2); + CPPUNIT_ASSERT_EQUAL(css::text::RelOrientation::PAGE_PRINT_AREA, + getProperty<sal_Int16>(xShape2, u"VertOrientRelation"_ustr)); + + CPPUNIT_ASSERT(getProperty<bool>(xShape2, u"IsFollowingTextFlow"_ustr)); +} + CPPUNIT_TEST_FIXTURE(Test, testEndnotesAtSectEndDOC) { // Given a document, endnotes at collected at section end: diff --git a/sw/source/filter/ww8/ww8graf.cxx b/sw/source/filter/ww8/ww8graf.cxx index 71906dea342e..8e520c8a5ea1 100644 --- a/sw/source/filter/ww8/ww8graf.cxx +++ b/sw/source/filter/ww8/ww8graf.cxx @@ -2466,10 +2466,11 @@ RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec& rRecord, WW8_FS // at frame|character and has wrap through, but its attribute // 'layout in table cell' isn't set, convert its horizontal alignment to page text area. // #i84783# - use new method <IsObjectLayoutInTableCell()> - if (m_nInTable && + const bool bIsObjectLayoutInTableCell + = m_nInTable && IsObjectLayoutInTableCell(rRecord.nGroupShapeBooleanProperties); + if (!bIsObjectLayoutInTableCell && m_nInTable && (eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR) && - rFSPA.nwr == 3 && - !IsObjectLayoutInTableCell(rRecord.nGroupShapeBooleanProperties)) + rFSPA.nwr == 3) { eHoriRel = text::RelOrientation::PAGE_PRINT_AREA; } @@ -2497,6 +2498,19 @@ RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec& rRecord, WW8_FS eVertOri = aVertOriTab[ nYAlign ]; } + if (bIsObjectLayoutInTableCell && eAnchor == RndStdIds::FLY_AT_CHAR) + { + // Microsoft is buggy and inconsistent in how they handle layoutInCell. + // Map wrongly-implemented settings to the closest implemented setting + + // "page" is implemented as if it was "margin" - to cell spacing, not edge + if (eVertRel == text::RelOrientation::PAGE_FRAME) + eVertRel = text::RelOrientation::PAGE_PRINT_AREA; + // only "from top" and "top" are appropriate. Others are implemented as Top + if (eVertOri != text::VertOrientation::NONE) + eVertOri = text::VertOrientation::TOP; + } + // Below line in word is a positive value, while in writer its // negative tools::Long nYPos = rFSPA.nYaTop;