sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 139 ++++++---- sw/qa/extras/ooxmlexport/ooxmlexport12.cxx | 368 +++++++++++++++-------------- sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 90 +++---- sw/qa/extras/ooxmlexport/ooxmlexport17.cxx | 108 ++++---- sw/qa/extras/ooxmlexport/ooxmlexport18.cxx | 333 ++++++++++++++------------ sw/qa/extras/ooxmlexport/ooxmlexport2.cxx | 164 ++++++------ sw/qa/extras/ooxmlexport/ooxmlexport3.cxx | 33 +- sw/qa/extras/ooxmlexport/ooxmlexport4.cxx | 80 +++--- sw/qa/extras/ooxmlexport/ooxmlexport5.cxx | 76 +++-- sw/qa/extras/ooxmlexport/ooxmlexport6.cxx | 134 +++++----- sw/qa/extras/ooxmlexport/ooxmlexport8.cxx | 82 +++--- 11 files changed, 879 insertions(+), 728 deletions(-)
New commits: commit 740c030e302cba0ee29ef8aa4288626cc5b4e3f7 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Wed Oct 16 12:57:58 2024 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Wed Oct 16 14:19:19 2024 +0200 ooxmlexport: drop isExported (part 1) Change-Id: I2c40a9290c89e4fd4da18de9f3cb2d735182bdf8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/175012 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Tested-by: Jenkins diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 7f15c33de51d..64901fcf7359 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -175,55 +175,63 @@ CPPUNIT_TEST_FIXTURE(Test, testEmptyAnnotationMark) assertXPath(pXmlDoc, "//w:commentRangeEnd", 0); } -DECLARE_OOXMLEXPORT_TEST(testDropdownInCell, "dropdown-in-cell.docx") +CPPUNIT_TEST_FIXTURE(Test, testDropdownInCell) { - // First problem: table was missing from the document, this was 0. - uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); + auto verify = [this](bool bIsExport = false) { + // First problem: table was missing from the document, this was 0. + uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); - // Second problem: dropdown shape wasn't anchored inside the B1 cell. - if (getShapes() > 0) - { - uno::Reference<text::XTextContent> xShape(getShape(1), uno::UNO_QUERY); - uno::Reference<text::XTextRange> xAnchor = xShape->getAnchor(); - uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY); - uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xCell, uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int16(0), xTextRangeCompare->compareRegionStarts(xAnchor, xCell)); - } - else if (!isExported()) - { - // ComboBox was imported as DropDown text field - uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); - uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); - CPPUNIT_ASSERT(xFields->hasMoreElements()); - uno::Any aField = xFields->nextElement(); - uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY); - CPPUNIT_ASSERT(xServiceInfo->supportsService(u"com.sun.star.text.textfield.DropDown"_ustr)); - } - else - { - // DropDown text field is exported as inline SDT, we import that back here. - uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); - uno::Reference<table::XCell> xCell = xTable->getCellByName(u"B1"_ustr); - uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, uno::UNO_QUERY); - uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration(); - uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(), - uno::UNO_QUERY); - uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration(); - uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY); - OUString aPortionType; - xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType; - CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType); - uno::Reference<text::XTextContent> xContentControl; - xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl; - uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); - uno::Sequence<beans::PropertyValues> aListItems; - xContentControlProps->getPropertyValue(u"ListItems"_ustr) >>= aListItems; - CPPUNIT_ASSERT(aListItems.hasElements()); - } + // Second problem: dropdown shape wasn't anchored inside the B1 cell. + if (getShapes() > 0) + { + uno::Reference<text::XTextContent> xShape(getShape(1), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xAnchor = xShape->getAnchor(); + uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY); + uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xCell, uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int16(0), xTextRangeCompare->compareRegionStarts(xAnchor, xCell)); + } + + if (!bIsExport) + { + // ComboBox was imported as DropDown text field + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); + CPPUNIT_ASSERT(xFields->hasMoreElements()); + uno::Any aField = xFields->nextElement(); + uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY); + CPPUNIT_ASSERT(xServiceInfo->supportsService(u"com.sun.star.text.textfield.DropDown"_ustr)); + } + else + { + // DropDown text field is exported as inline SDT, we import that back here. + uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<table::XCell> xCell = xTable->getCellByName(u"B1"_ustr); + uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration(); + uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY); + OUString aPortionType; + xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType; + CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType); + uno::Reference<text::XTextContent> xContentControl; + xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl; + uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValues> aListItems; + xContentControlProps->getPropertyValue(u"ListItems"_ustr) >>= aListItems; + CPPUNIT_ASSERT(aListItems.hasElements()); + } + }; + + createSwDoc("dropdown-in-cell.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } DECLARE_OOXMLEXPORT_TEST(testTableAlignment, "table-alignment.docx") @@ -254,17 +262,20 @@ CPPUNIT_TEST_FIXTURE(Test, testSdtRunPicture) assertXPath(pXmlDoc, "//w:body/w:p/w:sdt", 1); } -DECLARE_OOXMLEXPORT_TEST(testChartDupe, "chart-dupe.docx") +CPPUNIT_TEST_FIXTURE(Test, testChartDupe) { - // Single chart was exported back as two charts. - uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xEmbeddedObjects(xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY); - // This was 2, on second import we got a duplicated chart copy. - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xEmbeddedObjects->getCount()); - + auto verify = [this]() { + // Single chart was exported back as two charts. + uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xEmbeddedObjects(xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY); + // This was 2, on second import we got a duplicated chart copy. + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xEmbeddedObjects->getCount()); + }; - if (!isExported()) - return; // initial import + createSwDoc("chart-dupe.docx"); + verify(); + saveAndReload(mpFilter); + verify(); xmlDocUniquePtr pXmlDocCT = parseExport(u"[Content_Types].xml"_ustr); @@ -786,17 +797,21 @@ DECLARE_OOXMLEXPORT_TEST(testTdf97090, "tdf97090.docx") CPPUNIT_ASSERT_EQUAL(COL_WHITE, getProperty<Color>(paragraphProperties, u"FillColor"_ustr)); } -DECLARE_OOXMLEXPORT_TEST(testTdf89791, "tdf89791.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf89791) { - if (isExported()) - { - uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); - CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName(u"docProps/custom.xml"_ustr))); - } + createSwDoc("tdf89791.docx"); //tdf#102619 - setting FollowStyle with a not-yet-created style was failing. (Titre is created before Corps de texte). uno::Reference< beans::XPropertySet > properties(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Titre"_ustr), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(u"Corps de texte"_ustr, getProperty<OUString>(properties, u"FollowStyle"_ustr)); + + saveAndReload(mpFilter); + + properties.set(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Titre"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"Corps de texte"_ustr, getProperty<OUString>(properties, u"FollowStyle"_ustr)); + + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL()); + CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName(u"docProps/custom.xml"_ustr))); } DECLARE_OOXMLEXPORT_TEST(testTdf91261, "tdf91261.docx") diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx index 53a6ef85844f..eac7320aa568 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx @@ -668,58 +668,65 @@ CPPUNIT_TEST_FIXTURE(Test, testObjectCrossReference) CPPUNIT_ASSERT_EQUAL(sal_uInt16(21), nIndex); } -DECLARE_OOXMLEXPORT_TEST(testTdf112202, "090716_Studentische_Arbeit_VWS.docx") -{ - xmlDocUniquePtr pXmlDoc = parseLayoutDump(); - - // page 1 header: 1 paragraph, 2 flys, 1 draw object - assertXPath(pXmlDoc, "/root/page[1]/header/txt", 1); - assertXPath(pXmlDoc, "/root/page[1]/header/txt/anchored/fly", 2); - if (isExported()) // somehow there's an additional shape on re-import? - assertXPath(pXmlDoc, "/root/page[1]/header/txt/anchored/SwAnchoredDrawObject", 2); - else - assertXPath(pXmlDoc, "/root/page[1]/header/txt/anchored/SwAnchoredDrawObject", 1); - - // page 2 header: 3 paragraphs, 1 table, 1 fly on last paragraph - assertXPath(pXmlDoc, "/root/page[2]/header/txt", 3); - assertXPath(pXmlDoc, "/root/page[2]/header/tab", 1); - assertXPath(pXmlDoc, "/root/page[2]/header/txt/anchored/fly", 1); - - // page 3 header: 1 table, 1 paragraph, no text - assertXPath(pXmlDoc, "/root/page[3]/header/txt", 1); - assertXPath(pXmlDoc, "/root/page[3]/header/tab", 1); - assertXPath(pXmlDoc, - "/root/page[3]/header/tab/row/cell/txt/SwParaPortion/SwLineLayout/child::*", 0); - assertXPath(pXmlDoc, "/root/page[3]/header//anchored", 0); - // tdf#149313: ensure 3rd page does not have extra empty paragraph at top - assertXPathContent(pXmlDoc, "/root/page[3]/body//txt", u"AUFGABENSTELLUNG"); - - // page 4 header: 1 table, 1 paragraph, with text - assertXPath(pXmlDoc, "/root/page[4]/header/txt", 1); - assertXPath(pXmlDoc, "/root/page[4]/header/tab", 1); - assertXPath( - pXmlDoc, - "/root/page[4]/header/tab/row[1]/cell[1]/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"Titel der studentischen Arbeit"); - assertXPath(pXmlDoc, "/root/page[4]/header//anchored", 0); - - // page 5: same as page 4 - assertXPath(pXmlDoc, "/root/page[5]/header/txt", 1); - assertXPath(pXmlDoc, "/root/page[5]/header/tab", 1); - assertXPath( - pXmlDoc, - "/root/page[5]/header/tab/row[1]/cell[1]/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"Titel der studentischen Arbeit"); - assertXPath(pXmlDoc, "/root/page[5]/header//anchored", 0); +CPPUNIT_TEST_FIXTURE(Test, testTd112202) +{ + auto verify = [this](bool bIsExport = false) { + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + + // page 1 header: 1 paragraph, 2 flys, 1 draw object + assertXPath(pXmlDoc, "/root/page[1]/header/txt", 1); + assertXPath(pXmlDoc, "/root/page[1]/header/txt/anchored/fly", 2); + if (bIsExport) // somehow there's an additional shape on re-import? + assertXPath(pXmlDoc, "/root/page[1]/header/txt/anchored/SwAnchoredDrawObject", 2); + else + assertXPath(pXmlDoc, "/root/page[1]/header/txt/anchored/SwAnchoredDrawObject", 1); + + // page 2 header: 3 paragraphs, 1 table, 1 fly on last paragraph + assertXPath(pXmlDoc, "/root/page[2]/header/txt", 3); + assertXPath(pXmlDoc, "/root/page[2]/header/tab", 1); + assertXPath(pXmlDoc, "/root/page[2]/header/txt/anchored/fly", 1); + + // page 3 header: 1 table, 1 paragraph, no text + assertXPath(pXmlDoc, "/root/page[3]/header/txt", 1); + assertXPath(pXmlDoc, "/root/page[3]/header/tab", 1); + assertXPath(pXmlDoc, + "/root/page[3]/header/tab/row/cell/txt/SwParaPortion/SwLineLayout/child::*", 0); + assertXPath(pXmlDoc, "/root/page[3]/header//anchored", 0); + // tdf#149313: ensure 3rd page does not have extra empty paragraph at top + assertXPathContent(pXmlDoc, "/root/page[3]/body//txt", u"AUFGABENSTELLUNG"); + + // page 4 header: 1 table, 1 paragraph, with text + assertXPath(pXmlDoc, "/root/page[4]/header/txt", 1); + assertXPath(pXmlDoc, "/root/page[4]/header/tab", 1); + assertXPath(pXmlDoc, + "/root/page[4]/header/tab/row[1]/cell[1]/txt[1]/SwParaPortion/SwLineLayout/" + "SwParaPortion", + "portion", u"Titel der studentischen Arbeit"); + assertXPath(pXmlDoc, "/root/page[4]/header//anchored", 0); + + // page 5: same as page 4 + assertXPath(pXmlDoc, "/root/page[5]/header/txt", 1); + assertXPath(pXmlDoc, "/root/page[5]/header/tab", 1); + assertXPath(pXmlDoc, + "/root/page[5]/header/tab/row[1]/cell[1]/txt[1]/SwParaPortion/SwLineLayout/" + "SwParaPortion", + "portion", u"Titel der studentischen Arbeit"); + assertXPath(pXmlDoc, "/root/page[5]/header//anchored", 0); + + // page 6: same as page 4 + assertXPath(pXmlDoc, "/root/page[6]/header/txt", 1); + assertXPath(pXmlDoc, "/root/page[6]/header/tab", 1); + assertXPath(pXmlDoc, + "/root/page[6]/header/tab/row[1]/cell[1]/txt[1]/SwParaPortion/SwLineLayout/" + "SwParaPortion", + "portion", u"Titel der studentischen Arbeit"); + assertXPath(pXmlDoc, "/root/page[6]/header//anchored", 0); + }; - // page 6: same as page 4 - assertXPath(pXmlDoc, "/root/page[6]/header/txt", 1); - assertXPath(pXmlDoc, "/root/page[6]/header/tab", 1); - assertXPath( - pXmlDoc, - "/root/page[6]/header/tab/row[1]/cell[1]/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"Titel der studentischen Arbeit"); - assertXPath(pXmlDoc, "/root/page[6]/header//anchored", 0); + createSwDoc("090716_Studentische_Arbeit_VWS.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } CPPUNIT_TEST_FIXTURE(Test, testTdf79435_legacyInputFields) @@ -1152,12 +1159,11 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf131420) assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:pPr/w:pBdr/w:top"); } -DECLARE_OOXMLEXPORT_TEST(testTdf80526_word_wrap, "tdf80526_word_wrap.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf80526_word_wrap) { // tdf#80526: check whether the "wrap" property has been set + createSwDoc("tdf80526_word_wrap.docx"); // TODO: fix export too - if (isExported()) - return; uno::Reference<drawing::XShape> xShape = getShape(1); CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xShape, u"TextWordWrap"_ustr)); } @@ -1780,22 +1786,27 @@ DECLARE_OOXMLEXPORT_TEST(testTdf58944RepeatingTableHeader, "tdf58944-repeating-t CPPUNIT_TEST_FIXTURE(Test, testTdf81100) { - loadAndSave("tdf81100.docx"); + auto verify = [this](bool bIsExport = false) { + xmlDocUniquePtr pDump = parseLayoutDump(); + CPPUNIT_ASSERT_EQUAL(3, getPages()); + + // table starts on page 1 and finished on page 2 + // and it has got only a single repeating header line + assertXPath(pDump, "/root/page[2]/body/tab[1]", 1); + assertXPath(pDump, "/root/page[2]/body/tab[1]/row", 2); + assertXPath(pDump, "/root/page[3]/body/tab", 1); + if (!bIsExport) // TODO export tblHeader=false + assertXPath(pDump, "/root/page[3]/body/tab/row", 1); + }; + createSwDoc("tdf81100.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/styles.xml"_ustr); CPPUNIT_ASSERT(pXmlDoc); // keep "repeat table header" setting of table styles assertXPath(pXmlDoc, "/w:styles/w:style/w:tblStylePr/w:trPr/w:tblHeader", 4); - - xmlDocUniquePtr pDump = parseLayoutDump(); - CPPUNIT_ASSERT_EQUAL(3, getPages()); - - // table starts on page 1 and finished on page 2 - // and it has got only a single repeating header line - assertXPath(pDump, "/root/page[2]/body/tab[1]", 1); - assertXPath(pDump, "/root/page[2]/body/tab[1]/row", 2); - assertXPath(pDump, "/root/page[3]/body/tab", 1); - if (!isExported()) // TODO export tblHeader=false - assertXPath(pDump, "/root/page[3]/body/tab/row", 1); } CPPUNIT_TEST_FIXTURE(Test, testTdf88496) @@ -2153,111 +2164,128 @@ static bool lcl_nearEqual(const sal_Int32 nNumber1, const sal_Int32 nNumber2, return std::abs(nNumber1 - nNumber2) < nMaxDiff; } -DECLARE_OOXMLEXPORT_TEST(testTdf119952_negativeMargins, "tdf119952_negativeMargins.docx") -{ - // With negative margins (in MS Word) one can set up header (or footer) that overlaps with the body. - // LibreOffice unable to display that, so when importing negative margins, - // the header (or footer) converted to a flyframe, anchored to the header.. - // that can overlap with the body, and will appear like in Word. - // This conversion modifies the document [i.e. replacing header text with a textbox...] - // but its DOCX export looks the same, as the original document in Word, too. - xmlDocUniquePtr pDump = parseLayoutDump(); - - //Check layout positions / sizes - sal_Int32 nLeftHead = getXPath(pDump, "//page[1]/header/infos/bounds", "left").toInt32(); - sal_Int32 nLeftBody = getXPath(pDump, "//page[1]/body/infos/bounds", "left").toInt32(); - sal_Int32 nLeftFoot = getXPath(pDump, "//page[1]/footer/infos/bounds", "left").toInt32(); - sal_Int32 nLeftHFly - = getXPath(pDump, "//page[1]/header/txt/anchored/fly/infos/bounds", "left").toInt32(); - sal_Int32 nLeftFFly - = getXPath(pDump, "//page[1]/footer/txt/anchored/fly/infos/bounds", "left").toInt32(); - - sal_Int32 nTopHead = getXPath(pDump, "//page[1]/header/infos/bounds", "top").toInt32(); - sal_Int32 nTopBody = getXPath(pDump, "//page[1]/body/infos/bounds", "top").toInt32(); - sal_Int32 nTopFoot = getXPath(pDump, "//page[1]/footer/infos/bounds", "top").toInt32(); - sal_Int32 nTopHFly - = getXPath(pDump, "//page[1]/header/txt/anchored/fly/infos/bounds", "top").toInt32(); - sal_Int32 nTopFFly - = getXPath(pDump, "//page[1]/footer/txt/anchored/fly/infos/bounds", "top").toInt32(); - - sal_Int32 nHeightHead = getXPath(pDump, "//page[1]/header/infos/bounds", "height").toInt32(); - sal_Int32 nHeightBody = getXPath(pDump, "//page[1]/body/infos/bounds", "height").toInt32(); - sal_Int32 nHeightFoot = getXPath(pDump, "//page[1]/footer/infos/bounds", "height").toInt32(); - sal_Int32 nHeightHFly - = getXPath(pDump, "//page[1]/header/txt/anchored/fly/infos/bounds", "height").toInt32(); - sal_Int32 nHeightFFly - = getXPath(pDump, "//page[1]/footer/txt/anchored/fly/infos/bounds", "height").toInt32(); - sal_Int32 nHeightHFlyBound - = getXPath(pDump, "//page[1]/header/infos/prtBounds", "height").toInt32(); - sal_Int32 nHeightFFlyBound - = getXPath(pDump, "//page[1]/footer/infos/prtBounds", "height").toInt32(); - - CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftBody)); - CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftFoot)); - CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftHFly)); - CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftFFly)); - - CPPUNIT_ASSERT(lcl_nearEqual(nTopHead, 851)); - CPPUNIT_ASSERT(lcl_nearEqual(nTopBody, 1418)); - CPPUNIT_ASSERT(lcl_nearEqual(nTopFoot, 15875)); - CPPUNIT_ASSERT(lcl_nearEqual(nTopHFly, 851)); - - // this seems to be an import bug - if (!isExported()) - CPPUNIT_ASSERT(lcl_nearEqual(nTopFFly, 14403)); - - CPPUNIT_ASSERT(lcl_nearEqual(nHeightHead, 567)); - CPPUNIT_ASSERT(lcl_nearEqual(nHeightBody, 14457)); - CPPUNIT_ASSERT(lcl_nearEqual(nHeightFoot, 680)); - CPPUNIT_ASSERT(lcl_nearEqual(nHeightHFly, 2152)); - CPPUNIT_ASSERT(lcl_nearEqual(nHeightFFly, 2152)); - - // after export these heights increase to like 567. - // not sure if it is another import, or export bug... or just the result of the modified document - if (!isExported()) - { - CPPUNIT_ASSERT(lcl_nearEqual(nHeightHFlyBound, 57)); - CPPUNIT_ASSERT(lcl_nearEqual(nHeightFFlyBound, 57)); - } +CPPUNIT_TEST_FIXTURE(Test, testTdf119952_negativeMargins) +{ + auto verify = [this](bool bIsExport = false) { + // With negative margins (in MS Word) one can set up header (or footer) that overlaps with the body. + // LibreOffice unable to display that, so when importing negative margins, + // the header (or footer) converted to a flyframe, anchored to the header.. + // that can overlap with the body, and will appear like in Word. + // This conversion modifies the document [i.e. replacing header text with a textbox...] + // but its DOCX export looks the same, as the original document in Word, too. + xmlDocUniquePtr pDump = parseLayoutDump(); + + //Check layout positions / sizes + sal_Int32 nLeftHead = getXPath(pDump, "//page[1]/header/infos/bounds", "left").toInt32(); + sal_Int32 nLeftBody = getXPath(pDump, "//page[1]/body/infos/bounds", "left").toInt32(); + sal_Int32 nLeftFoot = getXPath(pDump, "//page[1]/footer/infos/bounds", "left").toInt32(); + sal_Int32 nLeftHFly + = getXPath(pDump, "//page[1]/header/txt/anchored/fly/infos/bounds", "left").toInt32(); + sal_Int32 nLeftFFly + = getXPath(pDump, "//page[1]/footer/txt/anchored/fly/infos/bounds", "left").toInt32(); + + sal_Int32 nTopHead = getXPath(pDump, "//page[1]/header/infos/bounds", "top").toInt32(); + sal_Int32 nTopBody = getXPath(pDump, "//page[1]/body/infos/bounds", "top").toInt32(); + sal_Int32 nTopFoot = getXPath(pDump, "//page[1]/footer/infos/bounds", "top").toInt32(); + sal_Int32 nTopHFly + = getXPath(pDump, "//page[1]/header/txt/anchored/fly/infos/bounds", "top").toInt32(); + sal_Int32 nTopFFly + = getXPath(pDump, "//page[1]/footer/txt/anchored/fly/infos/bounds", "top").toInt32(); + + sal_Int32 nHeightHead + = getXPath(pDump, "//page[1]/header/infos/bounds", "height").toInt32(); + sal_Int32 nHeightBody = getXPath(pDump, "//page[1]/body/infos/bounds", "height").toInt32(); + sal_Int32 nHeightFoot + = getXPath(pDump, "//page[1]/footer/infos/bounds", "height").toInt32(); + sal_Int32 nHeightHFly + = getXPath(pDump, "//page[1]/header/txt/anchored/fly/infos/bounds", "height").toInt32(); + sal_Int32 nHeightFFly + = getXPath(pDump, "//page[1]/footer/txt/anchored/fly/infos/bounds", "height").toInt32(); + sal_Int32 nHeightHFlyBound + = getXPath(pDump, "//page[1]/header/infos/prtBounds", "height").toInt32(); + sal_Int32 nHeightFFlyBound + = getXPath(pDump, "//page[1]/footer/infos/prtBounds", "height").toInt32(); + + CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftBody)); + CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftFoot)); + CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftHFly)); + CPPUNIT_ASSERT(lcl_nearEqual(nLeftHead, nLeftFFly)); + + CPPUNIT_ASSERT(lcl_nearEqual(nTopHead, 851)); + CPPUNIT_ASSERT(lcl_nearEqual(nTopBody, 1418)); + CPPUNIT_ASSERT(lcl_nearEqual(nTopFoot, 15875)); + CPPUNIT_ASSERT(lcl_nearEqual(nTopHFly, 851)); + + // this seems to be an import bug + if (!bIsExport) + CPPUNIT_ASSERT(lcl_nearEqual(nTopFFly, 14403)); + + CPPUNIT_ASSERT(lcl_nearEqual(nHeightHead, 567)); + CPPUNIT_ASSERT(lcl_nearEqual(nHeightBody, 14457)); + CPPUNIT_ASSERT(lcl_nearEqual(nHeightFoot, 680)); + CPPUNIT_ASSERT(lcl_nearEqual(nHeightHFly, 2152)); + CPPUNIT_ASSERT(lcl_nearEqual(nHeightFFly, 2152)); + + // after export these heights increase to like 567. + // not sure if it is another import, or export bug... or just the result of the modified document + if (!bIsExport) + { + CPPUNIT_ASSERT(lcl_nearEqual(nHeightHFlyBound, 57)); + CPPUNIT_ASSERT(lcl_nearEqual(nHeightFFlyBound, 57)); + } - //Check text of header/ footer - assertXPath(pDump, - "//page[1]/header/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"f1"); - assertXPath(pDump, - "//page[1]/header/txt/anchored/fly/txt[8]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u" f8"); - assertXPath(pDump, - "//page[1]/footer/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u" f8"); - assertXPath(pDump, - "//page[1]/footer/txt/anchored/fly/txt[8]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"f1"); - - assertXPath(pDump, - "//page[2]/header/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"p1"); - assertXPath(pDump, - "//page[2]/footer/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u"p1"); - - assertXPath(pDump, - "//page[3]/header/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u" aaaa"); - assertXPath(pDump, - "//page[3]/header/txt/anchored/fly/txt[5]/SwParaPortion/SwLineLayout/SwParaPortion", - "portion", u" eeee"); - - assertXPathContent(pDump, "/root/page[1]/header/txt/anchored/fly", - u"f1 f2 f3 f4 f5 f6 " - " f7 f8"); - assertXPathContent(pDump, "/root/page[1]/footer/txt/anchored/fly", - u" f8 f7 f6 f5 " - " f4 f3 f2f1"); - assertXPathContent(pDump, "/root/page[2]/header/txt/anchored/fly", u"p1"); - assertXPathContent(pDump, "/root/page[2]/footer/txt/anchored/fly", u"p1"); - assertXPathContent(pDump, "/root/page[3]/header/txt/anchored/fly", - u" aaaa bbbb cccc dddd eeee"); + //Check text of header/ footer + assertXPath( + pDump, + "//page[1]/header/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u"f1"); + assertXPath( + pDump, + "//page[1]/header/txt/anchored/fly/txt[8]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u" f8"); + assertXPath( + pDump, + "//page[1]/footer/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u" f8"); + assertXPath( + pDump, + "//page[1]/footer/txt/anchored/fly/txt[8]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u"f1"); + + assertXPath( + pDump, + "//page[2]/header/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u"p1"); + assertXPath( + pDump, + "//page[2]/footer/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u"p1"); + + assertXPath( + pDump, + "//page[3]/header/txt/anchored/fly/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u" aaaa"); + assertXPath( + pDump, + "//page[3]/header/txt/anchored/fly/txt[5]/SwParaPortion/SwLineLayout/SwParaPortion", + "portion", u" eeee"); + + assertXPathContent(pDump, "/root/page[1]/header/txt/anchored/fly", + u"f1 f2 f3 f4 f5 f6 " + " f7 f8"); + assertXPathContent(pDump, "/root/page[1]/footer/txt/anchored/fly", + u" f8 f7 f6 f5 " + " f4 f3 f2f1"); + assertXPathContent(pDump, "/root/page[2]/header/txt/anchored/fly", u"p1"); + assertXPathContent(pDump, "/root/page[2]/footer/txt/anchored/fly", u"p1"); + assertXPathContent(pDump, "/root/page[3]/header/txt/anchored/fly", + u" aaaa bbbb cccc dddd eeee"); + }; + + createSwDoc("tdf119952_negativeMargins.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } DECLARE_OOXMLEXPORT_TEST(testTdf143384_tableInFoot_negativeMargins, diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index 2db8bc8f1bcd..f5968b005358 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -804,33 +804,40 @@ CPPUNIT_TEST_FIXTURE(Test, testTextInput) CPPUNIT_ASSERT_EQUAL(4, nElements); } -DECLARE_OOXMLEXPORT_TEST(testTdf123460, "tdf123460.docx") -{ - // check paragraph mark deletion at terminating moveFrom - CPPUNIT_ASSERT(getParagraph( 2 )->getString().startsWith("Nunc")); - uno::Reference<container::XEnumerationAccess> xRunEnumAccess(getParagraph( 2 ), uno::UNO_QUERY); - uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); - uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL( u""_ustr, xRun->getString()); - xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT(hasProperty(xRun, u"RedlineType"_ustr)); - CPPUNIT_ASSERT_EQUAL(u"Delete"_ustr,getProperty<OUString>(xRun, u"RedlineType"_ustr)); - xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT(xRun->getString().endsWith("tellus.")); - xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT(hasProperty(xRun, u"Bookmark"_ustr)); - - // The paragraph marker's formatting. - xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,getProperty<OUString>(xRun, u"TextPortionType"_ustr)); - CPPUNIT_ASSERT(xRun->getString().isEmpty()); - - // deleted paragraph mark at the end of the second paragraph - if (isExported()) - { - // there is no run after the MoveBookmark - CPPUNIT_ASSERT(!xRunEnum->hasMoreElements()); - } +CPPUNIT_TEST_FIXTURE(Test, testTdf123460) +{ + auto verify = [this](bool bIsExport = false) { + // check paragraph mark deletion at terminating moveFrom + CPPUNIT_ASSERT(getParagraph( 2 )->getString().startsWith("Nunc")); + uno::Reference<container::XEnumerationAccess> xRunEnumAccess(getParagraph( 2 ), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); + uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL( u""_ustr, xRun->getString()); + xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT(hasProperty(xRun, u"RedlineType"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"Delete"_ustr,getProperty<OUString>(xRun, u"RedlineType"_ustr)); + xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT(xRun->getString().endsWith("tellus.")); + xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT(hasProperty(xRun, u"Bookmark"_ustr)); + + // The paragraph marker's formatting. + xRun.set(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"Text"_ustr,getProperty<OUString>(xRun, u"TextPortionType"_ustr)); + CPPUNIT_ASSERT(xRun->getString().isEmpty()); + + // deleted paragraph mark at the end of the second paragraph + if (bIsExport) + { + // there is no run after the MoveBookmark + CPPUNIT_ASSERT(!xRunEnum->hasMoreElements()); + } + }; + + createSwDoc("tdf123460.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } CPPUNIT_TEST_FIXTURE(Test, testTdf146140) @@ -884,27 +891,26 @@ DECLARE_OOXMLEXPORT_TEST(testTdf121784, "tdf121784.docx") CPPUNIT_ASSERT_EQUAL( u"i"_ustr, getRun( getParagraph( 2 ), 3 )->getString()); } -DECLARE_OOXMLEXPORT_TEST(testTbrlFrameVml, "tbrl-frame-vml.docx") +CPPUNIT_TEST_FIXTURE(Test, testTbrlFrameVml) { + createSwDoc("tbrl-frame-vml.docx"); uno::Reference<beans::XPropertySet> xTextFrame(getShape(1), uno::UNO_QUERY); CPPUNIT_ASSERT(xTextFrame.is()); - if (isExported()) - { - // DML import: creates a TextBox, eaVert read back as TB_RL in TextWritingMode + // VML import: creates a TextFrame. - auto eMode = getProperty<text::WritingMode>(xTextFrame, u"TextWritingMode"_ustr); - CPPUNIT_ASSERT_EQUAL(text::WritingMode::WritingMode_TB_RL, eMode); - } - else - { - // VML import: creates a TextFrame. + auto nActual = getProperty<sal_Int16>(xTextFrame, u"WritingMode"_ustr); + // Without the accompanying fix in place, this test would have failed with 'Expected: 2; Actual: + // 4', i.e. writing direction was inherited from page, instead of explicit tbrl. + CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, nActual); - auto nActual = getProperty<sal_Int16>(xTextFrame, u"WritingMode"_ustr); - // Without the accompanying fix in place, this test would have failed with 'Expected: 2; Actual: - // 4', i.e. writing direction was inherited from page, instead of explicit tbrl. - CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL, nActual); - } + saveAndReload(mpFilter); + xTextFrame.set(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT(xTextFrame.is()); + + // DML import: creates a TextBox, eaVert read back as TB_RL in TextWritingMode + auto eMode = getProperty<text::WritingMode>(xTextFrame, u"TextWritingMode"_ustr); + CPPUNIT_ASSERT_EQUAL(text::WritingMode::WritingMode_TB_RL, eMode); } CPPUNIT_TEST_FIXTURE(Test, testTdf119037) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx index 7456fe1577ff..b5c47bee7c8d 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx @@ -88,15 +88,14 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148380_createField, "tdf148380_createField.docx" CPPUNIT_ASSERT_EQUAL(u"yesterday at noon"_ustr, xField->getPresentation(false)); } -DECLARE_OOXMLEXPORT_TEST(testTdf148380_fldLocked, "tdf148380_fldLocked.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf148380_fldLocked) { + createSwDoc("tdf148380_fldLocked.docx"); getParagraph(2, u"4/5/2022 4:29:00 PM"_ustr); getParagraph(4, u"1/23/4567 8:9:10 PM"_ustr); // Verify that these are fields, and not just plain text // (import only, since export thankfully just dumps these fixed fields as plain text - if (isExported()) - return; uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); auto xFieldsAccess(xTextFieldsSupplier->getTextFields()); uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); @@ -107,6 +106,10 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148380_fldLocked, "tdf148380_fldLocked.docx") xField.set(xFields->nextElement(), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(u"1/23/4567 8:9:10 PM"_ustr, xField->getPresentation(false)); CPPUNIT_ASSERT_EQUAL(u"DocInformation:Last printed (fixed)"_ustr, xField->getPresentation(true)); + saveAndReload(mpFilter); + + getParagraph(2, u"4/5/2022 4:29:00 PM"_ustr); + getParagraph(4, u"1/23/4567 8:9:10 PM"_ustr); } DECLARE_OOXMLEXPORT_TEST(testTdf148380_usernameField, "tdf148380_usernameField.docx") @@ -499,10 +502,9 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf148494) assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[3]/w:instrText", u" MACROBUTTON AllCaps Hello World "); } -DECLARE_OOXMLEXPORT_TEST(testTdf137466, "tdf137466.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf137466) { - if (!isExported()) - return; // initial import, no further checks + loadAndSave("tdf137466.docx"); xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); // Ensure that we have <w:placeholder><w:docPart v:val="xxxx"/></w:placeholder> @@ -662,22 +664,25 @@ DECLARE_OOXMLEXPORT_TEST(testTdf126287, "tdf126287.docx") CPPUNIT_ASSERT_EQUAL(2, getPages()); } -DECLARE_OOXMLEXPORT_TEST(testTdf123642_BookmarkAtDocEnd, "tdf123642.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf123642_BookmarkAtDocEnd) { - // get bookmark interface - uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY); - uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks(); - - // check: we have 1 bookmark (previously there were 0) - CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xBookmarksByIdx->getCount()); - CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"Bookmark1"_ustr)); - - // and it is really in exported DOCX (let's ensure) - if (!isExported()) - return; // initial import, no further checks - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + auto verify = [this]() { + // get bookmark interface + uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks(); + + // check: we have 1 bookmark (previously there were 0) + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xBookmarksByIdx->getCount()); + CPPUNIT_ASSERT(xBookmarksByName->hasByName(u"Bookmark1"_ustr)); + }; + + createSwDoc("tdf123642.docx"); + verify(); + saveAndReload(mpFilter); + verify(); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:bookmarkStart[1]", "name", u"Bookmark1"); } @@ -854,35 +859,40 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148052, "tdf148052.docx") CPPUNIT_ASSERT_EQUAL(u"14. Aug 18"_ustr, xTextField->getPresentation(false)); } -DECLARE_OOXMLEXPORT_TEST(testTdf148111, "tdf148111.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf148111) { - uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + auto verify = [this]() { + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + + uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); + std::vector<OUString> aExpectedValues = { + // These field values are NOT in order in document: getTextFields did provide + // fields in a strange but fixed order (mostly reversed, thanks to SwModify::Add) + u"Title"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, + u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, + u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, + u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, + u"Placeholder"_ustr, u"Title"_ustr, u"Title"_ustr, u"Title"_ustr, + u"Title"_ustr, u"Title"_ustr, u"Title"_ustr, u"Title"_ustr + }; - uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); - std::vector<OUString> aExpectedValues = { - // These field values are NOT in order in document: getTextFields did provide - // fields in a strange but fixed order (mostly reversed, thanks to SwModify::Add) - u"Title"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, - u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, - u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, - u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, u"Placeholder"_ustr, - u"Placeholder"_ustr, u"Title"_ustr, u"Title"_ustr, u"Title"_ustr, - u"Title"_ustr, u"Title"_ustr, u"Title"_ustr, u"Title"_ustr - }; + sal_uInt16 nIndex = 0; + while (xFields->hasMoreElements()) + { + uno::Reference<text::XTextField> xTextField(xFields->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(aExpectedValues[nIndex++], xTextField->getPresentation(false)); + } - sal_uInt16 nIndex = 0; - while (xFields->hasMoreElements()) - { - uno::Reference<text::XTextField> xTextField(xFields->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(aExpectedValues[nIndex++], xTextField->getPresentation(false)); - } + // No more fields + CPPUNIT_ASSERT(!xFields->hasMoreElements()); + }; - // No more fields - CPPUNIT_ASSERT(!xFields->hasMoreElements()); + createSwDoc("tdf148111.docx"); + verify(); + saveAndReload(mpFilter); + verify(); - if (!isExported()) - return; xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); // ShowingPlaceholder should be off for 0, false and "on". (This was 21 before the fix) assertXPath(pXmlDoc,"//w:p/w:sdt/w:sdtPr/w:showingPlcHdr", 12); @@ -916,10 +926,9 @@ DECLARE_OOXMLEXPORT_TEST(TestTdf73499, "tdf73499.docx") xTextBox2Properties->getPropertyValue(u"ChainPrevName"_ustr).get<OUString>()); } -DECLARE_OOXMLEXPORT_TEST(testTdf81507, "tdf81507.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf81507) { - if (!isExported()) - return; // initial import, no further checks + loadAndSave("tdf81507.docx"); xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); // Ensure that we have <w:text w:multiLine="1"/> @@ -1013,10 +1022,9 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148455_1, "tdf148455_1.docx") CPPUNIT_ASSERT_EQUAL(u"1.1.1."_ustr, getProperty<OUString>(xPara2, u"ListLabelString"_ustr)); } -DECLARE_OOXMLEXPORT_TEST(testTdf148455_2, "tdf148455_2.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf148455_2) { - if (!isExported()) - return; // initial import, no further checks + loadAndSave("tdf148455_2.docx"); xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); // Find list id for restarted list diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx index 57d10c95aeb7..bb5151098e5d 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx @@ -74,34 +74,40 @@ CPPUNIT_TEST_FIXTURE(Test, testCellSdtRedline) loadAndSave("cell-sdt-redline.docx"); } -DECLARE_OOXMLEXPORT_TEST(testTdf148956_directEndFormatting, "tdf148956_directEndFormatting.docx") -{ - SwDoc* pDoc = getSwDoc(); - SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); +CPPUNIT_TEST_FIXTURE(Test, testTdf148956_directEndFormatting) +{ + auto verify = [this](bool bIsExport = false) { + SwDoc* pDoc = getSwDoc(); + SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + // pWrtShell->EndPara(/*bSelect=*/true); + dispatchCommand(mxComponent, u".uno:GotoEndOfPara"_ustr, {}); + if (!bIsExport) + { + CPPUNIT_ASSERT_MESSAGE( + "Has direct formatting", + pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints()); + } + else + { + CPPUNIT_ASSERT_MESSAGE( + "Direct formatting cleared", + !pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints()); + } + + pWrtShell->SttPara(/*bSelect=*/true); + dispatchCommand(mxComponent, u".uno:ResetAttributes"_ustr, {}); + + dispatchCommand(mxComponent, u".uno:GotoEndOfPara"_ustr, {}); - // pWrtShell->EndPara(/*bSelect=*/true); - dispatchCommand(mxComponent, u".uno:GotoEndOfPara"_ustr, {}); - if (!isExported()) - { - CPPUNIT_ASSERT_MESSAGE( - "Has direct formatting", - pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints()); - } - else - { CPPUNIT_ASSERT_MESSAGE( "Direct formatting cleared", !pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints()); - } - - pWrtShell->SttPara(/*bSelect=*/true); - dispatchCommand(mxComponent, u".uno:ResetAttributes"_ustr, {}); - - dispatchCommand(mxComponent, u".uno:GotoEndOfPara"_ustr, {}); - - CPPUNIT_ASSERT_MESSAGE( - "Direct formatting cleared", - !pWrtShell->GetCursor()->GetPoint()->GetNode().GetTextNode()->GetpSwpHints()); + }; + createSwDoc("tdf148956_directEndFormatting.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } DECLARE_OOXMLEXPORT_TEST(testTdf147646, "tdf147646_mergedCellNumbering.docx") @@ -121,33 +127,30 @@ DECLARE_OOXMLEXPORT_TEST(testTdf153526_commentInNumbering, "tdf153526_commentInN CPPUNIT_ASSERT_EQUAL(13, getParagraphs()); } -DECLARE_OOXMLEXPORT_TEST(testTdf153042_largeTab, "tdf153042_largeTab.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf153042_largeTab) { + createSwDoc("tdf153042_largeTab.docx"); // This is not the greatest test because it is slightly weird, and has a different layout // in MS Word 2010/2003 than it does in Word 2019. This tests for the 2019 layout. // Additionally (in Word 2019), going to paragraph properties and hitting OK changes the layout. // It changes back by going to outline numbering properties and hitting OK. // export does not keep the tabstop when exporting non-numbering. (Probably a good thing...) - if (isExported()) - return; xmlDocUniquePtr pLayout = parseLayoutDump(); // Ensure a large tabstop is used in the pseudo-numbering (numbering::NONE followed by tabstop) assertXPath(pLayout, "//SwFixPortion", "width", u"1701"); } -DECLARE_OOXMLEXPORT_TEST(testTdf153042_noTab, "tdf153042_noTab.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf153042_noTab) { + createSwDoc("tdf153042_noTab.docx"); // This is not the greatest test because it is slightly weird. // It is the same as the "largeTab" file, except the paragraph properties were viewed // and OK'ed, and now it looks like how Word 2010 and 2003 were laying it out. // Amazingly, LO is handling both documents correctly at the moment, so let's unit test that... // export does not keep the tabstop when exporting non-numbering. (Probably a good thing...) - if (isExported()) - return; - xmlDocUniquePtr pLayout = parseLayoutDump(); // Ensure a miniscule tab is used in the pseudo-numbering (numbering::NONE followed by tabstop) assertXPath(pLayout, "//SwFixPortion", "width", u"10"); @@ -250,31 +253,36 @@ DECLARE_OOXMLEXPORT_TEST(testTdf154703_framePr, "tdf154703_framePr.docx") CPPUNIT_ASSERT_EQUAL(1, getShapes()); } -DECLARE_OOXMLEXPORT_TEST(testTdf154703_framePr2, "tdf154703_framePr2.rtf") -{ - // framePr frames are always imported as fully transparent - CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(getShape(1), u"FillTransparence"_ustr)); - - // as opposed to testLibreOfficeHang (RTF != INVERT_BORDER_SPACING) do not duplicate left/right - uno::Reference<text::XTextRange> xTextRange(getShape(1), uno::UNO_QUERY); - uno::Reference<text::XText> xText = xTextRange->getText(); - CPPUNIT_ASSERT_EQUAL(u"framePr"_ustr, getParagraphOfText(1, xText)->getString()); - sal_Int32 nFrame = getProperty<sal_Int32>(getShape(1), u"LeftBorderDistance"_ustr); - sal_Int32 nPara = getProperty<sal_Int32>(getParagraphOfText(1, xText), u"LeftBorderDistance"_ustr); - if (!isExported()) // RTF - CPPUNIT_ASSERT_EQUAL(sal_Int32(529), nFrame + nPara); - else // DOCX - CPPUNIT_ASSERT_EQUAL(sal_Int32(529*2), nFrame + nPara); - - if (!isExported()) - { - // Fill the frame with a red background. It should be transferred on export to the paragraph - uno::Reference<beans::XPropertySet> xFrame(getShape(1), uno::UNO_QUERY); - xFrame->setPropertyValue(u"FillColor"_ustr, uno::Any(COL_RED)); - xFrame->setPropertyValue(u"FillTransparence"_ustr, uno::Any(static_cast<sal_Int32>(0))); - - return; - } +CPPUNIT_TEST_FIXTURE(Test, testTdf154703_framePr2) +{ + auto verify = [this](bool bIsExport = false) { + // framePr frames are always imported as fully transparent + CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(getShape(1), u"FillTransparence"_ustr)); + + // as opposed to testLibreOfficeHang (RTF != INVERT_BORDER_SPACING) do not duplicate left/right + uno::Reference<text::XTextRange> xTextRange(getShape(1), uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextRange->getText(); + CPPUNIT_ASSERT_EQUAL(u"framePr"_ustr, getParagraphOfText(1, xText)->getString()); + sal_Int32 nFrame = getProperty<sal_Int32>(getShape(1), u"LeftBorderDistance"_ustr); + sal_Int32 nPara = getProperty<sal_Int32>(getParagraphOfText(1, xText), u"LeftBorderDistance"_ustr); + if (!bIsExport) // RTF + CPPUNIT_ASSERT_EQUAL(sal_Int32(529), nFrame + nPara); + else // DOCX + CPPUNIT_ASSERT_EQUAL(sal_Int32(529*2), nFrame + nPara); + + if (!bIsExport) + { + // Fill the frame with a red background. It should be transferred on export to the paragraph + uno::Reference<beans::XPropertySet> xFrame(getShape(1), uno::UNO_QUERY); + xFrame->setPropertyValue(u"FillColor"_ustr, uno::Any(COL_RED)); + xFrame->setPropertyValue(u"FillTransparence"_ustr, uno::Any(static_cast<sal_Int32>(0))); + } + }; + + createSwDoc("tdf154703_framePr2.rtf"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); // exported: framed paragraphs without a background should now have a red background xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); @@ -285,22 +293,22 @@ DECLARE_OOXMLEXPORT_TEST(testTdf154703_framePr2, "tdf154703_framePr2.rtf") assertXPathNoAttribute(pXmlDoc, "//w:body/w:p[3]/w:pPr/w:framePr", "y"); } -DECLARE_OOXMLEXPORT_TEST(testTdf154703_framePrWrapSpacing, "tdf154703_framePrWrapSpacing.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf154703_framePrWrapSpacing) { + loadAndSave("tdf154703_framePrWrapSpacing.docx"); CPPUNIT_ASSERT_EQUAL(2, getPages()); - if (!isExported()) - return; xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); // before the fix, this was half of the correct value. assertXPath(pXmlDoc, "//w:body/w:p/w:pPr/w:framePr", "hSpace", u"2552"); } -DECLARE_OOXMLEXPORT_TEST(testTdf154703_framePrTextDirection, "tdf154703_framePrTextDirection.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf154703_framePrTextDirection) { + createSwDoc("tdf154703_framePrTextDirection.docx"); + CPPUNIT_ASSERT_EQUAL(sal_Int16(text::WritingMode2::TB_RL), getProperty<sal_Int16>(getShape(1), u"WritingMode"_ustr)); + saveAndReload(mpFilter); CPPUNIT_ASSERT_EQUAL(sal_Int16(text::WritingMode2::TB_RL), getProperty<sal_Int16>(getShape(1), u"WritingMode"_ustr)); - if (!isExported()) - return; xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); assertXPath(pXmlDoc, "//w:body/w:p/w:pPr/w:textDirection", "val", u"tbRl"); @@ -564,13 +572,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf149551_mongolianVert) assertXPath(pXmlDoc, "//wps:bodyPr", "vert", u"mongolianVert"); } -DECLARE_OOXMLEXPORT_TEST(testTdf151912, "tdf151912.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf151912) { + loadAndSave("tdf151912.docx"); // For now just ensure roundtrip is successful //tdf#151548 - ensure block SDT preserves id (instead of random re-assignment) - if (!isExported()) - return; xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); assertXPath(pXmlDoc, "//w:sdt//w:sdtPr/w:id", "val", u"1802566103"); } @@ -951,87 +958,123 @@ DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_max, "tdf159158_zOrder_max.docx") CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); } -DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_zIndexMax, "tdf159158_zOrder_zIndexMax.docx") -{ - // given a yellow star with a heaven z-index of MAX_SAL_INT32 - // followed by overlapped blue star with a heaven z-index of MAX_SAL_INT32 - 1 - uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher - // there is no artificial maximum for z-index. All values are unique. Yellow is on top - if (!isExported()) //somehow the name is lost on this export - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); - if (!isExported()) //somehow the name is lost on this export - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_zIndexDuplicate_compat15, "tdf159158_zOrder_zIndexDuplicate_compat15.docx") -{ - // given a yellow star with a heaven z-index of MAX_SAL_INT32 - 1 - // followed by overlapping blue star with the same heaven z-index (last duplicate wins) - uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher - // should be the same as relativeHeight - last duplicate wins so blue is on top. - if (!isExported()) //somehow the name is lost on this export +CPPUNIT_TEST_FIXTURE(Test, testTdf159158_zOrder_zIndexMax) +{ + auto verify = [this](bool bIsExport = false) { + // given a yellow star with a heaven z-index of MAX_SAL_INT32 + // followed by overlapped blue star with a heaven z-index of MAX_SAL_INT32 - 1 + uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher + // there is no artificial maximum for z-index. All values are unique. Yellow is on top + if (!bIsExport) //somehow the name is lost on this export + { + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); + } + }; + + createSwDoc("tdf159158_zOrder_zIndexMax.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf159158_zOrder_zIndexDuplicate_compat15) +{ + auto verify = [this](bool bIsExport = false) { + // given a yellow star with a heaven z-index of MAX_SAL_INT32 - 1 + // followed by overlapping blue star with the same heaven z-index (last duplicate wins) + uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher + // should be the same as relativeHeight - last duplicate wins so blue is on top. + if (!bIsExport) //somehow the name is lost on this export + { + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); + } + }; + + createSwDoc("tdf159158_zOrder_zIndexDuplicate_compat15.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf159158_zOrder_zIndexWins) +{ + auto verify = [this](bool bIsExport = false) { + // given a yellow star with relativeHeight 0 (typically a maximum value, but not today) + // followed by an overlapping-everything textbox at z-index 0 (the lowest heaven-layer z-index) + // followed by a partially overlapping blue star with a + // seems-to-be-a-magic-number relativeHeight 251658240 (0F00 0000) + uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> zOrder2(getShape(3), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getProperty<sal_Int32>(zOrder2, u"ZOrder"_ustr)); // higher + // I'm puzzled. Somehow 0 is larger than 0EFF FFFF, but not larger than 0F00 0000 + // and yet the maximum value was established earlier as 1DFF FFFF. Something doesn't line up. + // Perhaps 0 and 1 don't mean maximum value at all, but something completely different? + CPPUNIT_ASSERT_MESSAGE("DID YOU FIX ME? I really should be yellow, not blue", + "5-Point Star Yellow" != getProperty<OUString>(zOrder0, u"Name"_ustr)); + // CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), getProperty<OUString>(zOrder1,"Name")); + // If zOrder is defined by z-index, it seems that it goes above everything set by relativeHeight + if (bIsExport) // not named on import + CPPUNIT_ASSERT_EQUAL(u"Frame1"_ustr, getProperty<OUString>(zOrder2,u"Name"_ustr)); + }; + createSwDoc("tdf159158_zOrder_zIndexWins.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf159158_zOrder_behindDocA) +{ + auto verify = [this](bool bIsExport = false) { + // given a yellow star with lowest relativeHeight 2 but behindDoc + // followed by an overlapping blue star with negative z-index -1644167168. + uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher + // yellow is at the lowest hell-level possible for relativeHeight, so expected to be under blue CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); - if (!isExported()) //somehow the name is lost on this export - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_zIndexWins, "tdf159158_zOrder_zIndexWins.docx") -{ - // given a yellow star with relativeHeight 0 (typically a maximum value, but not today) - // followed by an overlapping-everything textbox at z-index 0 (the lowest heaven-layer z-index) - // followed by a partially overlapping blue star with a - // seems-to-be-a-magic-number relativeHeight 251658240 (0F00 0000) - uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> zOrder2(getShape(3), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getProperty<sal_Int32>(zOrder2, u"ZOrder"_ustr)); // higher - // I'm puzzled. Somehow 0 is larger than 0EFF FFFF, but not larger than 0F00 0000 - // and yet the maximum value was established earlier as 1DFF FFFF. Something doesn't line up. - // Perhaps 0 and 1 don't mean maximum value at all, but something completely different? - CPPUNIT_ASSERT_MESSAGE("DID YOU FIX ME? I really should be yellow, not blue", - "5-Point Star Yellow" != getProperty<OUString>(zOrder0, u"Name"_ustr)); - // CPPUNIT_ASSERT_EQUAL(OUString("5-Point Star Blue"), getProperty<OUString>(zOrder1,"Name")); - // If zOrder is defined by z-index, it seems that it goes above everything set by relativeHeight - if (isExported()) // not named on import - CPPUNIT_ASSERT_EQUAL(u"Frame1"_ustr, getProperty<OUString>(zOrder2,u"Name"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_behindDocA, "tdf159158_zOrder_behindDocA.docx") -{ - // given a yellow star with lowest relativeHeight 2 but behindDoc - // followed by an overlapping blue star with negative z-index -1644167168. - uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher - // yellow is at the lowest hell-level possible for relativeHeight, so expected to be under blue - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); - if (!isExported()) // the name is lost on export - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); -} - -DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_behindDocB, "tdf159158_zOrder_behindDocB.docx") -{ - // given a yellow star with a high relativeHeight 503314431 (1DFF F7FF) but behindDoc - // followed by an overlapping blue star with negative z-index -1644167168. - uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower - CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher - // yellow is at the highest hell-level possible for relativeHeight, - // so you will be forgiven for thinking yellow should be on the top. - // Any z-index level ends up being above any relativeHeight, so blue should still be on top - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); - if (!isExported()) // the name is lost on export - CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); + if (!bIsExport) // the name is lost on export + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); + }; + + createSwDoc("tdf159158_zOrder_behindDocA.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf159158_zOrder_behindDocB) +{ + auto verify = [this](bool bIsExport = false) { + // given a yellow star with a high relativeHeight 503314431 (1DFF F7FF) but behindDoc + // followed by an overlapping blue star with negative z-index -1644167168. + uno::Reference<beans::XPropertySet> zOrder0(getShape(1), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> zOrder1(getShape(2), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(zOrder0, u"ZOrder"_ustr)); // lower + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty<sal_Int32>(zOrder1, u"ZOrder"_ustr)); // higher + // yellow is at the highest hell-level possible for relativeHeight, + // so you will be forgiven for thinking yellow should be on the top. + // Any z-index level ends up being above any relativeHeight, so blue should still be on top + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Yellow"_ustr, getProperty<OUString>(zOrder0, u"Name"_ustr)); + if (!bIsExport) // the name is lost on export + CPPUNIT_ASSERT_EQUAL(u"5-Point Star Blue"_ustr, getProperty<OUString>(zOrder1,u"Name"_ustr)); + }; + + createSwDoc("tdf159158_zOrder_behindDocB.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } DECLARE_OOXMLEXPORT_TEST(testTdf159158_zOrder_headerBehind, "tdf159158_zOrder_headerBehind.odt") diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx index 2d4e5f639b9c..04356b53fa66 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx @@ -148,18 +148,23 @@ DECLARE_OOXMLEXPORT_TEST(testKeywords, "tdf143175.docx") CPPUNIT_ASSERT_EQUAL(u"Three"_ustr, aKeywords[2]); } -DECLARE_OOXMLEXPORT_TEST(testZoom, "zoom.docx") -{ - uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); - uno::Reference<view::XViewSettingsSupplier> xViewSettingsSupplier(xModel->getCurrentController(), uno::UNO_QUERY); - uno::Reference<beans::XPropertySet> xPropertySet(xViewSettingsSupplier->getViewSettings()); - sal_Int16 nValue = 0; - xPropertySet->getPropertyValue(u"ZoomValue"_ustr) >>= nValue; - CPPUNIT_ASSERT_EQUAL(sal_Int16(42), nValue); +CPPUNIT_TEST_FIXTURE(Test, testZoom) +{ + auto verify = [this]() { + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<view::XViewSettingsSupplier> xViewSettingsSupplier(xModel->getCurrentController(), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPropertySet(xViewSettingsSupplier->getViewSettings()); + sal_Int16 nValue = 0; + xPropertySet->getPropertyValue(u"ZoomValue"_ustr) >>= nValue; + CPPUNIT_ASSERT_EQUAL(sal_Int16(42), nValue); + }; + + createSwDoc("zoom.docx"); + verify(); + saveAndReload(mpFilter); + verify(); // Validation test: order of elements were wrong. - if (!isExported()) - return; validate(maTempFile.GetFileName(), test::OOXML); xmlDocUniquePtr pXmlDoc = parseExport(u"word/styles.xml"_ustr); // Order was: rsid, next. @@ -188,62 +193,67 @@ CPPUNIT_TEST_FIXTURE(Test, defaultTabStopNotInStyles) CPPUNIT_ASSERT_EQUAL( style::TabAlign_DEFAULT, stops[ 0 ].Alignment ); } -DECLARE_OOXMLEXPORT_TEST(testFdo38244, "fdo38244.docx") -{ - /* - * Comments attached to a range was imported without the range, check for the annotation mark start/end positions. - * - * oParas = ThisComponent.Text.createEnumeration - * oPara = oParas.nextElement - * oRuns = oPara.createEnumeration - * oRun = oRuns.nextElement - * oRun = oRuns.nextElement 'Annotation - * oRun = oRuns.nextElement - * oRun = oRuns.nextElement 'AnnotationEnd - * xray oRun.TextPortionType - */ - uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY); - uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); - uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY); - uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); - xRunEnum->nextElement(); - uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr, getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr)); - xRunEnum->nextElement(); - xPropertySet.set(xRunEnum->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr, getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr)); - - /* - * Initials were not imported. - * - * oFields = ThisComponent.TextFields.createEnumeration - * oField = oFields.nextElement - * xray oField.Initials - */ - uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); - uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); - uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); - xPropertySet.set(xFields->nextElement(), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(u"M"_ustr, getProperty<OUString>(xPropertySet, u"Initials"_ustr)); - - /* - * There was a fake empty paragraph at the end of the comment text. - * - * oFields = ThisComponent.TextFields.createEnumeration - * oField = oFields.nextElement - * oParas = oField.TextRange.createEnumeration - * oPara = oParas.nextElement - * oPara = oParas.nextElement - */ - - xParaEnumAccess = getProperty< uno::Reference<container::XEnumerationAccess> >(xPropertySet, u"TextRange"_ustr); - xParaEnum = xParaEnumAccess->createEnumeration(); - xParaEnum->nextElement(); - CPPUNIT_ASSERT(!xParaEnum->hasMoreElements()); +CPPUNIT_TEST_FIXTURE(Test, testFdo38244) +{ + auto verify = [this]() { + /* + * Comments attached to a range was imported without the range, check for the annotation mark start/end positions. + * + * oParas = ThisComponent.Text.createEnumeration + * oPara = oParas.nextElement + * oRuns = oPara.createEnumeration + * oRun = oRuns.nextElement + * oRun = oRuns.nextElement 'Annotation + * oRun = oRuns.nextElement + * oRun = oRuns.nextElement 'AnnotationEnd + * xray oRun.TextPortionType + */ + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); + xRunEnum->nextElement(); + uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr, getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr)); + xRunEnum->nextElement(); + xPropertySet.set(xRunEnum->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr, getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr)); + + /* + * Initials were not imported. + * + * oFields = ThisComponent.TextFields.createEnumeration + * oField = oFields.nextElement + * xray oField.Initials + */ + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields()); + uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration()); + xPropertySet.set(xFields->nextElement(), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"M"_ustr, getProperty<OUString>(xPropertySet, u"Initials"_ustr)); + + /* + * There was a fake empty paragraph at the end of the comment text. + * + * oFields = ThisComponent.TextFields.createEnumeration + * oField = oFields.nextElement + * oParas = oField.TextRange.createEnumeration + * oPara = oParas.nextElement + * oPara = oParas.nextElement + */ + + xParaEnumAccess = getProperty< uno::Reference<container::XEnumerationAccess> >(xPropertySet, u"TextRange"_ustr); + xParaEnum = xParaEnumAccess->createEnumeration(); + xParaEnum->nextElement(); + CPPUNIT_ASSERT(!xParaEnum->hasMoreElements()); + }; - if (isExported()) - validate(maTempFile.GetFileName(), test::OOXML); + createSwDoc("fdo38244.docx"); + verify(); + saveAndReload(mpFilter); + verify(); + validate(maTempFile.GetFileName(), test::OOXML); } CPPUNIT_TEST_FIXTURE(Test, testCommentsNested) @@ -672,16 +682,16 @@ DECLARE_OOXMLEXPORT_TEST(testI120928, "i120928.docx") CPPUNIT_ASSERT(xBitmap.is()); } -DECLARE_OOXMLEXPORT_TEST(testFdo64826, "fdo64826.docx") +CPPUNIT_TEST_FIXTURE(Test, testFdo64826) { // 'Track-Changes' (Track Revisions) wasn't exported. + createSwDoc("fdo64826.docx"); + CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(mxComponent, u"RecordChanges"_ustr)); + saveAndReload(mpFilter); CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(mxComponent, u"RecordChanges"_ustr)); // 'Show-Changes' should not be exported - default is true. - if (isExported()) - { - xmlDocUniquePtr pXmlSettings = parseExport(u"word/settings.xml"_ustr); - assertXPath(pXmlSettings, "/w:settings/w:revisionView", 0); - } + xmlDocUniquePtr pXmlSettings = parseExport(u"word/settings.xml"_ustr); + assertXPath(pXmlSettings, "/w:settings/w:revisionView", 0); } DECLARE_OOXMLEXPORT_TEST(testPageBackground, "page-background.docx") @@ -810,17 +820,17 @@ DECLARE_OOXMLEXPORT_TEST(testFdo65400, "fdo65400.docx") CPPUNIT_ASSERT_EQUAL( sal_Int32( 0xd8d8d8 ), getProperty< sal_Int32 >( shaded, u"CharBackColor"_ustr )); } -DECLARE_OOXMLEXPORT_TEST(testFdo66543, "fdo66543.docx") +CPPUNIT_TEST_FIXTURE(Test, testFdo66543) { // The problem was that when importing DOCX with 'line numbers' - the 'start value' was imported // but nothing was done with it. + createSwDoc("fdo66543.docx"); - uno::Reference< text::XTextRange > paragraph1 = getParagraph( 1 ); CPPUNIT_ASSERT_EQUAL(sal_Int32(2), - getProperty<sal_Int32>(paragraph1, u"ParaLineNumberStartValue"_ustr)); - - if (!isExported()) - return; + getProperty<sal_Int32>(getParagraph( 1 ), u"ParaLineNumberStartValue"_ustr)); + saveAndReload(mpFilter); + CPPUNIT_ASSERT_EQUAL(sal_Int32(2), + getProperty<sal_Int32>(getParagraph( 1 ), u"ParaLineNumberStartValue"_ustr)); // ensure unnecessary suppressLineNumbers entry is not created. xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx index c61dd9041464..ff6d169ef39d 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx @@ -273,22 +273,27 @@ CPPUNIT_TEST_FIXTURE(Test, testCalendar1) assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tblPr/w:tblLook", "val", u"04a0"); } -DECLARE_OOXMLEXPORT_TEST(testCalendar2, "calendar2.docx") -{ - // Problem was that CharCaseMap was style::CaseMap::NONE. - uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY); - uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(style::CaseMap::UPPERCASE, getProperty<sal_Int16>(getRun(getParagraphOfText(1, xCell->getText()), 1), u"CharCaseMap"_ustr)); - // Font size in the second row was 11. - xCell.set(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()), 1), u"CharHeight"_ustr)); - // Font size in the third row was 11 as well. - xCell.set(xTable->getCellByName(u"B3"_ustr), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(14.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()), 1), u"CharHeight"_ustr)); +CPPUNIT_TEST_FIXTURE(Test, testCalendar2) +{ + auto verify = [this]() { + // Problem was that CharCaseMap was style::CaseMap::NONE. + uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY); + uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(style::CaseMap::UPPERCASE, getProperty<sal_Int16>(getRun(getParagraphOfText(1, xCell->getText()), 1), u"CharCaseMap"_ustr)); + // Font size in the second row was 11. + xCell.set(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(16.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()), 1), u"CharHeight"_ustr)); + // Font size in the third row was 11 as well. + xCell.set(xTable->getCellByName(u"B3"_ustr), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(14.f, getProperty<float>(getRun(getParagraphOfText(1, xCell->getText()), 1), u"CharHeight"_ustr)); + }; + + createSwDoc("calendar2.docx"); + verify(); + saveAndReload(mpFilter); + verify(); // This paragraph property was missing in table style. - if (!isExported()) - return; xmlDocUniquePtr pXmlStyles = parseExport(u"word/styles.xml"_ustr); assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='Calendar2']/w:pPr/w:jc", "val", u"center"); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx index ddfd73f15e93..60c65bd222f1 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport4.cxx @@ -37,28 +37,35 @@ protected: void verifyComboBoxExport(bool aComboBoxAsDropDown); }; -DECLARE_OOXMLEXPORT_TEST(testRelorientation, "relorientation.docx") -{ - uno::Reference<drawing::XShape> xShape = getShape(1); - // This was text::RelOrientation::FRAME, when handling relativeFrom=page, align=right - CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME, getProperty<sal_Int16>(xShape, u"HoriOrientRelation"_ustr)); - - uno::Reference<drawing::XShapes> xGroup(xShape, uno::UNO_QUERY); - // This resulted in lang::IndexOutOfBoundsException, as nested groupshapes weren't handled. - uno::Reference<drawing::XShapeDescriptor> xShapeDescriptor(xGroup->getByIndex(0), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(u"com.sun.star.drawing.GroupShape"_ustr, xShapeDescriptor->getShapeType()); - - // 'actual child size' = 'group ext' * 'child ext' / 'chExt from group', see section 'chExt' in - // [MS-OI29500]. Here for width from file 3108960 * 4896 / 4911 = 3099464 EMU. That corresponds to - // width 8.61cm and 325px in UI in Word and rounds down to 8609 Hmm. Considering scaling of the - // parent group to the anchor extent (* 3118485 / 3108960) we get a display width of 3108960 EMU - // = 8636Hmm. FIXME: Expected value is as in LO 7.2. Reason for difference is yet unknown. - if (isExported()) - { - uno::Reference<drawing::XShape> xYear(xGroup->getByIndex(1), uno::UNO_QUERY); - // This was 2, due to incorrect handling of parent transformations inside DML groupshapes. - CPPUNIT_ASSERT_EQUAL(sal_Int32(8662), xYear->getSize().Width); - } +CPPUNIT_TEST_FIXTURE(Test, testRelorientation) +{ + auto verify = [this](bool bIsExport = false) { + uno::Reference<drawing::XShape> xShape = getShape(1); + // This was text::RelOrientation::FRAME, when handling relativeFrom=page, align=right + CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME, getProperty<sal_Int16>(xShape, u"HoriOrientRelation"_ustr)); + + uno::Reference<drawing::XShapes> xGroup(xShape, uno::UNO_QUERY); + // This resulted in lang::IndexOutOfBoundsException, as nested groupshapes weren't handled. + uno::Reference<drawing::XShapeDescriptor> xShapeDescriptor(xGroup->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"com.sun.star.drawing.GroupShape"_ustr, xShapeDescriptor->getShapeType()); + + // 'actual child size' = 'group ext' * 'child ext' / 'chExt from group', see section 'chExt' in + // [MS-OI29500]. Here for width from file 3108960 * 4896 / 4911 = 3099464 EMU. That corresponds to + // width 8.61cm and 325px in UI in Word and rounds down to 8609 Hmm. Considering scaling of the + // parent group to the anchor extent (* 3118485 / 3108960) we get a display width of 3108960 EMU + // = 8636Hmm. FIXME: Expected value is as in LO 7.2. Reason for difference is yet unknown. + if (bIsExport) + { + uno::Reference<drawing::XShape> xYear(xGroup->getByIndex(1), uno::UNO_QUERY); + // This was 2, due to incorrect handling of parent transformations inside DML groupshapes. + CPPUNIT_ASSERT_EQUAL(sal_Int32(8662), xYear->getSize().Width); + } + }; + + createSwDoc("relorientation.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } CPPUNIT_TEST_FIXTURE(Test, testBezier) @@ -349,16 +356,14 @@ CPPUNIT_TEST_FIXTURE(Test, testFDO74215) } } -DECLARE_OOXMLEXPORT_TEST(testColumnBreak_ColumnCountIsZero,"fdo74153.docx") +CPPUNIT_TEST_FIXTURE(Test, testColumnBreak_ColumnCountIsZero) { /* fdo73545: Column Break with Column_count = 0 was not getting preserved. * The <w:br w:type="column" /> was missing after roundtrip */ - if (isExported()) - { - xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); - assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[1]/w:br", "type", u"column"); - } + loadAndSave("fdo74153.docx"); + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r[1]/w:br", "type", u"column"); //tdf76349 match Word's behavior of treating breaks in single columns as page breaks. CPPUNIT_ASSERT_EQUAL(2, getPages()); @@ -473,16 +478,21 @@ CPPUNIT_TEST_FIXTURE(Test, testAbi11739) CPPUNIT_ASSERT(getXPathPosition(pXmlDoc, "/w:styles/w:style[11]", "unhideWhenUsed") < getXPathPosition(pXmlDoc, "/w:styles/w:style[11]", "qFormat")); } -DECLARE_OOXMLEXPORT_TEST(testEmbeddedXlsx, "embedded-xlsx.docx") +CPPUNIT_TEST_FIXTURE(Test, testEmbeddedXlsx) { - // check there are two objects and they are FrameShapes - CPPUNIT_ASSERT_EQUAL(2, getShapes()); - CPPUNIT_ASSERT_EQUAL(u"FrameShape"_ustr, getShape(1)->getShapeType()); - CPPUNIT_ASSERT_EQUAL(u"FrameShape"_ustr, getShape(2)->getShapeType()); + auto verify = [this]() { + // check there are two objects and they are FrameShapes + CPPUNIT_ASSERT_EQUAL(2, getShapes()); + CPPUNIT_ASSERT_EQUAL(u"FrameShape"_ustr, getShape(1)->getShapeType()); + CPPUNIT_ASSERT_EQUAL(u"FrameShape"_ustr, getShape(2)->getShapeType()); + }; + + createSwDoc("embedded-xlsx.docx"); + verify(); + saveAndReload(mpFilter); + verify(); // check the objects are present in the exported document.xml - if (!isExported()) - return; xmlDocUniquePtr pXmlDocument = parseExport(u"word/document.xml"_ustr); assertXPath(pXmlDocument, "/w:document/w:body/w:p/w:r/w:object", 2); diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx index 2d73ab7adeb9..fa34635dd1ca 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport5.cxx @@ -121,46 +121,58 @@ CPPUNIT_TEST_FIXTURE(Test, testfdo79008) CPPUNIT_ASSERT(!pTextDoc->GetDocShell()->IsSecurityOptOpenReadOnly()); } -DECLARE_OOXMLEXPORT_TEST(testTdf120852_readOnlyProtection, "tdf120852_readOnlyProtection.docx") +CPPUNIT_TEST_FIXTURE(Test, testTdf120852_readOnlyProtection) { - if (isExported()) - { - xmlDocUniquePtr pXmlSettings = parseExport(u"word/settings.xml"_ustr); - assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "enforcement", u"1"); - assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "edit", u"readOnly"); - } - + createSwDoc("tdf120852_readOnlyProtection.docx"); // Read-only is set, so Enforcement must enable it. SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); CPPUNIT_ASSERT(pTextDoc->GetDocShell()->IsSecurityOptOpenReadOnly()); -} -DECLARE_OOXMLEXPORT_TEST(testTdf120852_readOnlyUnProtected, "tdf120852_readOnlyUnProtected.docx") -{ - // Readonly is not enforced, just a suggestion, - // so when a section is protected, the document should enable forms protection. - SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); + saveAndReload(mpFilter); + + pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); - CPPUNIT_ASSERT(!pTextDoc->GetDocShell()->IsSecurityOptOpenReadOnly()); + CPPUNIT_ASSERT(pTextDoc->GetDocShell()->IsSecurityOptOpenReadOnly()); - uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY_THROW); - uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY_THROW); - const sal_Int32 nLastSection = xSections->getCount() - 1; - uno::Reference<beans::XPropertySet> xSect(xSections->getByIndex(nLastSection), uno::UNO_QUERY_THROW); - if ( !isExported() ) - { - CPPUNIT_ASSERT_MESSAGE("Section is not protected", !getProperty<bool>(xSect, u"IsProtected"_ustr)); - // Enable section protection. The round-trip should have forms protection enabled. - xSect->setPropertyValue(u"IsProtected"_ustr, uno::Any(true)); - } - else - { - CPPUNIT_ASSERT_MESSAGE("Section is protected", getProperty<bool>(xSect, u"IsProtected"_ustr)); - xmlDocUniquePtr pXmlSettings = parseExport(u"word/settings.xml"_ustr); - assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "edit", u"forms"); - assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "enforcement", u"true"); - } + xmlDocUniquePtr pXmlSettings = parseExport(u"word/settings.xml"_ustr); + assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "enforcement", u"1"); + assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "edit", u"readOnly"); + +} + +CPPUNIT_TEST_FIXTURE(Test, testTdf120852_readOnlyUnProtected) +{ + auto verify = [this](bool bIsExport = false) { + // Readonly is not enforced, just a suggestion, + // so when a section is protected, the document should enable forms protection. + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + CPPUNIT_ASSERT(!pTextDoc->GetDocShell()->IsSecurityOptOpenReadOnly()); + + uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY_THROW); + uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY_THROW); + const sal_Int32 nLastSection = xSections->getCount() - 1; + uno::Reference<beans::XPropertySet> xSect(xSections->getByIndex(nLastSection), uno::UNO_QUERY_THROW); + if ( !bIsExport ) + { + CPPUNIT_ASSERT_MESSAGE("Section is not protected", !getProperty<bool>(xSect, u"IsProtected"_ustr)); + // Enable section protection. The round-trip should have forms protection enabled. + xSect->setPropertyValue(u"IsProtected"_ustr, uno::Any(true)); + } + else + { + CPPUNIT_ASSERT_MESSAGE("Section is protected", getProperty<bool>(xSect, u"IsProtected"_ustr)); + xmlDocUniquePtr pXmlSettings = parseExport(u"word/settings.xml"_ustr); + assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "edit", u"forms"); + assertXPath(pXmlSettings, "/w:settings/w:documentProtection", "enforcement", u"true"); + } + }; + + createSwDoc("tdf120852_readOnlyUnProtected.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } CPPUNIT_TEST_FIXTURE(Test, testAuthorPropertySdt) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx index c122868aa7dc..34478da70c54 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport6.cxx @@ -83,34 +83,41 @@ CPPUNIT_TEST_FIXTURE(Test, testDmlGroupshapeRelsize) assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/wp14:sizeRelH", "relativeFrom", u"margin"); } -DECLARE_OOXMLEXPORT_TEST(testDmlTextshape, "dml-textshape.docx") +CPPUNIT_TEST_FIXTURE(Test, testDmlTextshape) { - uno::Reference<container::XIndexAccess> xGroup(getShape(1), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(text::VertOrientation::TOP, getProperty<sal_Int16>(xGroup, u"VertOrient"_ustr)); - uno::Reference<drawing::XShape> xShape(xGroup->getByIndex(1), uno::UNO_QUERY); - // This was drawing::FillStyle_NONE. - CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape, u"FillStyle"_ustr)); - // This was drawing::LineStyle_NONE. - CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_SOLID, getProperty<drawing::LineStyle>(xShape, u"LineStyle"_ustr)); - - if (!isExported()) - return; - xmlDocUniquePtr pXmlDocument = parseExport(u"word/document.xml"_ustr); - // This was wrap="none". - assertXPath(pXmlDocument, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wpg:wgp/wps:wsp[2]/wps:bodyPr", "wrap", u"square"); - - xShape.set(xGroup->getByIndex(3), uno::UNO_QUERY); - OUString aType = comphelper::SequenceAsHashMap(getProperty<beans::PropertyValues>(xShape, u"CustomShapeGeometry"_ustr))[u"Type"_ustr].get<OUString>(); - CPPUNIT_ASSERT_EQUAL(u"ooxml-bentConnector3"_ustr, aType); - // Connector was incorrectly shifted towards the top left corner, X was 552, Y was 0. - // It is not a DML, but a VML shape. The whole group is shifted 3mm right and 6mm up. - // Values are as in LO7.2, original problem is still fixed. - CPPUNIT_ASSERT_EQUAL(sal_Int32(4016), xShape->getPosition().X); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-4485), xShape->getPosition().Y); + auto verify = [this](bool bIsExport = false) { + uno::Reference<container::XIndexAccess> xGroup(getShape(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(text::VertOrientation::TOP, getProperty<sal_Int16>(xGroup, u"VertOrient"_ustr)); + uno::Reference<drawing::XShape> xShape(xGroup->getByIndex(1), uno::UNO_QUERY); + // This was drawing::FillStyle_NONE. + CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xShape, u"FillStyle"_ustr)); + // This was drawing::LineStyle_NONE. + CPPUNIT_ASSERT_EQUAL(drawing::LineStyle_SOLID, getProperty<drawing::LineStyle>(xShape, u"LineStyle"_ustr)); + + if (!bIsExport) + return; + xmlDocUniquePtr pXmlDocument = parseExport(u"word/document.xml"_ustr); + // This was wrap="none". + assertXPath(pXmlDocument, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wpg:wgp/wps:wsp[2]/wps:bodyPr", "wrap", u"square"); + + xShape.set(xGroup->getByIndex(3), uno::UNO_QUERY); + OUString aType = comphelper::SequenceAsHashMap(getProperty<beans::PropertyValues>(xShape, u"CustomShapeGeometry"_ustr))[u"Type"_ustr].get<OUString>(); + CPPUNIT_ASSERT_EQUAL(u"ooxml-bentConnector3"_ustr, aType); + // Connector was incorrectly shifted towards the top left corner, X was 552, Y was 0. + // It is not a DML, but a VML shape. The whole group is shifted 3mm right and 6mm up. + // Values are as in LO7.2, original problem is still fixed. + CPPUNIT_ASSERT_EQUAL(sal_Int32(4016), xShape->getPosition().X); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-4485), xShape->getPosition().Y); + + xShape.set(xGroup->getByIndex(5), uno::UNO_QUERY); + // This was incorrectly shifted towards the top of the page, Y was 106. + CPPUNIT_ASSERT_EQUAL(sal_Int32(-4729), xShape->getPosition().Y); + }; - xShape.set(xGroup->getByIndex(5), uno::UNO_QUERY); - // This was incorrectly shifted towards the top of the page, Y was 106. - CPPUNIT_ASSERT_EQUAL(sal_Int32(-4729), xShape->getPosition().Y); + createSwDoc("dml-textshape.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } // testDmlTextshapeB was only made export-only because as an import-export test it failed for an unknown reason @@ -352,24 +359,31 @@ DECLARE_OOXMLEXPORT_TEST(testDMLShapeFillPattern, "dml-shape-fillpattern.docx") CPPUNIT_ASSERT_EQUAL(drawing::HatchStyle_DOUBLE, aHatch.Style); } -DECLARE_OOXMLEXPORT_TEST(testDMLGroupShapeChildPosition, "dml-groupshape-childposition.docx") +CPPUNIT_TEST_FIXTURE(Test, testDMLGroupShapeChildPosition) { - // Problem was parent transformation was ignored fully, but translate component - // which specify the position must be also applied for children of the group. - - uno::Reference<drawing::XShapes> xGroup(getShape(1), uno::UNO_QUERY); - uno::Reference<drawing::XShape> xChildGroup(xGroup->getByIndex(1), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-2123), xChildGroup->getPosition().X); - CPPUNIT_ASSERT_EQUAL(sal_Int32(11331), xChildGroup->getPosition().Y); - - xGroup.set(xChildGroup, uno::UNO_QUERY); - xChildGroup.set(xGroup->getByIndex(0), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-1859), xChildGroup->getPosition().X); - CPPUNIT_ASSERT_EQUAL(sal_Int32(11331), xChildGroup->getPosition().Y); - - xChildGroup.set(xGroup->getByIndex(1), uno::UNO_QUERY); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-2123), xChildGroup->getPosition().X); - CPPUNIT_ASSERT_EQUAL(sal_Int32(isExported() ? 14023 : 14021), xChildGroup->getPosition().Y); + auto verify = [this](bool bIsExport = false) { + // Problem was parent transformation was ignored fully, but translate component + // which specify the position must be also applied for children of the group. + + uno::Reference<drawing::XShapes> xGroup(getShape(1), uno::UNO_QUERY); + uno::Reference<drawing::XShape> xChildGroup(xGroup->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-2123), xChildGroup->getPosition().X); + CPPUNIT_ASSERT_EQUAL(sal_Int32(11331), xChildGroup->getPosition().Y); + + xGroup.set(xChildGroup, uno::UNO_QUERY); + xChildGroup.set(xGroup->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-1859), xChildGroup->getPosition().X); + CPPUNIT_ASSERT_EQUAL(sal_Int32(11331), xChildGroup->getPosition().Y); + + xChildGroup.set(xGroup->getByIndex(1), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-2123), xChildGroup->getPosition().X); + CPPUNIT_ASSERT_EQUAL(sal_Int32(bIsExport ? 14023 : 14021), xChildGroup->getPosition().Y); + }; + + createSwDoc("dml-groupshape-childposition.docx"); + verify(); + saveAndReload(mpFilter); + verify(/*bIsExport*/ true); } CPPUNIT_TEST_FIXTURE(Test, testDMLGradientFillTheme) @@ -456,18 +470,23 @@ DECLARE_OOXMLEXPORT_TEST(testDMLGroupShapeParaSpacing, "dml-groupshape-paraspaci // CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xRun, "ParaBottomMargin")); } -DECLARE_OOXMLEXPORT_TEST(testTableFloatingMargins, "table-floating-margins.docx") +CPPUNIT_TEST_FIXTURE(Test, testTableFloatingMargins) { - // In case the table had custom left cell margin, the horizontal position was still incorrect (too small, -199). - uno::Reference<beans::XPropertySet> xFrame(getShape(1), uno::UNO_QUERY); - sal_Int32 nHoriOrientPosition = getProperty<sal_Int32>(xFrame, u"HoriOrientPosition"_ustr); - CPPUNIT_ASSERT(nHoriOrientPosition < sal_Int32(-495)); - // These were 0 as well, due to lack of import. - CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), getProperty<sal_Int32>(xFrame, u"TopMargin"_ustr)); - CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty<sal_Int32>(xFrame, u"BottomMargin"_ustr)); - - if (!isExported()) - return; + auto verify = [this]() { -e ... etc. - the rest is truncated