/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class Test : public SwModelTestBase { public: Test() : SwModelTestBase("/sw/qa/extras/odfexport/data/", "writer8") {} }; CPPUNIT_TEST_FIXTURE(Test, testEmbeddedFontProps) { loadAndReload("embedded-font-props.odt"); CPPUNIT_ASSERT_EQUAL(1, getPages()); #if !defined(MACOSX) // Test that font style/weight of embedded fonts is exposed. // Test file is a normal ODT, except EmbedFonts is set to true in settings.xml. xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); // These failed, the attributes were missing. assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[1]"_ostr, "font-style"_ostr, "normal"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[1]"_ostr, "font-weight"_ostr, "normal"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[2]"_ostr, "font-style"_ostr, "normal"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[2]"_ostr, "font-weight"_ostr, "bold"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[3]"_ostr, "font-style"_ostr, "italic"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[3]"_ostr, "font-weight"_ostr, "normal"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[4]"_ostr, "font-style"_ostr, "italic"); assertXPath(pXmlDoc, "//style:font-face[@style:name='Liberation Serif']/svg:font-face-src/svg:font-face-uri[4]"_ostr, "font-weight"_ostr, "bold"); #endif } DECLARE_ODFEXPORT_TEST(testTdf100492, "tdf100492.odt") { CPPUNIT_ASSERT_EQUAL(2, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xShape = getShape(1); CPPUNIT_ASSERT(xShape.is()); // Save the first shape to a SVG uno::Reference xGraphicExporter = drawing::GraphicExportFilter::create(comphelper::getProcessComponentContext()); uno::Reference xSourceDoc(xShape, uno::UNO_QUERY); xGraphicExporter->setSourceDocument(xSourceDoc); SvMemoryStream aStream; uno::Reference xOutputStream(new utl::OStreamWrapper(aStream)); uno::Sequence aDescriptor( comphelper::InitPropertySequence({ { "OutputStream", uno::Any(xOutputStream) }, { "FilterName", uno::Any(OUString("SVG")) } })); xGraphicExporter->filter(aDescriptor); aStream.Seek(STREAM_SEEK_TO_BEGIN); // TODO: Disabled. Parsing of SVG gives just root node without any children. // Reason of such behavior unclear. So XPATH assert fails. // Parse resulting SVG as XML file. // xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream); // Check amount of paths required to draw an arrow. // Since there are still some empty paths in output test can fail later. There are just two // really used and visible paths. //assertXPath(pXmlDoc, "/svg/path", 4); } DECLARE_ODFEXPORT_TEST(testTdf77961, "tdf77961.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xStyles(getStyles("PageStyles")); uno::Reference xStyle(xStyles->getByName("Standard"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL( false , getProperty(xStyle, "GridDisplay")); CPPUNIT_ASSERT_EQUAL( false , getProperty(xStyle, "GridPrint")); } DECLARE_ODFEXPORT_TEST(testReferenceLanguage, "referencelanguage.odt") { CPPUNIT_ASSERT_EQUAL(2, getPages()); // Test loext:reference-language attribute of reference fields // (used from LibreOffice 6.1, and proposed for next ODF) OUString const aFieldTexts[] = { "A 2", "Az Isten", "Az 50-esek", "A 2018-asok", "Az egyebek", "A fejezetek", u"Az „Őseinket...”"_ustr, "a 2", "Az v", "az 1", "Az e)", "az 1", "Az (5)", "az 1", "A 2", "az 1" }; uno::Reference xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); // update "A (4)" to "Az (5)" uno::Reference(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY_THROW)->refresh(); uno::Reference xFieldsAccess(xTextFieldsSupplier->getTextFields()); uno::Reference xFields(xFieldsAccess->createEnumeration()); uno::Any aHu(OUString("Hu")); uno::Any ahu(OUString("hu")); for (auto const& sFieldText : aFieldTexts) { uno::Any aField = xFields->nextElement(); uno::Reference xServiceInfo(aField, uno::UNO_QUERY); if (xServiceInfo->supportsService("com.sun.star.text.textfield.GetReference")) { uno::Reference xPropertySet(aField, uno::UNO_QUERY); uno::Any aLang = xPropertySet->getPropertyValue("ReferenceFieldLanguage"); CPPUNIT_ASSERT_EQUAL(true, aLang == aHu || aLang == ahu); uno::Reference xField(aField, uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(sFieldText, xField->getAnchor()->getString()); } } } CPPUNIT_TEST_FIXTURE(Test, testRubyPosition) { loadAndReload("ruby-position.odt"); CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); assertXPath(pXmlDoc, "//style:style[@style:family='ruby']/style:ruby-properties[@loext:ruby-position='inter-character']"_ostr, 1); assertXPath(pXmlDoc, "//style:style[@style:family='ruby']/style:ruby-properties[@style:ruby-position='below']"_ostr, 1); } DECLARE_ODFEXPORT_TEST(testAllowOverlap, "allow-overlap.odt") { CPPUNIT_ASSERT_EQUAL(2, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xShape = getShape(1); // Without the accompanying fix in place, this test would have failed with: // - Expression: !getProperty(xShape, "AllowOverlap") // i.e. the custom AllowOverlap=false shape property was lost on import/export. CPPUNIT_ASSERT(!getProperty(xShape, "AllowOverlap")); xShape = getShape(2); CPPUNIT_ASSERT(!getProperty(xShape, "AllowOverlap")); } CPPUNIT_TEST_FIXTURE(Test, testSignatureLineProperties) { loadAndReload("signatureline-properties.fodt"); uno::Reference xShape = getShape(1); CPPUNIT_ASSERT(xShape.is()); CPPUNIT_ASSERT_EQUAL(true, getProperty(xShape, "IsSignatureLine")); CPPUNIT_ASSERT_EQUAL(OUString("{3C24159B-3B98-4F60-AB52-00E7721758E9}"), getProperty(xShape, "SignatureLineId")); CPPUNIT_ASSERT_EQUAL(OUString("John Doe"), getProperty(xShape, "SignatureLineSuggestedSignerName")); CPPUNIT_ASSERT_EQUAL(OUString("Farmer"), getProperty(xShape, "SignatureLineSuggestedSignerTitle")); CPPUNIT_ASSERT_EQUAL(OUString("john@farmers.org"), getProperty(xShape, "SignatureLineSuggestedSignerEmail")); CPPUNIT_ASSERT_EQUAL(OUString("Please farm here."), getProperty(xShape, "SignatureLineSigningInstructions")); CPPUNIT_ASSERT_EQUAL(true, getProperty(xShape, "SignatureLineCanAddComment")); CPPUNIT_ASSERT_EQUAL(true, getProperty(xShape, "SignatureLineShowSignDate")); // tdf#130917 This needs to be always set when importing a doc, ooxml export expects it. uno::Reference xUnsignedGraphic; uno::Reference xProps(xShape, uno::UNO_QUERY); xProps->getPropertyValue("SignatureLineUnsignedImage") >>= xUnsignedGraphic; CPPUNIT_ASSERT_EQUAL(true, xUnsignedGraphic.is()); } DECLARE_ODFEXPORT_TEST(testQrCodeGenProperties, "qrcode-properties.odt") { CPPUNIT_ASSERT_EQUAL(1, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xShape = getShape(1); CPPUNIT_ASSERT(xShape.is()); css::drawing::BarCode aBarCode = getProperty(xShape, "BarCodeProperties"); CPPUNIT_ASSERT_EQUAL(OUString("www.libreoffice.org"), aBarCode.Payload); CPPUNIT_ASSERT_EQUAL(css::drawing::BarCodeErrorCorrection::LOW, aBarCode.ErrorCorrection); CPPUNIT_ASSERT_EQUAL(sal_Int32(5), aBarCode.Border); } DECLARE_ODFEXPORT_TEST(testChapterNumberingNewLine, "chapter-number-new-line.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xNumberingSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xNumberingRules = xNumberingSupplier->getChapterNumberingRules(); comphelper::SequenceAsHashMap hashMap(xNumberingRules->getByIndex(0)); //This failed Actual Value was LISTTAB instead of NEWLINE CPPUNIT_ASSERT_EQUAL( sal_Int16(SvxNumberFormat::NEWLINE), hashMap["LabelFollowedBy"].get()); } DECLARE_ODFEXPORT_TEST(testSpellOutNumberingTypes, "spellout-numberingtypes.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); // ordinal indicator, ordinal and cardinal number numbering styles (from LibreOffice 6.1) OUString const aFieldTexts[] = { "1st", "Erste", "Eins", "1.", "Premier", "Un", u"1ᵉʳ"_ustr, "First", "One" }; // fallback for old platforms without std::codecvt and std::regex supports OUString const aFieldTextFallbacks[] = { "Ordinal-number 1", "Ordinal 1", "1" }; uno::Reference xTextFieldsSupplier(mxComponent, uno::UNO_QUERY); // update text field content uno::Reference(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY_THROW)->refresh(); uno::Reference xFieldsAccess(xTextFieldsSupplier->getTextFields()); uno::Reference xFields(xFieldsAccess->createEnumeration()); for (size_t i = 0; i < SAL_N_ELEMENTS(aFieldTexts); i++) { uno::Any aField = xFields->nextElement(); uno::Reference xServiceInfo(aField, uno::UNO_QUERY); if (xServiceInfo->supportsService("com.sun.star.text.textfield.PageNumber")) { uno::Reference xField(aField, uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(true, aFieldTexts[i].equals(xField->getAnchor()->getString()) || aFieldTextFallbacks[i%3].equals(xField->getAnchor()->getString())); } } } DECLARE_ODFEXPORT_TEST(tdf133507_contextualSpacingSection, "tdf133507_contextualSpacingSection.odt") { // Previously this was one page (no UL spacing) or three pages (every para had spacing) CPPUNIT_ASSERT_EQUAL(2, getPages()); } // MAILMERGE Add conditional to expand / collapse bookmarks DECLARE_ODFEXPORT_TEST(tdf101856_overlapped, "tdf101856_overlapped.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); // get bookmark interface uno::Reference xBookmarksSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY); uno::Reference xBookmarksByName = xBookmarksSupplier->getBookmarks(); // check: we have 2 bookmarks CPPUNIT_ASSERT_EQUAL(static_cast(2), xBookmarksByIdx->getCount()); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkNonHidden")); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkHidden")); // uno::Reference xBookmark1(xBookmarksByName->getByName("BookmarkNonHidden"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty(xBookmark1, UNO_NAME_BOOKMARK_CONDITION)); CPPUNIT_ASSERT_EQUAL(false, getProperty(xBookmark1, UNO_NAME_BOOKMARK_HIDDEN)); // uno::Reference xBookmark2(xBookmarksByName->getByName("BookmarkHidden"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty(xBookmark2, UNO_NAME_BOOKMARK_CONDITION)); CPPUNIT_ASSERT_EQUAL(true, getProperty(xBookmark2, UNO_NAME_BOOKMARK_HIDDEN)); } // MAILMERGE Add conditional to expand / collapse bookmarks DECLARE_ODFEXPORT_TEST(tdf101856, "tdf101856.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); // get bookmark interface uno::Reference xBookmarksSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY); uno::Reference xBookmarksByName = xBookmarksSupplier->getBookmarks(); // check: we have 2 bookmarks CPPUNIT_ASSERT_EQUAL(static_cast(5), xBookmarksByIdx->getCount()); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkVisible")); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkHidden")); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkVisibleWithCondition")); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkNotHiddenWithCondition")); CPPUNIT_ASSERT(xBookmarksByName->hasByName("BookmarkHiddenWithCondition")); // uno::Reference xBookmark1(xBookmarksByName->getByName("BookmarkVisible"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty(xBookmark1, UNO_NAME_BOOKMARK_CONDITION)); CPPUNIT_ASSERT_EQUAL(false, getProperty(xBookmark1, UNO_NAME_BOOKMARK_HIDDEN)); // uno::Reference xBookmark2(xBookmarksByName->getByName("BookmarkHidden"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty(xBookmark2, UNO_NAME_BOOKMARK_CONDITION)); CPPUNIT_ASSERT_EQUAL(true, getProperty(xBookmark2, UNO_NAME_BOOKMARK_HIDDEN)); // uno::Reference xBookmark3(xBookmarksByName->getByName("BookmarkVisibleWithCondition"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("0==1"), getProperty(xBookmark3, UNO_NAME_BOOKMARK_CONDITION)); CPPUNIT_ASSERT_EQUAL(true, getProperty(xBookmark3, UNO_NAME_BOOKMARK_HIDDEN)); // // // The following test doesn't work, while during output in the case of loext:hidden="false". // no additional parameters are written. Implementation should be reviewed. // // uno::Reference xBookmark4(xBookmarksByName->getByName("BookmarkNotHiddenWithCondition"), uno::UNO_QUERY); // CPPUNIT_ASSERT_EQUAL(OUString("1==1"), getProperty(xBookmark4, UNO_NAME_BOOKMARK_CONDITION)); // CPPUNIT_ASSERT_EQUAL(false, getProperty(xBookmark4, UNO_NAME_BOOKMARK_HIDDEN)); // uno::Reference xBookmark5(xBookmarksByName->getByName("BookmarkHiddenWithCondition"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("1==1"), getProperty(xBookmark5, UNO_NAME_BOOKMARK_CONDITION)); CPPUNIT_ASSERT_EQUAL(true, getProperty(xBookmark5, UNO_NAME_BOOKMARK_HIDDEN)); } DECLARE_ODFEXPORT_TEST(tdf118502, "tdf118502.odt") { CPPUNIT_ASSERT_EQUAL(1, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xShape = getShape(1); // Make sure the replacement graphic is still there // (was gone because the original graphic was not recognized during load) auto xReplacementGraphic = getProperty>(xShape, "ReplacementGraphic"); CPPUNIT_ASSERT(xReplacementGraphic.is()); } CPPUNIT_TEST_FIXTURE(Test, tdf99631) { loadAndReload("tdf99631.docx"); // check import of VisualArea settings of the embedded XLSX OLE objects xmlDocUniquePtr pXmlDoc = parseExport("Object 1/settings.xml"); assertXPathContent(pXmlDoc, "//config:config-item[@config:name='VisibleAreaWidth']"_ostr, "4516"); assertXPathContent(pXmlDoc, "//config:config-item[@config:name='VisibleAreaHeight']"_ostr, "903"); xmlDocUniquePtr pXmlDoc2 = parseExport("Object 2/settings.xml"); assertXPathContent(pXmlDoc2, "//config:config-item[@config:name='VisibleAreaWidth']"_ostr, "4516"); assertXPathContent(pXmlDoc2, "//config:config-item[@config:name='VisibleAreaHeight']"_ostr, "1355"); } CPPUNIT_TEST_FIXTURE(Test, tdf145871) { loadAndReload("tdf145871.odt"); uno::Reference xTablesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY); uno::Reference xTextTable(xTables->getByIndex(0), uno::UNO_QUERY); uno::Reference xTableRows = xTextTable->getRows(); // Without the fix in place, this test would have failed with // - Expected: 3150 // - Actual : 5851 CPPUNIT_ASSERT_EQUAL(sal_Int64(3150) , getProperty(xTableRows->getByIndex(0), "Height")); } CPPUNIT_TEST_FIXTURE(Test, tdf128504) { loadAndReload("tdf128504.docx"); uno::Reference xPara = getParagraph(6); uno::Reference xRun(getRun(xPara,1), uno::UNO_QUERY); OUString unVisitedStyleName = getProperty(xRun, "UnvisitedCharStyleName"); CPPUNIT_ASSERT(!unVisitedStyleName.equalsIgnoreAsciiCase("Internet Link")); OUString visitedStyleName = getProperty(xRun, "VisitedCharStyleName"); CPPUNIT_ASSERT(!visitedStyleName.equalsIgnoreAsciiCase("Visited Internet Link")); } DECLARE_ODFEXPORT_TEST(tdf121658, "tdf121658.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xParaStyles(getStyles("ParagraphStyles")); uno::Reference xStyle1(xParaStyles->getByName( "Standard"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(true, getProperty(xStyle1, "ParaHyphenationNoCaps")); } DECLARE_ODFEXPORT_TEST(tdf149248, "tdf149248.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); CPPUNIT_ASSERT_EQUAL(false, getProperty(getParagraph(2), "ParaHyphenationNoLastWord")); CPPUNIT_ASSERT_EQUAL(true, getProperty(getParagraph(4), "ParaHyphenationNoLastWord")); } DECLARE_ODFEXPORT_TEST(testThemeCrash, "tdf156905.odt") { // first it started to crash at import time, later at export time CPPUNIT_ASSERT_EQUAL(4, getPages()); } DECLARE_ODFEXPORT_TEST(testTdf150394, "tdf150394.odt") { // crashes at import time CPPUNIT_ASSERT_EQUAL(1, getPages()); } DECLARE_ODFEXPORT_TEST(tdf149324, "tdf149324.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), getProperty(getParagraph(2), "ParaHyphenationMinWordLength")); CPPUNIT_ASSERT_EQUAL(sal_uInt16(7), getProperty(getParagraph(4), "ParaHyphenationMinWordLength")); } DECLARE_ODFEXPORT_TEST(tdf149420, "tdf149420.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), getProperty(getParagraph(2), "ParaHyphenationZone")); CPPUNIT_ASSERT_EQUAL(sal_uInt16(567), getProperty(getParagraph(4), "ParaHyphenationZone")); } DECLARE_ODFEXPORT_TEST(testArabicZeroNumbering, "arabic-zero-numbering.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); auto xNumberingRules = getProperty>(getParagraph(1), "NumberingRules"); comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0)); // Without the accompanying fix in place, this test would have failed with: // - Expected: 64 // - Actual : 4 // i.e. numbering type was ARABIC, not ARABIC_ZERO. CPPUNIT_ASSERT_EQUAL(o3tl::narrowing(style::NumberingType::ARABIC_ZERO), aMap["NumberingType"].get()); } DECLARE_ODFEXPORT_TEST(testArabicZero3Numbering, "arabic-zero3-numbering.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); auto xNumberingRules = getProperty>(getParagraph(1), "NumberingRules"); comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0)); // Without the accompanying fix in place, this test would have failed with: // - Expected: 65 // - Actual : 4 // i.e. numbering type was ARABIC, not ARABIC_ZERO3. CPPUNIT_ASSERT_EQUAL(o3tl::narrowing(style::NumberingType::ARABIC_ZERO3), aMap["NumberingType"].get()); } DECLARE_ODFEXPORT_TEST(testArabicZero4Numbering, "arabic-zero4-numbering.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); auto xNumberingRules = getProperty>(getParagraph(1), "NumberingRules"); comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0)); // Without the accompanying fix in place, this test would have failed with: // - Expected: 66 // - Actual : 4 // i.e. numbering type was ARABIC, not ARABIC_ZERO4. CPPUNIT_ASSERT_EQUAL(o3tl::narrowing(style::NumberingType::ARABIC_ZERO4), aMap["NumberingType"].get()); } DECLARE_ODFEXPORT_TEST(testArabicZero5Numbering, "arabic-zero5-numbering.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); auto xNumberingRules = getProperty>(getParagraph(1), "NumberingRules"); comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0)); // Without the accompanying fix in place, this test would have failed with: // - Expected: 67 // - Actual : 4 // i.e. numbering type was ARABIC, not ARABIC_ZERO5. CPPUNIT_ASSERT_EQUAL(o3tl::narrowing(style::NumberingType::ARABIC_ZERO5), aMap["NumberingType"].get()); } DECLARE_ODFEXPORT_TEST(testRovasNumbering, "rovas-numbering.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); auto xNumberingRules = getProperty>(getParagraph(1), "NumberingRules"); comphelper::SequenceAsHashMap aMap(xNumberingRules->getByIndex(0)); // Without the accompanying fix in place, this test would have failed with: // - Expected: 68 // - Actual : 4 // i.e. numbering type was ARABIC, not SZEKELY_ROVAS. CPPUNIT_ASSERT_EQUAL(o3tl::narrowing(style::NumberingType::SZEKELY_ROVAS), aMap["NumberingType"].get()); } DECLARE_ODFEXPORT_TEST(testPageContentTop, "page-content-top.odt") { CPPUNIT_ASSERT_EQUAL(1, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xShape(getShape(1), uno::UNO_QUERY); sal_Int16 nExpected = text::RelOrientation::PAGE_PRINT_AREA_TOP; CPPUNIT_ASSERT_EQUAL(nExpected, getProperty(xShape, "VertOrientRelation")); } DECLARE_ODFEXPORT_TEST(testPageContentBottom, "page-content-bottom.odt") { CPPUNIT_ASSERT_EQUAL(1, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xShape(getShape(1), uno::UNO_QUERY); sal_Int16 nExpected = text::RelOrientation::PAGE_PRINT_AREA_BOTTOM; CPPUNIT_ASSERT_EQUAL(nExpected, getProperty(xShape, "VertOrientRelation")); } CPPUNIT_TEST_FIXTURE(Test, tdf124470) { loadAndReload("tdf124470TableAndEmbeddedUsedFonts.odt"); // Table styles were exported out of place, inside font-face-decls. // Without the fix in place, this will fail already in ODF validation: // "content.xml[2,2150]: Error: tag name "style:style" is not allowed. Possible tag names are: " CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); assertXPath(pXmlDoc, "/office:document-content/office:font-face-decls/style:style"_ostr, 0); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:family='table']"_ostr, 1); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:family='table-column']"_ostr, 2); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:family='paragraph']"_ostr, 1); } CPPUNIT_TEST_FIXTURE(Test, tdf135942) { loadAndReload("nestedTableInFooter.odt"); // All table autostyles should be collected, including nested, and must not crash. CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseExport("styles.xml"); assertXPath(pXmlDoc, "/office:document-styles/office:automatic-styles/style:style[@style:family='table']"_ostr, 2); } CPPUNIT_TEST_FIXTURE(Test, tdf150927) { // Similar to tdf135942 loadAndReload("table-in-frame-in-table-in-header-base.odt"); // All table autostyles should be collected, including nested, and must not crash. CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseExport("styles.xml"); assertXPath(pXmlDoc, "/office:document-styles/office:automatic-styles/style:style[@style:family='table']"_ostr, 2); } CPPUNIT_TEST_FIXTURE(Test, tdf151100) { // Similar to tdf135942 loadAndReload("tdf151100.docx"); // All table autostyles should be collected, including nested, and must not crash. CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseExport("styles.xml"); assertXPath(pXmlDoc, "/office:document-styles/office:automatic-styles/style:style[@style:family='table']"_ostr, 1); } DECLARE_ODFEXPORT_TEST(testGutterLeft, "gutter-left.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); uno::Reference xPageStyle; getStyles("PageStyles")->getByName("Standard") >>= xPageStyle; sal_Int32 nGutterMargin{}; xPageStyle->getPropertyValue("GutterMargin") >>= nGutterMargin; // Without the accompanying fix in place, this test would have failed with: // - Expected: 1270 // - Actual : 0 // i.e. gutter margin was lost. CPPUNIT_ASSERT_EQUAL(static_cast(1270), nGutterMargin); } DECLARE_ODFEXPORT_TEST(testTdf52065_centerTabs, "testTdf52065_centerTabs.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); sal_Int32 nTabStop = parseDump("//body/txt[4]/SwParaPortion/SwLineLayout/child::*[3]"_ostr, "width"_ostr).toInt32(); // Without the fix, the text was unseen, with a tabstop width of 64057. It should be 3057 CPPUNIT_ASSERT(nTabStop < 4000); CPPUNIT_ASSERT(3000 < nTabStop); CPPUNIT_ASSERT_EQUAL(u"Pečiatka zamestnávateľa"_ustr, parseDump("//body/txt[4]/SwParaPortion/SwLineLayout/child::*[4]"_ostr, "portion"_ostr)); // tdf#149547: __XXX___invalid CharacterStyles should not be imported/exported CPPUNIT_ASSERT(!getStyles("CharacterStyles")->hasByName("__XXX___invalid")); } DECLARE_ODFEXPORT_TEST(testTdf104254_noHeaderWrapping, "tdf104254_noHeaderWrapping.odt") { CPPUNIT_ASSERT_EQUAL(1, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseLayoutDump(); sal_Int32 nParaHeight = getXPath(pXmlDoc, "//header/txt[1]/infos/bounds"_ostr, "height"_ostr).toInt32(); // The wrapping on header images is supposed to be ignored (since OOo for MS compat reasons), // thus making the text run underneath the image. Before, height was 1104. Now it is 552. CPPUNIT_ASSERT_MESSAGE("Paragraph should fit on a single line", nParaHeight < 600); } DECLARE_ODFEXPORT_TEST(testTdf131025_noZerosInTable, "tdf131025_noZerosInTable.odt") { uno::Reference xSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xTables = xSupplier->getTextTables(); uno::Reference xTable(xTables->getByName("Table1"), uno::UNO_QUERY); uno::Reference xCell(xTable->getCellByName("C3"), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("5 gp"), xCell->getString()); } DECLARE_ODFEXPORT_TEST(testTdf153090, "Custom-Style-TOC.docx") { uno::Reference xIndexSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xIndexes(xIndexSupplier->getDocumentIndexes()); uno::Reference xTOC(xIndexes->getByIndex(0), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("_CustomImageCaption"), getProperty(xTOC, "CreateFromParagraphStyle")); // tdf#153659 this was imported as "table of figures" instead of "Figure Index 1" // thus custom settings were not retained after ToF update CPPUNIT_ASSERT_EQUAL(OUString("Figure Index 1"), getProperty(getParagraph(1), "ParaStyleName")); xTOC->update(); OUString const tocContent(xTOC->getAnchor()->getString()); CPPUNIT_ASSERT(tocContent.indexOf("1. Abb. Ein Haus") != -1); CPPUNIT_ASSERT(tocContent.indexOf("2. Abb.Ein Schiff!") != -1); CPPUNIT_ASSERT(tocContent.indexOf(u"1. ábra Small house with Hungarian description category") != -1); } DECLARE_ODFEXPORT_TEST(testTdf143793_noBodyWrapping, "tdf143793_noBodyWrapping.odt") { CPPUNIT_ASSERT_EQUAL(2, getShapes()); // Preserve old document wrapping. Compat "Use OOo 1.1 text wrapping around objects" // Originally, the body text did not wrap around spill-over header images CPPUNIT_ASSERT_EQUAL_MESSAGE( "Fits on one page", 1, getPages() ); xmlDocUniquePtr pXmlDoc = parseLayoutDump(); sal_Int32 nParaHeight = getXPath(pXmlDoc, "//page[1]/header/txt[1]/infos/bounds"_ostr, "height"_ostr).toInt32(); // The header text should wrap around the header image in OOo 1.1 and prior, // thus taking up two lines instead of one. One line is 276. It should be 552. CPPUNIT_ASSERT_MESSAGE("Header text should fill two lines", nParaHeight > 400); } CPPUNIT_TEST_FIXTURE(Test, testTdf137199) { loadAndReload("tdf137199.docx"); CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty(getParagraph(1), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString("1)"), getProperty(getParagraph(2), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString("HELLO1WORLD!"), getProperty(getParagraph(3), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString("HELLO2WORLD!"), getProperty(getParagraph(4), "ListLabelString")); } DECLARE_ODFEXPORT_TEST(testTdf143605, "tdf143605.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); // With numbering type "none" there should be just prefix & suffix CPPUNIT_ASSERT_EQUAL(OUString("."), getProperty(getParagraph(1), "ListLabelString")); } CPPUNIT_TEST_FIXTURE(Test, testTdf57317_autoListName) { createSwDoc("tdf57317_autoListName.odt"); // The list style (from styles.xml) overrides a duplicate named auto-style //uno::Any aNumStyle = getStyles("NumberingStyles")->getByName("L1"); //CPPUNIT_ASSERT(aNumStyle.hasValue()); uno::Reference xPara(getParagraph(1), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty(xPara, "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString("L1"), getProperty(xPara, "NumberingStyleName")); dispatchCommand(mxComponent, ".uno:SelectAll", {}); dispatchCommand(mxComponent, ".uno:DefaultBullet", {}); // This was failing with a duplicate auto numbering style name of L1 instead of a unique name, // thus it was showing the same info as before the bullet modification. saveAndReload("writer8"); xPara.set(getParagraph(1), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty(xPara, "ListLabelString")); uno::Reference xLevels(xPara->getPropertyValue("NumberingRules"), uno::UNO_QUERY); uno::Sequence aProps; xLevels->getByIndex(0) >>= aProps; for (beans::PropertyValue const& rProp : std::as_const(aProps)) { if (rProp.Name == "BulletChar") return; } CPPUNIT_FAIL("no BulletChar property"); } CPPUNIT_TEST_FIXTURE(Test, testListFormatDocx) { loadAndReload("listformat.docx"); // Ensure in resulting ODT we also have not just prefix/suffix, but custom delimiters CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty(getParagraph(1), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString(">>1/1<<"), getProperty(getParagraph(2), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString(">>1/1/1<<"), getProperty(getParagraph(3), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString(">>1/1/2<<"), getProperty(getParagraph(4), "ListLabelString")); // Check also that in numbering styles we have num-list-format defined xmlDocUniquePtr pXmlDoc = parseExport("styles.xml"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='1']"_ostr, "num-list-format"_ostr, ">%1%<"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='2']"_ostr, "num-list-format"_ostr, ">>%1%/%2%<<"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='3']"_ostr, "num-list-format"_ostr, ">>%1%/%2%/%3%<<"); // But for compatibility there are still prefix/suffix assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='1']"_ostr, "num-prefix"_ostr, ">"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='1']"_ostr, "num-suffix"_ostr, "<"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='2']"_ostr, "num-prefix"_ostr, ">>"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='2']"_ostr, "num-suffix"_ostr, "<<"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='3']"_ostr, "num-prefix"_ostr, ">>"); assertXPath(pXmlDoc, "/office:document-styles/office:styles/text:list-style[@style:name='WWNum1']/" "text:list-level-style-number[@text:level='3']"_ostr, "num-suffix"_ostr, "<<"); } DECLARE_ODFEXPORT_TEST(testShapeWithHyperlink, "shape-with-hyperlink.odt") { CPPUNIT_ASSERT_EQUAL(1, getShapes()); CPPUNIT_ASSERT_EQUAL(1, getPages()); if (isExported()) { xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); // Check how conversion from prefix/suffix to list format did work assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p/draw:a"_ostr, "href"_ostr, "http://shape.com/"); } } DECLARE_ODFEXPORT_TEST(testShapesHyperlink, "shapes-hyperlink.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); CPPUNIT_ASSERT_EQUAL(5, getShapes()); uno::Reference const xPropSet1(getShape(1), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice.org/"), getProperty(xPropSet1, "Hyperlink")); uno::Reference const xPropSet2(getShape(2), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice2.org/"), getProperty(xPropSet2, "Hyperlink")); uno::Reference const xPropSet3(getShape(3), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice3.org/"), getProperty(xPropSet3, "Hyperlink")); uno::Reference const xPropSet4(getShape(4), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice4.org/"), getProperty(xPropSet4, "Hyperlink")); uno::Reference const xPropSet5(getShape(5), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice5.org/"), getProperty(xPropSet5, "Hyperlink")); } DECLARE_ODFEXPORT_TEST(testListFormatOdt, "listformat.odt") { CPPUNIT_ASSERT_EQUAL(1, getPages()); // Ensure in resulting ODT we also have not just prefix/suffix, but custom delimiters CPPUNIT_ASSERT_EQUAL(OUString(">1<"), getProperty(getParagraph(1), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString(">>1.1<<"), getProperty(getParagraph(2), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString(">>1.1.1<<"), getProperty(getParagraph(3), "ListLabelString")); CPPUNIT_ASSERT_EQUAL(OUString(">>1.1.2<<"), getProperty(getParagraph(4), "ListLabelString")); if (isExported()) { xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); // Check how conversion from prefix/suffix to list format did work assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='1']"_ostr, "num-list-format"_ostr, ">%1%<"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='2']"_ostr, "num-list-format"_ostr, ">>%1%.%2%<<"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='3']"_ostr, "num-list-format"_ostr, ">>%1%.%2%.%3%<<"); // But for compatibility there are still prefix/suffix as they were before assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='1']"_ostr, "num-prefix"_ostr, ">"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='1']"_ostr, "num-suffix"_ostr, "<"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='2']"_ostr, "num-prefix"_ostr, ">>"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='2']"_ostr, "num-suffix"_ostr, "<<"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='3']"_ostr, "num-prefix"_ostr, ">>"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/text:list-style[@style:name='L1']/" "text:list-level-style-number[@text:level='3']"_ostr, "num-suffix"_ostr, "<<"); } } CPPUNIT_TEST_FIXTURE(Test, testStyleLink) { // Given a document with a para and a char style that links each other, when loading that // document: createSwDoc("style-link.fodt"); // Then make sure the char style links the para one: uno::Any aCharStyle = getStyles("CharacterStyles")->getByName("List Paragraph Char"); // Without the accompanying fix in place, this test would have failed with: // - Expected: List Paragraph // - Actual : // i.e. the linked style was lost on import. CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph"), getProperty(aCharStyle, "LinkStyle")); uno::Any aParaStyle = getStyles("ParagraphStyles")->getByName("List Paragraph"); // Without the accompanying fix in place, this test would have failed with: // - Expected: List Paragraph Char // - Actual : // i.e. the linked style was lost on import. CPPUNIT_ASSERT_EQUAL(OUString("List Paragraph Char"), getProperty(aParaStyle, "LinkStyle")); } CPPUNIT_TEST_FIXTURE(Test, tdf120972) { loadAndReload("table_number_format_3.docx"); xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); OUString cDecimal(SvtSysLocale().GetLocaleData().getNumDecimalSep()[0]); assertXPath( pXmlDoc, "//style:style[@style:name='P1']/style:paragraph-properties/style:tab-stops/style:tab-stop"_ostr, "char"_ostr, cDecimal); assertXPath( pXmlDoc, "//style:style[@style:name='P2']/style:paragraph-properties/style:tab-stops/style:tab-stop"_ostr, "char"_ostr, cDecimal); } DECLARE_ODFEXPORT_TEST(testTdf114287, "tdf114287.odt") { uno::Reference const xLevels1( getProperty>(getParagraph(2), "NumberingRules")); uno::Reference const xNum1(xLevels1, uno::UNO_QUERY); ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0)); CPPUNIT_ASSERT_EQUAL(sal_Int32(-700), props1["FirstLineIndent"].get()); CPPUNIT_ASSERT_EQUAL(sal_Int32(1330), props1["IndentAt"].get()); // 1: automatic style applies list-style-name and margin-left CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), getProperty(getParagraph(2), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty(getParagraph(2), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(2), "ParaRightMargin")); // list is continued uno::Reference const xNum2( getProperty>(getParagraph(9), "NumberingRules")); CPPUNIT_ASSERT_EQUAL(xNum1->getName(), xNum2->getName()); // 2: style applies list-style-name and margin-left, list applies list-style-name CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), getProperty(getParagraph(9), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty(getParagraph(9), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(9), "ParaRightMargin")); // list is continued uno::Reference const xNum3( getProperty>(getParagraph(16), "NumberingRules")); CPPUNIT_ASSERT_EQUAL(xNum1->getName(), xNum3->getName()); // 3: style applies margin-left, automatic style applies list-style-name CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), getProperty(getParagraph(16), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty(getParagraph(16), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(16), "ParaRightMargin")); xmlDocUniquePtr pXmlDoc = parseLayoutDump(); assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds"_ostr, "left"_ostr, "2268"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds"_ostr, "right"_ostr, "11339"); // the problem was that the list style name of the list must override the // paragraph style even though it's the same list style assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "left"_ostr, "357"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "right"_ostr, "11339"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/infos/prtBounds"_ostr, "left"_ostr, "357"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[16]/infos/prtBounds"_ostr, "right"_ostr, "11339"); } DECLARE_ODFEXPORT_TEST(testSectionColumnSeparator, "section-columns-separator.fodt") { // tdf#150235: due to wrong types used in column export, 'style:height' and 'style:style' // attributes were exported incorrectly for 'style:column-sep' element auto xSection = getProperty>(getParagraph(1), "TextSection"); auto xColumns = getProperty>(xSection, "TextColumns"); CPPUNIT_ASSERT(xColumns); CPPUNIT_ASSERT_EQUAL(sal_Int16(2), xColumns->getColumnCount()); // Without the accompanying fix in place, this test would have failed with: // - Expected: 50 // - Actual : 100 CPPUNIT_ASSERT_EQUAL(static_cast(50), getProperty(xColumns, "SeparatorLineRelativeHeight")); // Without the accompanying fix in place, this test would have failed with: // - Expected: 2 // - Actual : 0 CPPUNIT_ASSERT_EQUAL(css::text::ColumnSeparatorStyle::DOTTED, getProperty(xColumns, "SeparatorLineStyle")); // Check the rest of the properties, too CPPUNIT_ASSERT_EQUAL(true, getProperty(xColumns, "IsAutomatic")); CPPUNIT_ASSERT_EQUAL(sal_Int32(600), getProperty(xColumns, "AutomaticDistance")); CPPUNIT_ASSERT_EQUAL(sal_Int32(9), getProperty(xColumns, "SeparatorLineWidth")); CPPUNIT_ASSERT_EQUAL(Color(0x99, 0xAA, 0xBB), getProperty(xColumns, "SeparatorLineColor")); CPPUNIT_ASSERT_EQUAL( css::style::VerticalAlignment_BOTTOM, getProperty(xColumns, "SeparatorLineVerticalAlignment")); CPPUNIT_ASSERT_EQUAL(true, getProperty(xColumns, "SeparatorLineIsOn")); } DECLARE_ODFEXPORT_TEST(testTdf78510, "WordTest_edit.odt") { uno::Reference const xLevels1( getProperty>(getParagraph(1), "NumberingRules")); ::comphelper::SequenceAsHashMap props1(xLevels1->getByIndex(0)); CPPUNIT_ASSERT_EQUAL(sal_Int32(-1000), props1["FirstLineIndent"].get()); CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), props1["IndentAt"].get()); // 1: inherited from paragraph style and overridden by list CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(1), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(1), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(1), "ParaRightMargin")); // 2: as 1 + paragraph sets firstline CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), getProperty(getParagraph(2), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(2), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(2), "ParaRightMargin")); // 3: as 1 + paragraph sets textleft CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(3), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty(getParagraph(3), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(3), "ParaRightMargin")); // 4: as 1 + paragraph sets firstline, textleft CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty(getParagraph(4), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty(getParagraph(4), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(4), "ParaRightMargin")); // 5: as 1 + paragraph sets firstline CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty(getParagraph(5), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(5), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(5), "ParaRightMargin")); // 6: as 1 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(6), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(6), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(6), "ParaRightMargin")); uno::Reference const xLevels8( getProperty>(getParagraph(8), "NumberingRules")); ::comphelper::SequenceAsHashMap props8(xLevels8->getByIndex(0)); CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), props8["FirstLineIndent"].get()); CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), props8["IndentAt"].get()); // 8: inherited from paragraph style and overridden by list CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(8), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(8), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(8), "ParaRightMargin")); // 9: as 8 + paragraph sets firstline CPPUNIT_ASSERT_EQUAL(sal_Int32(2000), getProperty(getParagraph(9), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(9), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(9), "ParaRightMargin")); // 10: as 8 + paragraph sets textleft CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(10), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty(getParagraph(10), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(10), "ParaRightMargin")); // 11: as 8 + paragraph sets firstline, textleft CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty(getParagraph(11), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(3000), getProperty(getParagraph(11), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(11), "ParaRightMargin")); // 12: as 8 + paragraph sets firstline CPPUNIT_ASSERT_EQUAL(sal_Int32(-2000), getProperty(getParagraph(12), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(12), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(12), "ParaRightMargin")); // 13: as 8 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(13), "ParaFirstLineIndent")); CPPUNIT_ASSERT_EQUAL(sal_Int32(1270), getProperty(getParagraph(13), "ParaLeftMargin")); CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty(getParagraph(13), "ParaRightMargin")); // unfortunately it appears that the portions don't have a position // so it's not possible to check the first-line-offset that's applied // (the first-line-indent is computed on the fly in SwTextMargin when // painting) { xmlDocUniquePtr pXmlDoc = parseLayoutDump(); assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds"_ostr, "left"_ostr, "1134"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/infos/prtBounds"_ostr, "left"_ostr, "1134"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/infos/prtBounds"_ostr, "left"_ostr, "0"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/infos/prtBounds"_ostr, "left"_ostr, "1701"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/infos/prtBounds"_ostr, "left"_ostr, "-567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[12]/infos/prtBounds"_ostr, "right"_ostr, "9359"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/infos/prtBounds"_ostr, "left"_ostr, "567"); assertXPath(pXmlDoc, "/root/page[1]/body/txt[13]/infos/prtBounds"_ostr, "right"_ostr, "9359"); } // now check the positions where text is actually painted - // wonder how fragile this is... // FIXME some platform difference, 1st one is 2306 on Linux, 3087 on WNT ? // some Mac has 3110 #if !defined(_WIN32) && !defined(MACOSX) { SwDocShell *const pShell(dynamic_cast(*mxComponent).GetDocShell()); std::shared_ptr pMetaFile = pShell->GetPreviewMetaFile(); MetafileXmlDump aDumper; xmlDocUniquePtr pXmlDoc = dumpAndParse(aDumper, *pMetaFile); // 1: inherited from paragraph style and overridden by list // bullet char is extra assertXPath(pXmlDoc, "//textarray[1]"_ostr, "x"_ostr, "2306"); // text is after a tab from list - haven't checked if that is correct? assertXPath(pXmlDoc, "//textarray[2]"_ostr, "x"_ostr, "2873"); // second line assertXPath(pXmlDoc, "//textarray[3]"_ostr, "x"_ostr, "2873"); // 2: as 1 + paragraph sets firstline assertXPath(pXmlDoc, "//textarray[4]"_ostr, "x"_ostr, "3440"); assertXPath(pXmlDoc, "//textarray[5]"_ostr, "x"_ostr, "3593"); assertXPath(pXmlDoc, "//textarray[6]"_ostr, "x"_ostr, "2873"); // 3: as 1 + paragraph sets textleft assertXPath(pXmlDoc, "//textarray[7]"_ostr, "x"_ostr, "2873"); assertXPath(pXmlDoc, "//textarray[8]"_ostr, "x"_ostr, "3440"); assertXPath(pXmlDoc, "//textarray[9]"_ostr, "x"_ostr, "3440"); // 4: as 1 + paragraph sets firstline, textleft assertXPath(pXmlDoc, "//textarray[10]"_ostr, "x"_ostr, "2306"); assertXPath(pXmlDoc, "//textarray[11]"_ostr, "x"_ostr, "3440"); assertXPath(pXmlDoc, "//textarray[12]"_ostr, "x"_ostr, "3440"); // 5: as 1 + paragraph sets firstline assertXPath(pXmlDoc, "//textarray[13]"_ostr, "x"_ostr, "1739"); assertXPath(pXmlDoc, "//textarray[14]"_ostr, "x"_ostr, "2873"); assertXPath(pXmlDoc, "//textarray[15]"_ostr, "x"_ostr, "2873"); // 6: as 1 assertXPath(pXmlDoc, "//textarray[16]"_ostr, "x"_ostr, "2306"); assertXPath(pXmlDoc, "//textarray[17]"_ostr, "x"_ostr, "2873"); // 8: inherited from paragraph style and overridden by list assertXPath(pXmlDoc, "//textarray[18]"_ostr, "x"_ostr, "2873"); assertXPath(pXmlDoc, "//textarray[19]"_ostr, "x"_ostr, "3746"); assertXPath(pXmlDoc, "//textarray[20]"_ostr, "x"_ostr, "2306"); // 9: as 8 + paragraph sets firstline assertXPath(pXmlDoc, "//textarray[21]"_ostr, "x"_ostr, "3440"); assertXPath(pXmlDoc, "//textarray[22]"_ostr, "x"_ostr, "3746"); assertXPath(pXmlDoc, "//textarray[23]"_ostr, "x"_ostr, "2306"); // 10: as 8 + paragraph sets textleft assertXPath(pXmlDoc, "//textarray[24]"_ostr, "x"_ostr, "4007"); assertXPath(pXmlDoc, "//textarray[25]"_ostr, "x"_ostr, "4880"); assertXPath(pXmlDoc, "//textarray[26]"_ostr, "x"_ostr, "3440"); // 11: as 8 + paragraph sets firstline, textleft assertXPath(pXmlDoc, "//textarray[27]"_ostr, "x"_ostr, "2306"); assertXPath(pXmlDoc, "//textarray[28]"_ostr, "x"_ostr, "3440"); assertXPath(pXmlDoc, "//textarray[29]"_ostr, "x"_ostr, "3440"); // 12: as 8 + paragraph sets firstline assertXPath(pXmlDoc, "//textarray[30]"_ostr, "x"_ostr, "1172"); assertXPath(pXmlDoc, "//textarray[31]"_ostr, "x"_ostr, "1739"); assertXPath(pXmlDoc, "//textarray[32]"_ostr, "x"_ostr, "2306"); // 13: as 8 assertXPath(pXmlDoc, "//textarray[33]"_ostr, "x"_ostr, "2873"); assertXPath(pXmlDoc, "//textarray[34]"_ostr, "x"_ostr, "3746"); } #endif } CPPUNIT_TEST_FIXTURE(Test, testParagraphMarkerMarkupRoundtrip) { loadAndReload("ParagraphMarkerMarkup.fodt"); // Test that the markup stays at save-and-reload xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p"_ostr, "marker-style-name"_ostr, "T2"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties"_ostr, "font-size"_ostr, "9pt"); assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties"_ostr, "color"_ostr, "#ff0000"); } CPPUNIT_TEST_FIXTURE(Test, testCommentStyles) { createSwDoc(); auto xFactory(mxComponent.queryThrow()); auto xComment(xFactory->createInstance("com.sun.star.text.textfield.Annotation").queryThrow()); auto xCommentText(getProperty>(xComment, "TextRange")); xCommentText->setString("Hello World"); xCommentText.queryThrow()->setPropertyValue("ParaStyleName", uno::Any(OUString("Heading"))); xComment->attach(getParagraph(1)->getEnd()); saveAndReload("writer8"); auto xFields(mxComponent.queryThrow()->getTextFields()->createEnumeration()); xComment.set(xFields->nextElement().queryThrow()); CPPUNIT_ASSERT(xComment.queryThrow()->supportsService("com.sun.star.text.textfield.Annotation")); xCommentText.set(getProperty>(xComment, "TextRange")); CPPUNIT_ASSERT_EQUAL(OUString("Heading"), getProperty(xCommentText, "ParaStyleName")); auto xStyleFamilies(mxComponent.queryThrow()->getStyleFamilies()); auto xParaStyles(xStyleFamilies->getByName("ParagraphStyles")); auto xStyle(xParaStyles.queryThrow()->getByName("Heading")); CPPUNIT_ASSERT_EQUAL(getProperty(xStyle, "CharHeight"), getProperty(xCommentText, "CharHeight")); CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DEFAULT_VALUE, xCommentText.queryThrow()->getPropertyState("CharHeight")); } CPPUNIT_TEST_FIXTURE(Test, testTdf150408_IsLegal) { loadAndReload("IsLegal.fodt"); // Second level's numbering should use Arabic numbers for first level reference auto xPara = getParagraph(1); CPPUNIT_ASSERT_EQUAL(OUString("CH I"), getProperty(xPara, "ListLabelString")); xPara = getParagraph(2); CPPUNIT_ASSERT_EQUAL(OUString("Sect 1.01"), getProperty(xPara, "ListLabelString")); xPara = getParagraph(3); CPPUNIT_ASSERT_EQUAL(OUString("CH II"), getProperty(xPara, "ListLabelString")); xPara = getParagraph(4); CPPUNIT_ASSERT_EQUAL(OUString("Sect 2.01"), getProperty(xPara, "ListLabelString")); // Test that the markup stays at save-and-reload xmlDocUniquePtr pXmlDoc = parseExport("styles.xml"); assertXPath( pXmlDoc, "/office:document-styles/office:styles/text:outline-style/text:outline-level-style[2]"_ostr, "is-legal"_ostr, "true"); } CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */