Add a comment to clarify what kind of inputs the class handles
[LibreOffice.git] / sw / qa / extras / ooxmlexport / ooxmlexport.cxx
blob64901fcf7359f100678703a8c1ece3a81923cf63
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <swmodeltestbase.hxx>
12 #include <com/sun/star/awt/FontSlant.hpp>
13 #include <com/sun/star/awt/XBitmap.hpp>
14 #include <com/sun/star/drawing/FillStyle.hpp>
15 #include <com/sun/star/style/BreakType.hpp>
16 #include <com/sun/star/text/FontEmphasis.hpp>
17 #include <com/sun/star/text/HoriOrientation.hpp>
18 #include <com/sun/star/text/XTextRangeCompare.hpp>
19 #include <com/sun/star/text/WritingMode2.hpp>
20 #include <com/sun/star/text/TableColumnSeparator.hpp>
21 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
22 #include <com/sun/star/frame/XStorable.hpp>
23 #include <com/sun/star/text/XTextTablesSupplier.hpp>
24 #include <com/sun/star/text/XTextTable.hpp>
25 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
26 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
27 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
29 #include <o3tl/cppunittraitshelper.hxx>
30 #include <oox/drawingml/drawingmltypes.hxx>
31 #include <comphelper/sequenceashashmap.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <tools/UnitConversion.hxx>
34 #include <frameformats.hxx>
36 class Test : public SwModelTestBase
38 public:
39 Test() : SwModelTestBase(u"/sw/qa/extras/ooxmlexport/data/"_ustr, u"Office Open XML Text"_ustr) {}
42 CPPUNIT_TEST_FIXTURE(Test, testfdo81381)
44 loadAndSave("fdo81381.docx");
45 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
46 assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r[1]/w:object[1]/o:OLEObject[1]", "DrawAspect", u"Icon");
49 CPPUNIT_TEST_FIXTURE(Test, testSdtAlias)
51 loadAndSave("sdt-alias.docx");
52 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
54 // <w:alias> was completely missing.
55 assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:alias", "val", u"Subtitle");
58 CPPUNIT_TEST_FIXTURE(Test, testFooterBodyDistance)
60 loadAndSave("footer-body-distance.docx");
61 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
62 // Page break was exported as section break, this was 0
63 assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:br", 1);
66 DECLARE_OOXMLEXPORT_TEST(testfdo81031, "fdo81031.docx")
68 // vml image was not rendered
69 // As there are also numPicBullets in the file,
70 // the fragmentPath was not changed hence relationships were not resolved.
72 uno::Reference<drawing::XShape> image = getShape(1);
73 uno::Reference<beans::XPropertySet> xImage(image, uno::UNO_QUERY);
74 uno::Reference<graphic::XGraphic> xGraphic = getProperty<uno::Reference<graphic::XGraphic> >(xImage, u"Graphic"_ustr);
75 uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
76 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(381), xBitmap->getSize().Width );
77 CPPUNIT_ASSERT_EQUAL( static_cast<sal_Int32>(148), xBitmap->getSize().Height );
80 CPPUNIT_TEST_FIXTURE(Test, testPlausableBorder)
82 loadAndSave("plausable-border.docx");
83 // sw::util::IsPlausableSingleWordSection() did not merge two page styles due to borders.
84 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
85 // Page break was exported as section break, this was 0
86 assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/w:br", 1);
88 CPPUNIT_ASSERT_EQUAL( 2, getPages() );
91 CPPUNIT_TEST_FIXTURE(Test, testUnwantedSectionBreak)
93 loadAndSave("unwanted-section-break.docx");
94 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
95 // This was 2: an additional sectPr was added to the document.
96 assertXPath(pXmlDoc, "//w:sectPr", 1);
99 CPPUNIT_TEST_FIXTURE(Test, testfdo80897 )
101 loadAndSave("fdo80897.docx");
102 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
103 assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:anchor/a:graphic/a:graphicData/wps:wsp/wps:bodyPr/a:prstTxWarp", "prst", u"textTriangle");
107 DECLARE_OOXMLEXPORT_TEST(testFdo80997, "fdo80997.docx")
109 // The problem was that the DOCX exporter not able to export text behind textbox, if textbox has a wrap property.
110 uno::Reference< text::XTextRange > xParagraph = getParagraph( 1 );
111 getRun( xParagraph, 1, u" text"_ustr);
114 CPPUNIT_TEST_FIXTURE(Test, testFdo80902)
116 loadAndSave("fdo80902.docx");
117 // The problem was that the docGrid type was set as default so fix it for other grid type
118 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
120 assertXPath(pXmlDoc, "/w:document/w:body/w:sectPr/w:docGrid", "type", u"lines");
123 CPPUNIT_TEST_FIXTURE(Test, testParaShading)
125 loadAndSave("para-shading.docx");
126 // Make sure the themeColor attribute is not written when it would be empty.
127 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
128 assertXPathNoAttribute(pXmlDoc, "/w:document/w:body/w:p/w:pPr/w:shd", "themeColor");
131 CPPUNIT_TEST_FIXTURE(Test, testFDO83044)
133 loadAndSave("fdo83044.docx");
134 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
136 assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:sdt/w:sdtPr/w:text", 1);
139 DECLARE_OOXMLEXPORT_TEST(testfdo83428, "fdo83428.docx")
141 uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(mxComponent, uno::UNO_QUERY);
142 uno::Reference<document::XDocumentProperties> xProps(xDocumentPropertiesSupplier->getDocumentProperties());
143 uno::Reference<beans::XPropertySet> xUDProps(xProps->getUserDefinedProperties(), uno::UNO_QUERY);
144 CPPUNIT_ASSERT_EQUAL(u"Document"_ustr, getProperty<OUString>(xUDProps, u"Testing"_ustr));
147 CPPUNIT_TEST_FIXTURE(Test, testShapeInFloattable)
149 loadAndSave("shape-in-floattable.docx");
150 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
151 // No nested drawingML w:txbxContent.
152 assertXPath(pXmlDoc, "//mc:Choice//w:txbxContent//w:txbxContent", 0);
153 // Instead, make sure we have a separate shape and a table
154 assertXPath(pXmlDoc, "//mc:AlternateContent//mc:Choice[@Requires='wpg']", 1);
155 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl", 1);
158 CPPUNIT_TEST_FIXTURE(Test, testEmptyAnnotationMark)
160 loadAndReload("empty-annotation-mark.docx");
161 // Delete the word that is commented, and save again.
162 uno::Reference<text::XTextRange> xRun = getRun(getParagraph(1), 3);
163 CPPUNIT_ASSERT_EQUAL(u"with"_ustr, xRun->getString());
164 xRun->setString(u""_ustr);
165 uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
166 xStorable->store();
168 // Then inspect the OOXML markup of the modified document model.
169 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
170 // There were two commentReference nodes.
171 assertXPath(pXmlDoc, "//w:commentReference", "id", u"0");
172 // Empty comment range was not ignored on export, this was 1.
173 assertXPath(pXmlDoc, "//w:commentRangeStart", 0);
174 // Ditto.
175 assertXPath(pXmlDoc, "//w:commentRangeEnd", 0);
178 CPPUNIT_TEST_FIXTURE(Test, testDropdownInCell)
180 auto verify = [this](bool bIsExport = false) {
181 // First problem: table was missing from the document, this was 0.
182 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
183 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
184 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
186 // Second problem: dropdown shape wasn't anchored inside the B1 cell.
187 if (getShapes() > 0)
189 uno::Reference<text::XTextContent> xShape(getShape(1), uno::UNO_QUERY);
190 uno::Reference<text::XTextRange> xAnchor = xShape->getAnchor();
191 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
192 uno::Reference<text::XTextRange> xCell(xTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY);
193 uno::Reference<text::XTextRangeCompare> xTextRangeCompare(xCell, uno::UNO_QUERY);
194 CPPUNIT_ASSERT_EQUAL(sal_Int16(0), xTextRangeCompare->compareRegionStarts(xAnchor, xCell));
197 if (!bIsExport)
199 // ComboBox was imported as DropDown text field
200 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
201 uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
202 uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
203 CPPUNIT_ASSERT(xFields->hasMoreElements());
204 uno::Any aField = xFields->nextElement();
205 uno::Reference<lang::XServiceInfo> xServiceInfo(aField, uno::UNO_QUERY);
206 CPPUNIT_ASSERT(xServiceInfo->supportsService(u"com.sun.star.text.textfield.DropDown"_ustr));
208 else
210 // DropDown text field is exported as inline SDT, we import that back here.
211 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
212 uno::Reference<table::XCell> xCell = xTable->getCellByName(u"B1"_ustr);
213 uno::Reference<container::XEnumerationAccess> xParagraphsAccess(xCell, uno::UNO_QUERY);
214 uno::Reference<container::XEnumeration> xParagraphs = xParagraphsAccess->createEnumeration();
215 uno::Reference<container::XEnumerationAccess> xParagraph(xParagraphs->nextElement(),
216 uno::UNO_QUERY);
217 uno::Reference<container::XEnumeration> xPortions = xParagraph->createEnumeration();
218 uno::Reference<beans::XPropertySet> xTextPortion(xPortions->nextElement(), uno::UNO_QUERY);
219 OUString aPortionType;
220 xTextPortion->getPropertyValue(u"TextPortionType"_ustr) >>= aPortionType;
221 CPPUNIT_ASSERT_EQUAL(u"ContentControl"_ustr, aPortionType);
222 uno::Reference<text::XTextContent> xContentControl;
223 xTextPortion->getPropertyValue(u"ContentControl"_ustr) >>= xContentControl;
224 uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
225 uno::Sequence<beans::PropertyValues> aListItems;
226 xContentControlProps->getPropertyValue(u"ListItems"_ustr) >>= aListItems;
227 CPPUNIT_ASSERT(aListItems.hasElements());
231 createSwDoc("dropdown-in-cell.docx");
232 verify();
233 saveAndReload(mpFilter);
234 verify(/*bIsExport*/ true);
237 DECLARE_OOXMLEXPORT_TEST(testTableAlignment, "table-alignment.docx")
239 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
240 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
241 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
242 // This was LEFT_AND_WIDTH, i.e. table alignment wasn't imported correctly.
243 CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::RIGHT, getProperty<sal_Int16>(xTable, u"HoriOrient"_ustr));
246 CPPUNIT_TEST_FIXTURE(Test, testSdtIgnoredFooter)
248 loadAndSave("sdt-ignored-footer.docx");
249 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
250 // This was 1, make sure no w:sdt sneaks into the main document from the footer.
251 assertXPath(pXmlDoc, "//w:sdt", 0);
254 CPPUNIT_TEST_FIXTURE(Test, testSdtRunPicture)
256 loadAndSave("sdt-run-picture.docx");
257 // SDT around run was exported as SDT around paragraph
258 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
259 // This was 1: there was an SDT around w:p.
260 assertXPath(pXmlDoc, "//w:body/w:sdt", 0);
261 // This was 0: there were no SDT around w:r.
262 assertXPath(pXmlDoc, "//w:body/w:p/w:sdt", 1);
265 CPPUNIT_TEST_FIXTURE(Test, testChartDupe)
267 auto verify = [this]() {
268 // Single chart was exported back as two charts.
269 uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY);
270 uno::Reference<container::XIndexAccess> xEmbeddedObjects(xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY);
271 // This was 2, on second import we got a duplicated chart copy.
272 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xEmbeddedObjects->getCount());
275 createSwDoc("chart-dupe.docx");
276 verify();
277 saveAndReload(mpFilter);
278 verify();
280 xmlDocUniquePtr pXmlDocCT = parseExport(u"[Content_Types].xml"_ustr);
282 assertXPath(pXmlDocCT,
283 "/ContentType:Types/ContentType:Override[@PartName='/word/charts/chart1.xml']",
284 "ContentType",
285 u"application/vnd.openxmlformats-officedocument.drawingml.chart+xml");
286 assertXPath(pXmlDocCT, "/ContentType:Types/ContentType:Override[@PartName='/word/embeddings/Microsoft_Excel_Worksheet1.xlsx']", "ContentType", u"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
288 // check the rels too
289 xmlDocUniquePtr pXmlDocRels = parseExport(u"word/charts/_rels/chart1.xml.rels"_ustr);
290 assertXPath(pXmlDocRels,
291 "/rels:Relationships/rels:Relationship[@Target='../embeddings/Microsoft_Excel_Worksheet1.xlsx']",
292 "Type",
293 u"http://schemas.openxmlformats.org/officeDocument/2006/relationships/package");
294 // check the content too
295 xmlDocUniquePtr pXmlDocChart1 = parseExport(u"word/charts/chart1.xml"_ustr);
296 assertXPath(pXmlDocChart1,
297 "/c:chartSpace/c:externalData",
298 "id",
299 u"rId1");
302 DECLARE_OOXMLEXPORT_TEST(testPositionAndRotation, "position-and-rotation.docx")
304 // The document should look like: "This line is tricky, <image> because only 'This line is tricky,' is on the left."
305 // But the image was pushed down, so it did not break the line into two text portions.
306 uno::Reference<drawing::XShape> xShape = getShape(1);
307 // Should be 1559, was -5639
308 CPPUNIT_ASSERT(xShape->getPosition().X > 1500);
309 // Should be 88, was 473
310 CPPUNIT_ASSERT(xShape->getPosition().Y < 100);
313 DECLARE_OOXMLEXPORT_TEST(testNumberingFont, "numbering-font.docx")
315 // check that the original numrule font name is still Calibri
316 uno::Reference<beans::XPropertySet> xStyle(getStyles(u"CharacterStyles"_ustr)->getByName(u"ListLabel 1"_ustr), uno::UNO_QUERY);
317 CPPUNIT_ASSERT_EQUAL(u"Calibri"_ustr, getProperty<OUString>(xStyle, u"CharFontName"_ustr));
319 uno::Reference<text::XTextRange> xPara = getParagraph(2);
320 uno::Reference<beans::XPropertySet> properties(xPara, uno::UNO_QUERY);
321 uno::Any aValue = properties->getPropertyValue(u"ListAutoFormat"_ustr);
322 CPPUNIT_ASSERT(aValue.hasValue());
323 uno::Sequence<beans::NamedValue> aListAutoFormat;
324 CPPUNIT_ASSERT(aValue >>= aListAutoFormat);
325 auto it = std::find_if(std::cbegin(aListAutoFormat), std::cend(aListAutoFormat),
326 [](const css::beans::NamedValue& val) { return val.Name == "CharFontName"; });
327 CPPUNIT_ASSERT(it != std::cend(aListAutoFormat));
328 OUString sOverrideFontName;
329 CPPUNIT_ASSERT(it->Value >>= sOverrideFontName);
330 // but the overridden font name is Verdana
331 CPPUNIT_ASSERT_EQUAL(u"Verdana"_ustr, sOverrideFontName);
334 CPPUNIT_TEST_FIXTURE(Test, testTdf106541_noinheritChapterNumbering)
336 loadAndReload("tdf106541_noinheritChapterNumbering.odt");
337 CPPUNIT_ASSERT_EQUAL(1, getPages());
338 // in LO, it appears that styles based on the Chapter Numbering style explicitly set the
339 // numbering style/outline level to 0 by default, and that LO prevents inheriting directly from "Outline" style.
340 // Adding this preventative unit test to ensure that any fix for tdf106541 doesn't make incorrect assumptions.
342 //reverting tdf#76817 hard-codes the numbering style on the paragraph, preventing RT of "Outline" style
343 // CPPUNIT_ASSERT_EQUAL(OUString("Outline"), getProperty<OUString>(getParagraph(1), "NumberingStyleName"));
345 OUString sPara3NumberingStyle = getProperty<OUString>(getParagraph(3), u"NumberingStyleName"_ustr);
346 CPPUNIT_ASSERT_EQUAL(sPara3NumberingStyle, getProperty<OUString>(getParagraph(4), u"NumberingStyleName"_ustr));
348 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
349 assertXPath(pXmlDoc, "//body/txt/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", 3); //three of the four paragraphs have numbering
350 assertXPath(pXmlDoc, "//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", u"1");
351 assertXPath(pXmlDoc, "//body/txt[2]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", 0); //second paragraph style disables numbering
352 assertXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", u"I.");
353 assertXPath(pXmlDoc, "//body/txt[4]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", u"II.");
356 DECLARE_OOXMLEXPORT_TEST(testTdf53856_conflictingStyle, "tdf53856_conflictingStyle.docx")
358 // The "Text" style conflicted with builtin paragraph style Caption -> Text
359 uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Text"_ustr), uno::UNO_QUERY);
360 CPPUNIT_ASSERT_EQUAL(u"Times New Roman"_ustr, getProperty<OUString>(xStyle, u"CharFontName"_ustr));
361 CPPUNIT_ASSERT_EQUAL(awt::FontSlant_NONE, getProperty<awt::FontSlant>(xStyle, u"CharPosture"_ustr));
364 DECLARE_OOXMLEXPORT_TEST(testTdf104713_undefinedStyles, "tdf104713_undefinedStyles.docx")
366 // Normal paragraph style was not defined, so don't replace conflicting styles
367 uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Heading 1"_ustr), uno::UNO_QUERY);
368 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(212), getProperty<sal_Int32>(xStyle, u"ParaBottomMargin"_ustr));
370 // tdf108765: once importing is finished, use default values for any styles not yet defined.
371 xStyle.set( getStyles(u"ParagraphStyles"_ustr)->getByName(u"Footnote"_ustr), uno::UNO_QUERY );
372 CPPUNIT_ASSERT_EQUAL_MESSAGE("Font size", 10.f, getProperty<float>(xStyle, u"CharHeight"_ustr));
375 CPPUNIT_TEST_FIXTURE(Test, testDrawingmlFlipv)
377 loadAndSave("drawingml-flipv.docx");
378 // The problem was that the shape had vertical flip only, but then we added rotation as well on export.
379 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
380 assertXPathNoAttribute(pXmlDoc, "//a:xfrm", "rot");
383 CPPUNIT_TEST_FIXTURE(Test, testRot90Fliph)
385 loadAndSave("rot90-fliph.docx");
386 // The problem was that a shape rotation of 90° got turned into 270° after roundtrip.
387 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
388 assertXPath(pXmlDoc, "//a:xfrm", "flipH", u"1");
389 // This was 16200000 (270 * 60000).
390 assertXPath(pXmlDoc, "//a:xfrm", "rot", u"5400000");
393 CPPUNIT_TEST_FIXTURE(Test, testRot180Flipv)
395 loadAndSave("rot180-flipv.docx");
396 // 180° rotation got lost after roundtrip.
397 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
398 assertXPath(pXmlDoc, "//a:xfrm", "flipV", u"1");
399 // This attribute was completely missing.
400 assertXPath(pXmlDoc, "//a:xfrm", "rot", u"10800000");
403 CPPUNIT_TEST_FIXTURE(Test, testRot270Flipv)
405 loadAndSave("rot270-flipv.docx");
406 // 270° rotation got turned into 90° after roundtrip.
407 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
408 assertXPath(pXmlDoc, "//a:xfrm", "flipV", u"1");
409 // This was 5400000.
410 assertXPath(pXmlDoc, "//a:xfrm", "rot", u"16200000");
413 DECLARE_OOXMLEXPORT_TEST(testWpsCharColor, "wps-char-color.docx")
415 uno::Reference<text::XTextRange> xShape(getShape(1), uno::UNO_QUERY);
416 // This was -1, i.e. the character color was default (-1), not white.
417 CPPUNIT_ASSERT_EQUAL(COL_WHITE, getProperty<Color>(xShape->getStart(), u"CharColor"_ustr));
420 DECLARE_OOXMLEXPORT_TEST(testTableStyleCellBackColor, "table-style-cell-back-color.docx")
422 // The problem was that cell background was white, not green.
423 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
424 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
425 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
426 uno::Reference<table::XCell> xCell = xTable->getCellByName(u"A1"_ustr);
427 // This was 0xffffff.
428 CPPUNIT_ASSERT_EQUAL(COL_LIGHTGREEN, getProperty<Color>(xCell, u"BackColor"_ustr));
431 DECLARE_OOXMLEXPORT_TEST(testTableStyleBorder, "table-style-border.docx")
433 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
434 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
435 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
437 // This was 0, the second cell was missing its right border.
438 uno::Reference<table::XCell> xCell = xTable->getCellByName(u"A2"_ustr);
439 CPPUNIT_ASSERT(getProperty<table::BorderLine2>(xCell, u"RightBorder"_ustr).LineWidth > 0);
441 // This was also 0 (even after fixing the previous problem), the first cell was missing its right border, too.
442 xCell = xTable->getCellByName(u"A1"_ustr);
443 CPPUNIT_ASSERT(getProperty<table::BorderLine2>(xCell, u"RightBorder"_ustr).LineWidth > 0);
446 DECLARE_OOXMLEXPORT_TEST(testTableStyleBorderExport, "table-style-border-export.docx")
448 uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
449 uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
450 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
451 uno::Reference<table::XCell> xCell = xTable->getCellByName(u"A3"_ustr);
452 // Bottom border was white, so this was 0xffffff.
453 CPPUNIT_ASSERT_EQUAL(Color(0x8064A2), Color(ColorTransparency, getProperty<table::BorderLine2>(xCell, u"BottomBorder"_ustr).Color));
456 DECLARE_OOXMLEXPORT_TEST(testAnchorPosition, "anchor-position.docx")
458 // The problem was that the at-char anchored picture was at the end of the
459 // paragraph, so there were only two positions: a Text, then a Frame one.
460 CPPUNIT_ASSERT_EQUAL(u"Text"_ustr, getProperty<OUString>(getRun(getParagraph(1), 1), u"TextPortionType"_ustr));
461 CPPUNIT_ASSERT_EQUAL(u"Frame"_ustr, getProperty<OUString>(getRun(getParagraph(1), 2), u"TextPortionType"_ustr));
462 CPPUNIT_ASSERT_EQUAL(u"Text"_ustr, getProperty<OUString>(getRun(getParagraph(1), 3), u"TextPortionType"_ustr));
465 DECLARE_OOXMLEXPORT_TEST(testMultiPageToc, "multi-page-toc.docx")
467 // Import of this document triggered an STL assertion.
469 // Document has a ToC from its second paragraph.
470 uno::Reference<container::XNamed> xTextSection = getProperty< uno::Reference<container::XNamed> >(getParagraph(2), u"TextSection"_ustr);
471 CPPUNIT_ASSERT_EQUAL(u"Table of Contents1"_ustr, xTextSection->getName());
472 // There should be a field in the header as well.
473 uno::Reference<text::XText> xHeaderText = getProperty< uno::Reference<text::XText> >(getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), u"HeaderText"_ustr);
474 CPPUNIT_ASSERT_EQUAL(u"TextField"_ustr, getProperty<OUString>(getRun(getParagraphOfText(1, xHeaderText), 1), u"TextPortionType"_ustr));
477 DECLARE_OOXMLEXPORT_TEST(testTextboxTable, "textbox-table.docx")
479 // We wrote not-well-formed XML during export for this one:
480 // Shape with textbox, having a table and also anchored inside a table.
482 // Just make sure that we have both tables.
483 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
484 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
485 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xTables->getCount());
488 CPPUNIT_TEST_FIXTURE(Test, testCropPixel)
490 loadAndSave("crop-pixel.docx");
491 // If map mode of the graphic is in pixels, then we used to handle original
492 // size of the graphic as mm100, but it was in pixels.
493 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
494 // This is 17667 in the original document, was 504666 (so the image
495 // become invisible), now is around 19072.
496 CPPUNIT_ASSERT(getXPath(pXmlDoc, "//a:srcRect", "l").toInt32() <= 22452);
498 /* FixMe: tdf#142805 Test disabled, because the picture is not load at all.
499 CPPUNIT_TEST_FIXTURE(Test, testEffectExtent)
501 loadAndSave("effect-extent.docx");
502 // The problem was that in case there were no shadows on the picture, we
503 // wrote a <wp:effectExtent> full or zeros.
504 xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
505 // E.g. this was 0.
506 assertXPath(pXmlDoc, "//wp:effectExtent", "l", "114300");
509 CPPUNIT_TEST_FIXTURE(Test, testEffectExtentInline)
511 loadAndSave("effect-extent-inline.docx");
512 // The problem was that in case there was inline rotated picture, we
513 // wrote a <wp:effectExtent> full or zeros.
514 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
515 // E.g. this was 0.
516 assertXPath(pXmlDoc, "//wp:effectExtent", "l", u"609600");
517 assertXPath(pXmlDoc, "//wp:effectExtent", "r", u"590550");
518 assertXPath(pXmlDoc, "//wp:effectExtent", "t", u"590550");
519 assertXPath(pXmlDoc, "//wp:effectExtent", "b", u"571500");
522 DECLARE_OOXMLEXPORT_TEST(testEm, "em.docx")
524 // Test all possible <w:em> arguments.
525 CPPUNIT_ASSERT_EQUAL(text::FontEmphasis::NONE, getProperty<sal_Int16>(getRun(getParagraph(1), 1), u"CharEmphasis"_ustr));
526 // This was ACCENT_ABOVE.
527 CPPUNIT_ASSERT_EQUAL(text::FontEmphasis::DOT_ABOVE, getProperty<sal_Int16>(getRun(getParagraph(1), 2), u"CharEmphasis"_ustr));
528 // This was DOT_ABOVE.
529 CPPUNIT_ASSERT_EQUAL(text::FontEmphasis::ACCENT_ABOVE, getProperty<sal_Int16>(getRun(getParagraph(1), 3), u"CharEmphasis"_ustr));
530 CPPUNIT_ASSERT_EQUAL(text::FontEmphasis::CIRCLE_ABOVE, getProperty<sal_Int16>(getRun(getParagraph(1), 4), u"CharEmphasis"_ustr));
531 CPPUNIT_ASSERT_EQUAL(text::FontEmphasis::DOT_BELOW, getProperty<sal_Int16>(getRun(getParagraph(1), 5), u"CharEmphasis"_ustr));
534 DECLARE_OOXMLEXPORT_TEST(testFdo77716, "fdo77716.docx")
536 // The problem was that there should be 200 twips spacing between the two paragraphs, but there wasn't any.
537 uno::Reference<beans::XPropertySet> xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY);
538 // This was 0.
539 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(convertTwipToMm100(200)), getProperty<sal_Int32>(xStyle, u"ParaBottomMargin"_ustr));
542 DECLARE_OOXMLEXPORT_TEST(testAfterlines, "afterlines.docx")
544 // This was 353, i.e. the value of <w:spacing w:after="200"> from <w:pPrDefault>, instead of <w:spacing w:afterLines="100"/> from <w:pPr>.
545 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(423), getProperty<sal_Int32>(getParagraph(1), u"ParaBottomMargin"_ustr));
548 DECLARE_OOXMLEXPORT_TEST(testParagraphMark, "paragraph-mark.docx")
550 // The problem was that we didn't handle the situation when an empty paragraph's marker had both a char style and some direct formatting.
552 // This was 11.
553 CPPUNIT_ASSERT_EQUAL(12.f, getProperty<float>(getParagraph(1), u"CharHeight"_ustr));
554 // This was empty.
555 CPPUNIT_ASSERT_EQUAL(u"Emphasis"_ustr, getProperty<OUString>(getRun(getParagraph(1), 1), u"CharStyleName"_ustr));
558 DECLARE_OOXMLEXPORT_TEST(testParagraphMark2, "paragraph-mark2.docx")
560 // The problem was that we didn't handle the situation when an empty paragraph's marker had both a char style and some direct formatting.
562 // This was Segoe UI, set by Char Style FontStyle11 presumably.
563 CPPUNIT_ASSERT_EQUAL(u"Arial"_ustr, getProperty<OUString>(getRun(getParagraph(1), 1), u"CharFontName"_ustr));
564 // This was 11, set by Char Style FontStyle11 presumably.
565 CPPUNIT_ASSERT_EQUAL(10.f, getProperty<float>(getRun(getParagraph(1), 1), u"CharHeight"_ustr));
568 CPPUNIT_TEST_FIXTURE(Test, testParagraphMarkNonempty)
570 loadAndSave("paragraph-mark-nonempty.odt");
571 validate(maTempFile.GetFileName(), test::OOXML);
572 CPPUNIT_ASSERT_EQUAL(1, getPages());
573 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
574 // There were two <w:sz> elements, make sure the 40 one is dropped and the 20 one is kept.
575 assertXPath(pXmlDoc, "//w:p/w:pPr/w:rPr/w:sz", "val", u"20");
578 DECLARE_OOXMLEXPORT_TEST(testPageBreakBefore, "page-break-before.docx")
580 // This was style::BreakType_PAGE_BEFORE, i.e. page break wasn't ignored, as it should have been.
581 CPPUNIT_ASSERT_EQUAL(style::BreakType_NONE, getProperty<style::BreakType>(getParagraph(2), u"BreakType"_ustr));
584 DECLARE_OOXMLEXPORT_TEST(testTableRtl, "table-rtl.docx")
586 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
587 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
588 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
589 // This was text::WritingMode2::LR_TB, i.e. direction of the table was ignored.
590 CPPUNIT_ASSERT_EQUAL(text::WritingMode2::RL_TB, getProperty<sal_Int16>(xTable, u"WritingMode"_ustr));
593 DECLARE_OOXMLEXPORT_TEST(testTableLr, "table-ltr.docx")
595 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
596 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
597 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
598 // This was text::WritingMode2::RL_TB, i.e. direction of the table was wrongly guessed.
599 CPPUNIT_ASSERT_EQUAL(text::WritingMode2::CONTEXT, getProperty<sal_Int16>(xTable, u"WritingMode"_ustr));
602 DECLARE_OOXMLEXPORT_TEST(testOoxmlCjklist30, "cjklist30.docx")
604 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
605 CPPUNIT_ASSERT_EQUAL(style::NumberingType::TIAN_GAN_ZH, numFormat);
608 DECLARE_OOXMLEXPORT_TEST(testOoxmlCjklist31, "cjklist31.docx")
610 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
611 CPPUNIT_ASSERT_EQUAL(style::NumberingType::DI_ZI_ZH, numFormat);
614 DECLARE_OOXMLEXPORT_TEST(testOoxmlCjklist34, "cjklist34.docx")
616 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
617 CPPUNIT_ASSERT_EQUAL(style::NumberingType::NUMBER_UPPER_ZH_TW, numFormat);
620 DECLARE_OOXMLEXPORT_TEST(testOoxmlCjklist35, "cjklist35.docx")
622 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
623 CPPUNIT_ASSERT_EQUAL(style::NumberingType::NUMBER_LOWER_ZH, numFormat);
626 DECLARE_OOXMLEXPORT_TEST(testOoxmlCjklist44, "cjklist44.docx")
628 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
629 CPPUNIT_ASSERT_EQUAL(style::NumberingType::NUMBER_DIGITAL2_KO, numFormat);
632 DECLARE_OOXMLEXPORT_TEST(testOoxmlTextNumberList, "text_number_list.docx")
634 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
635 CPPUNIT_ASSERT_EQUAL(style::NumberingType::TEXT_NUMBER, numFormat);
638 DECLARE_OOXMLEXPORT_TEST(testOoxmlTextCardinalList, "text_cardinal_list.docx")
640 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
641 CPPUNIT_ASSERT_EQUAL(style::NumberingType::TEXT_CARDINAL, numFormat);
644 DECLARE_OOXMLEXPORT_TEST(testOoxmlTextOrdinalList, "text_ordinal_list.docx")
646 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
647 CPPUNIT_ASSERT_EQUAL(style::NumberingType::TEXT_ORDINAL, numFormat);
650 DECLARE_OOXMLEXPORT_TEST(testOoxmlSymbolChicagoList, "symbol_chicago_list.docx")
652 sal_Int16 numFormat = getNumberingTypeOfParagraph(1);
653 CPPUNIT_ASSERT_EQUAL(style::NumberingType::SYMBOL_CHICAGO, numFormat);
656 CPPUNIT_TEST_FIXTURE(Test, testOoxmlNumListZHTW)
658 loadAndSave("numlist-zhtw.odt");
659 CPPUNIT_ASSERT_EQUAL(1, getPages());
660 xmlDocUniquePtr pXmlDoc = parseExport(u"word/numbering.xml"_ustr);
662 assertXPath ( pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:numFmt","val",u"taiwaneseCountingThousand" );
665 CPPUNIT_TEST_FIXTURE(Test, testOoxmlNumListZHCN)
667 loadAndSave("numlist-zhcn.odt");
668 CPPUNIT_ASSERT_EQUAL(1, getPages());
669 xmlDocUniquePtr pXmlDoc = parseExport(u"word/numbering.xml"_ustr);
671 assertXPath ( pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:numFmt","val",u"chineseCountingThousand" );
674 CPPUNIT_TEST_FIXTURE(Test, testOOxmlOutlineNumberTypes)
676 loadAndSave("outline-number-types.odt");
677 CPPUNIT_ASSERT_EQUAL(1, getPages());
678 xmlDocUniquePtr pXmlDoc = parseExport(u"word/numbering.xml"_ustr);
680 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:pStyle", "val", u"Heading1");
681 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[1]/w:numFmt", "val", u"none");
682 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[2]/w:numFmt", "val", u"decimalEnclosedCircle");
683 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[3]/w:numFmt", "val", u"decimal"); // CHARS_GREEK_UPPER_LETTER fallback to decimal
684 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[4]/w:numFmt", "val", u"decimal"); // CHARS_GREEK_LOWER_LETTER fallback to decimal
685 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[5]/w:numFmt", "val", u"arabicAlpha");
686 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[6]/w:numFmt", "val", u"hindiVowels");
687 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[1]/w:lvl[7]/w:numFmt", "val", u"thaiLetters");
689 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[1]/w:numFmt", "val", u"decimal");
690 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[2]/w:numFmt", "val", u"decimal");
691 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[3]/w:numFmt", "val", u"decimal");
692 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[4]/w:numFmt", "val", u"decimal");
693 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[5]/w:numFmt", "val", u"russianUpper");
694 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[6]/w:numFmt", "val", u"russianLower");
695 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[7]/w:numFmt", "val", u"russianUpper");
696 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[2]/w:lvl[8]/w:numFmt", "val", u"russianLower");
698 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[1]/w:numFmt", "val", u"decimal");
699 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[2]/w:numFmt", "val", u"decimal");
700 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[3]/w:numFmt", "val", u"decimal");
701 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[4]/w:numFmt", "val", u"decimal");
702 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[5]/w:numFmt", "val", u"decimal");
703 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[6]/w:numFmt", "val", u"decimal");
704 assertXPath(pXmlDoc, "/w:numbering/w:abstractNum[3]/w:lvl[7]/w:numFmt", "val", u"decimal");
708 DECLARE_OOXMLEXPORT_TEST(testNumParentStyle, "num-parent-style.docx")
710 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
711 getProperty<sal_Int32>(getParagraph(1), u"OutlineLevel"_ustr));
712 CPPUNIT_ASSERT_EQUAL(u"1"_ustr, getProperty<OUString>(getParagraph(1), u"ListLabelString"_ustr));
713 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2),
714 getProperty<sal_Int32>(getParagraph(2), u"OutlineLevel"_ustr));
715 CPPUNIT_ASSERT_EQUAL(u"1.1"_ustr, getProperty<OUString>(getParagraph(2), u"ListLabelString"_ustr));
716 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1),
717 getProperty<sal_Int32>(getParagraph(3), u"OutlineLevel"_ustr));
718 CPPUNIT_ASSERT_EQUAL(u"2"_ustr, getProperty<OUString>(getParagraph(3), u"ListLabelString"_ustr));
719 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2),
720 getProperty<sal_Int32>(getParagraph(4), u"OutlineLevel"_ustr));
721 CPPUNIT_ASSERT_EQUAL(u"2.1"_ustr, getProperty<OUString>(getParagraph(4), u"ListLabelString"_ustr));
724 DECLARE_OOXMLEXPORT_TEST(testNumOverrideLvltext, "num-override-lvltext.docx")
726 uno::Reference<container::XIndexAccess> xRules = getProperty< uno::Reference<container::XIndexAccess> >(getStyles(u"NumberingStyles"_ustr)->getByName(u"WWNum1"_ustr), u"NumberingRules"_ustr);
727 // This was 1, i.e. the numbering on the second level was "1", not "1.1".
728 // Check the paragraph properties, not the list ones, since they can differ due to overrides
729 uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
730 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), getProperty<sal_Int16>(xPara, u"NumberingLevel"_ustr));
731 CPPUNIT_ASSERT_EQUAL(u"1.1"_ustr, getProperty<OUString>(xPara, u"ListLabelString"_ustr));
733 // The paragraph marker's red font color was inherited by the number portion, this was ff0000.
734 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
735 assertXPath(pXmlDoc, "//SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']/SwFont", "color", u"ffffffff");
738 DECLARE_OOXMLEXPORT_TEST(testNumOverrideStart, "num-override-start.docx")
740 uno::Reference<container::XIndexAccess> xRules = getProperty< uno::Reference<container::XIndexAccess> >(getStyles(u"NumberingStyles"_ustr)->getByName(u"WWNum1"_ustr), u"NumberingRules"_ustr);
741 // List starts with "1.1"
742 CPPUNIT_ASSERT_EQUAL(sal_Int16(1), comphelper::SequenceAsHashMap(xRules->getByIndex(1))[u"StartWith"_ustr].get<sal_Int16>());
743 // But paragraph starts with "1.3"
744 uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
745 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(1), getProperty<sal_Int16>(xPara, u"NumberingLevel"_ustr));
746 OUString listId;
747 CPPUNIT_ASSERT(xPara->getPropertyValue(u"ListId"_ustr) >>= listId);
748 CPPUNIT_ASSERT_EQUAL(u"1.3"_ustr, getProperty<OUString>(xPara, u"ListLabelString"_ustr));
751 DECLARE_OOXMLEXPORT_TEST(testTextboxRightEdge, "textbox-right-edge.docx")
753 // I'm fairly sure this is not specific to DOCX, but the doc model created
754 // by the ODF import doesn't trigger this bug, so let's test this here
755 // instead of uiwriter.
756 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
757 int nShapeLeft = getXPath(pXmlDoc, "//anchored/SwAnchoredDrawObject/bounds", "left").toInt32();
758 int nShapeWidth = getXPath(pXmlDoc, "//anchored/SwAnchoredDrawObject/bounds", "width").toInt32();
759 int nTextboxLeft = getXPath(pXmlDoc, "//anchored/fly/infos/bounds", "left").toInt32();
760 int nTextboxWidth = getXPath(pXmlDoc, "//anchored/fly/infos/bounds", "width").toInt32();
761 // This is a rectangle, make sure the right edge of the textbox is still
762 // inside the draw shape.
763 CPPUNIT_ASSERT(nShapeLeft + nShapeWidth >= nTextboxLeft + nTextboxWidth);
766 DECLARE_OOXMLEXPORT_TEST(testEffectExtentMargin, "effectextent-margin.docx")
768 // This was 318, i.e. oox::drawingml::convertEmuToHmm(114300), effectExtent
769 // wasn't part of the margin, leading to the fly not taking enough space
770 // around itself.
771 CPPUNIT_ASSERT_EQUAL(oox::drawingml::convertEmuToHmm(114300+95250), getProperty<sal_Int32>(getShape(1), u"LeftMargin"_ustr));
774 CPPUNIT_TEST_FIXTURE(Test, testTdf88583)
776 loadAndReload("tdf88583.odt");
777 CPPUNIT_ASSERT_EQUAL(1, getPages());
778 CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(getParagraph(1), u"FillStyle"_ustr));
779 CPPUNIT_ASSERT_EQUAL(Color(0x00cc00), getProperty<Color>(getParagraph(1), u"FillColor"_ustr));
782 DECLARE_OOXMLEXPORT_TEST(testTdf97090, "tdf97090.docx")
784 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
785 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
786 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
787 CPPUNIT_ASSERT_EQUAL(Color(0x95B3D7), getProperty<Color>(xTable->getCellByName(u"A1"_ustr), u"BackColor"_ustr));
789 uno::Reference<container::XEnumerationAccess> paraEnumAccess(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY);
790 assert( paraEnumAccess.is() );
791 uno::Reference<container::XEnumeration> paraEnum = paraEnumAccess->createEnumeration();
793 assert( paraEnum.is() );
794 uno::Reference<beans::XPropertySet> paragraphProperties(paraEnum->nextElement(), uno::UNO_QUERY);
795 assert( paragraphProperties.is() );
796 CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(paragraphProperties, u"FillStyle"_ustr));
797 CPPUNIT_ASSERT_EQUAL(COL_WHITE, getProperty<Color>(paragraphProperties, u"FillColor"_ustr));
800 CPPUNIT_TEST_FIXTURE(Test, testTdf89791)
803 createSwDoc("tdf89791.docx");
804 //tdf#102619 - setting FollowStyle with a not-yet-created style was failing. (Titre is created before Corps de texte).
805 uno::Reference< beans::XPropertySet > properties(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Titre"_ustr), uno::UNO_QUERY);
806 CPPUNIT_ASSERT_EQUAL(u"Corps de texte"_ustr, getProperty<OUString>(properties, u"FollowStyle"_ustr));
808 saveAndReload(mpFilter);
810 properties.set(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Titre"_ustr), uno::UNO_QUERY);
811 CPPUNIT_ASSERT_EQUAL(u"Corps de texte"_ustr, getProperty<OUString>(properties, u"FollowStyle"_ustr));
813 uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL());
814 CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName(u"docProps/custom.xml"_ustr)));
817 DECLARE_OOXMLEXPORT_TEST(testTdf91261, "tdf91261.docx")
819 bool snapToGrid = true;
820 uno::Reference< text::XTextRange > xPara = getParagraph( 2 );
821 uno::Reference< beans::XPropertySet > properties( xPara, uno::UNO_QUERY);
822 properties->getPropertyValue(u"SnapToGrid"_ustr) >>= snapToGrid ;
823 CPPUNIT_ASSERT_EQUAL(false, snapToGrid);
825 uno::Reference< beans::XPropertySet> xStyle(getStyles(u"PageStyles"_ustr)->getByName(u"Standard"_ustr), uno::UNO_QUERY);
826 sal_Int16 nGridMode;
827 xStyle->getPropertyValue(u"GridMode"_ustr) >>= nGridMode;
828 CPPUNIT_ASSERT_EQUAL( sal_Int16(2), nGridMode);
830 bool bGridSnapToChars;
831 xStyle->getPropertyValue(u"GridSnapToChars"_ustr) >>= bGridSnapToChars;
832 CPPUNIT_ASSERT_EQUAL(true, bGridSnapToChars);
835 DECLARE_OOXMLEXPORT_TEST(testTdf89890, "tdf89890.docx")
837 // Numbering picture bullet was too large.
838 uno::Reference<beans::XPropertySet> xPropertySet(getStyles(u"NumberingStyles"_ustr)->getByName(u"WWNum1"_ustr), uno::UNO_QUERY);
839 uno::Reference<container::XIndexAccess> xLevels(xPropertySet->getPropertyValue(u"NumberingRules"_ustr), uno::UNO_QUERY);
840 uno::Sequence<beans::PropertyValue> aProps;
841 xLevels->getByIndex(0) >>= aProps; // 1st level
843 bool bFound = false;
844 for (beans::PropertyValue const& rProp : aProps)
846 if (rProp.Name == "GraphicSize")
848 // Height of the graphic was too large: 4382 after import, then 2485 after roundtrip.
849 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(279), rProp.Value.get<awt::Size>().Height);
850 bFound = true;
853 CPPUNIT_ASSERT(bFound);
856 DECLARE_OOXMLEXPORT_TEST(testTdf91594, "tdf91594.docx")
858 uno::Reference<text::XTextRange> xPara1(getParagraph(1));
859 CPPUNIT_ASSERT_EQUAL(u'\xf0fb', xPara1->getString()[0] );
860 uno::Reference<text::XTextRange> xPara2(getParagraph(2));
861 CPPUNIT_ASSERT_EQUAL(u'\xf0fc', xPara2->getString()[0] );
862 uno::Reference<text::XTextRange> xPara3(getParagraph(3));
863 CPPUNIT_ASSERT_EQUAL(u'\xf0fd', xPara3->getString()[0] );
864 uno::Reference<text::XTextRange> xPara4(getParagraph(4));
865 CPPUNIT_ASSERT_EQUAL(u'\xf0fe', xPara4->getString()[0] );
867 uno::Reference<beans::XPropertySet> xRun(getRun(xPara1,1), uno::UNO_QUERY);
868 CPPUNIT_ASSERT_EQUAL(u"Wingdings"_ustr, getProperty<OUString>(xRun, u"CharFontName"_ustr));
869 CPPUNIT_ASSERT_EQUAL(u"Wingdings"_ustr, getProperty<OUString>(xRun, u"CharFontNameAsian"_ustr));
870 CPPUNIT_ASSERT_EQUAL(u"Wingdings"_ustr, getProperty<OUString>(xRun, u"CharFontNameComplex"_ustr));
872 DECLARE_OOXMLEXPORT_TEST(testTDF99434, "protectedform.docx")
874 css::uno::Reference<css::lang::XMultiServiceFactory> m_xTextFactory(mxComponent, uno::UNO_QUERY);
875 uno::Reference< beans::XPropertySet > xSettings(m_xTextFactory->createInstance(u"com.sun.star.document.Settings"_ustr), uno::UNO_QUERY);
876 uno::Any aProtect = xSettings->getPropertyValue(u"ProtectForm"_ustr);
877 bool bProt = false;
878 aProtect >>= bProt;
879 CPPUNIT_ASSERT(bProt);
882 DECLARE_OOXMLEXPORT_TEST(testTdf44986, "tdf44986.docx")
884 // Check that the table at the second paragraph.
885 uno::Reference<text::XTextTable> xTable(getParagraphOrTable(2), uno::UNO_QUERY);
886 uno::Reference<table::XTableRows> xTableRows = xTable->getRows();
887 // Check the first row of the table, it should have two cells (one separator).
888 // This was 0: the first row had no separators, so it had only one cell, which was too wide.
889 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), getProperty< uno::Sequence<text::TableColumnSeparator> >(xTableRows->getByIndex(0), u"TableColumnSeparators"_ustr).getLength());
890 // Check content of cells, including the newly added gridAfter cell
891 CPPUNIT_ASSERT_EQUAL(u"A1"_ustr, uno::Reference<text::XTextRange>(xTable->getCellByName(u"A1"_ustr), uno::UNO_QUERY_THROW)->getString());
892 CPPUNIT_ASSERT_EQUAL(u"A2"_ustr, uno::Reference<text::XTextRange>(xTable->getCellByName(u"A2"_ustr), uno::UNO_QUERY_THROW)->getString());
893 CPPUNIT_ASSERT_EQUAL(u""_ustr, uno::Reference<text::XTextRange>(xTable->getCellByName(u"B1"_ustr), uno::UNO_QUERY_THROW)->getString());
896 CPPUNIT_TEST_FIXTURE(Test, testTdf118682)
898 loadAndSave("tdf118682.fodt");
899 // Support cell references in table formulas
900 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
902 // Formula fields were completely missing.
903 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r/w:fldChar", 3);
904 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r/w:fldChar", 3);
906 // Cell references were parenthesized: <A1>+<A2> and SUM(<A1:A3>)
907 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:instrText", u" =A1+A2");
908 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:instrText", u" =SUM(A1:A3)");
911 CPPUNIT_TEST_FIXTURE(Test, testTdf133163)
913 loadAndSave("tdf133163.fodt");
914 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
916 // Formula cells were completely missing.
917 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r/w:fldChar", 3);
918 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r/w:fldChar", 3);
920 // Cell references were parenthesized: <A1>+<A2> and SUM(<A1:A3>)
921 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc/w:p/w:r[2]/w:instrText", u" =A1+A2");
922 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[2]/w:instrText", u" =SUM(A1:A3)");
925 CPPUNIT_TEST_FIXTURE(Test, testTdf133647)
927 loadAndSave("tdf133647.docx");
928 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
930 // Keep original formula during round-trip
931 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =SUM(A1,B1)");
932 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =SUM(C1:D1)");
933 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =SUM(A1,5,B1:C1,6)");
934 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[7]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =(1+2)*SUM(C1,D1)");
935 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[8]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =3*(2+SUM(A1:C1)+7)");
936 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[9]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =1+(SUM(1,2))");
937 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[10]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =(SUM(C1,5)*(2+7))*(3+SUM(1,B1))");
938 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[11]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =sum(a1,b1)");
941 CPPUNIT_TEST_FIXTURE(Test, testTdf123386)
943 loadAndSave("tdf123386.docx");
944 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
946 // Keep original formula during round-trip
947 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =A1 < 2");
948 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =B1 > 1");
949 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[5]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =C1=3");
950 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[6]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =D1 <> 3");
951 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[7]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =AND(A1=1,B1=2)");
952 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[8]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =AND((A1<1),(B1<>2))");
953 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[9]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =OR(A1=1,B1=2)");
954 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[10]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =OR(TRUE,FALSE)");
955 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[11]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =NOT(TRUE)");
956 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[12]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =AND(1,DEFINED(ABC1))");
959 CPPUNIT_TEST_FIXTURE(Test, testTdf123389)
961 loadAndSave("tdf123389.docx");
962 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
964 // Keep original formula during round-trip
965 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[3]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =ROUND(2.345,1)");
966 assertXPathContent(pXmlDoc, "/w:document/w:body/w:tbl/w:tr[4]/w:tc[4]/w:p/w:r[2]/w:instrText", u" =ROUND(A1,2)");
969 DECLARE_OOXMLEXPORT_TEST(testTdf106953, "tdf106953.docx")
971 uno::Reference<container::XIndexAccess> xRules = getProperty< uno::Reference<container::XIndexAccess> >(getStyles(u"NumberingStyles"_ustr)->getByName(u"WWNum1"_ustr), u"NumberingRules"_ustr);
972 // This was -635, so the tab of the numbering expanded to a small value instead of matching Word's larger value.
973 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), comphelper::SequenceAsHashMap(xRules->getByIndex(0))[u"FirstLineIndent"_ustr].get<sal_Int32>());
976 CPPUNIT_TEST_FIXTURE(Test, testTdf115094v3)
978 createSwDoc("tdf115094v3.docx");
980 SwDoc* pDoc = getSwDoc();
981 auto& rSpzFormats = *pDoc->GetSpzFrameFormats();
982 auto pFormat = rSpzFormats[0];
983 // Without the fix, this has failed with:
984 // - Expected: 1991
985 // - Actual : 1883
986 // i.e. some unwanted ~-2mm left margin appeared.
987 CPPUNIT_ASSERT_EQUAL(static_cast<SwTwips>(1991), pFormat->GetHoriOrient().GetPos());
989 save(mpFilter);
990 // floating table is now exported directly without surrounding frame
991 xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
993 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tblPr/w:tblpPr", "tblpX", u"1996");
994 assertXPath(pXmlDoc, "/w:document/w:body/w:tbl/w:tblPr/w:tblpPr", "tblpY", u"1064");
997 CPPUNIT_PLUGIN_IMPLEMENT();
999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */