1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
11 #define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
13 #include <AppKit/AppKit.h>
17 #include <swmodeltestbase.hxx>
19 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
20 #include <com/sun/star/embed/Aspects.hpp>
21 #include <com/sun/star/text/WritingMode2.hpp>
22 #include <com/sun/star/style/BreakType.hpp>
23 #include <com/sun/star/text/XTextDocument.hpp>
24 #include <com/sun/star/text/XTextTable.hpp>
26 #include <comphelper/propertysequence.hxx>
27 #include <vcl/BitmapReadAccess.hxx>
28 #include <vcl/graphicfilter.hxx>
29 #include <xmloff/odffields.hxx>
32 #include <IDocumentMarkAccess.hxx>
33 #include <IDocumentLayoutAccess.hxx>
35 #include <sortedobjs.hxx>
36 #include <anchoredobject.hxx>
39 #include <unotxdoc.hxx>
41 #include <rootfrm.hxx>
43 #include <pagefrm.hxx>
45 #include <flyfrms.hxx>
48 class Test
: public SwModelTestBase
52 : SwModelTestBase("/sw/qa/extras/ooxmlimport/data/", "Office Open XML Text")
57 CPPUNIT_TEST_FIXTURE(Test
, testTdf143476LockedCanvas_twoShapes
)
59 // Given a lockedCanvas in a docx document with compatibility to Word version 12 (2007).
60 // It contains two shapes. Error was, that the lockedCanvas was not imported as group at all,
61 // and only one shape was imported and that one was scaled to lockedCanvas area.
62 createSwDoc("tdf143476_lockedCanvas_twoShapes.docx");
63 // The group shape corresponds to the lockedCanvas.
64 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY
);
65 CPPUNIT_ASSERT(xGroup
.is());
66 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), xGroup
->getCount());
67 uno::Reference
<drawing::XShape
> xShape(xGroup
->getByIndex(1), uno::UNO_QUERY
);
68 CPPUNIT_ASSERT_EQUAL(sal_Int32(14200), xShape
->getPosition().X
);
69 CPPUNIT_ASSERT_EQUAL(sal_Int32(1120), xShape
->getPosition().Y
);
70 CPPUNIT_ASSERT_EQUAL(sal_Int32(1928), xShape
->getSize().Width
);
71 CPPUNIT_ASSERT_EQUAL(sal_Int32(1593), xShape
->getSize().Height
);
74 CPPUNIT_TEST_FIXTURE(Test
, testTdf143476LockedCanvas_position
)
76 // Given a lockedCanvas in a docx document with compatibility to Word version 12 (2007).
77 // Tests fix for regression introduced by 3262fc5ef3bde5b158909d11ccb008161ea95519
78 // Error was, that the imported shape had wrong position.
79 createSwDoc("tdf143476_lockedCanvas_position.docx");
80 // The group shape corresponds to the lockedCanvas.
81 uno::Reference
<drawing::XShape
> xGroupShape(getShape(1), uno::UNO_QUERY
);
82 // Without fix in place the test failed with position 185|947.
83 CPPUNIT_ASSERT_EQUAL(sal_Int32(2351), xGroupShape
->getPosition().X
);
84 CPPUNIT_ASSERT_EQUAL(sal_Int32(26), xGroupShape
->getPosition().Y
);
87 CPPUNIT_TEST_FIXTURE(Test
, testTdf143476LockedCanvas_image_line
)
89 // Given a lockedCanvas in a docx document with compatibility to Word version 12 (2007).
90 // It contains an image and a line. Error was, that both were not imported.
91 createSwDoc("tdf143476_lockedCanvas_image_line.docx");
92 CPPUNIT_ASSERT_MESSAGE("No shapes imported", getShapes() > 0);
95 CPPUNIT_TEST_FIXTURE(Test
, testTdf143475rotatedWord2007imageInline
)
97 // Given a docx document with compatibility to Word version 12 (2007), which has a shape
98 // rotated by 75deg. Similar to testTdf143475rotatedWord2007image but with inline anchored
99 // shape, as in bug report.
100 createSwDoc("tdf143475_rotatedWord2007imageInline.docx");
102 // Word 2007 does not swap width and height for rotated images as done in later versions.
103 // This was not considered and lead to wrong distance to text on import and wrong effectExtent
105 // Import fails without fix with left: expected 1258 actual -743 ; right expected 1256 actual -743;
106 // top: expected 14 actual 2013; bottom: expected 0 actual 1960;
107 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1258), getProperty
<sal_Int32
>(getShape(1), "LeftMargin"),
109 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1256),
110 getProperty
<sal_Int32
>(getShape(1), "RightMargin"), 1);
111 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(14), getProperty
<sal_Int32
>(getShape(1), "TopMargin"),
113 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(getShape(1), "BottomMargin"),
116 // Because LO made the same error on export, which inverts the import error, import-export-cycle
117 // does not fail without the patch. Therefore no export test.
120 CPPUNIT_TEST_FIXTURE(Test
, testTdf143475rotatedWord2007image
)
122 // Given a docx document with compatibility to Word version 12 (2007), which has a shape
124 createSwDoc("tdf143475_rotatedWord2007image.docx");
126 // Word 2007 does not swap width and height for rotated images as done in later versions.
127 // This was not considered and lead to wrong distance to text on import and wrong effectExtent
129 // Import fails without fix with left: expected 1252 actual -746 ; right expected 1256 actual -743;
130 // top: expected 12 actual 2013; bottom: expected 0 actual 1960;
131 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1252), getProperty
<sal_Int32
>(getShape(1), "LeftMargin"),
133 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(1256),
134 getProperty
<sal_Int32
>(getShape(1), "RightMargin"), 1);
135 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(12), getProperty
<sal_Int32
>(getShape(1), "TopMargin"),
137 CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(0), getProperty
<sal_Int32
>(getShape(1), "BottomMargin"),
140 // Because LO made the same error on export, which inverts the import error, import-export-cycle
141 // does not fail without the patch. Therefore no export test.
144 CPPUNIT_TEST_FIXTURE(Test
, testTdf143219ContourWrapRotate
)
146 createSwDoc("tdf143219_ContourWrap_rotate.docx");
147 const uno::Reference
<drawing::XShape
> xShape
= getShape(1);
148 const uno::Reference
<beans::XPropertySet
> xShapeProps(xShape
, uno::UNO_QUERY_THROW
);
149 sal_Int32 nWrapDistanceLeft
= -1;
150 sal_Int32 nWrapDistanceRight
= -1;
151 sal_Int32 nWrapDistanceTop
= -1;
152 sal_Int32 nWrapDistanceBottom
= -1;
153 xShapeProps
->getPropertyValue("LeftMargin") >>= nWrapDistanceLeft
;
154 xShapeProps
->getPropertyValue("RightMargin") >>= nWrapDistanceRight
;
155 xShapeProps
->getPropertyValue("TopMargin") >>= nWrapDistanceTop
;
156 xShapeProps
->getPropertyValue("BottomMargin") >>= nWrapDistanceBottom
;
157 // Word and Writer use different concepts for contour wrap. LO needs wrap margins to
158 // approximate Word's rendering.
159 // Without the fix in place left and right margin were too large, top and bottom margin too
160 // small. The test would have failed
161 // ... with expected 182 actual 1005.
162 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("LeftMargin", 182, nWrapDistanceLeft
, 1);
163 // ... with expected 183 actual 1005
164 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("RightMargin", 183, nWrapDistanceRight
, 1);
165 // ... with expected 42 actual 0
166 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("TopMargin", 42, nWrapDistanceTop
, 1);
167 // ... with expected 41 actual 0
168 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("BottomMargin", 41, nWrapDistanceBottom
, 1);
171 CPPUNIT_TEST_FIXTURE(Test
, testTdf108545_embeddedDocxIcon
)
173 createSwDoc("tdf108545_embeddedDocxIcon.docx");
174 uno::Reference
<document::XEmbeddedObjectSupplier2
> xSupplier(getShape(1), uno::UNO_QUERY
);
175 CPPUNIT_ASSERT_EQUAL(embed::Aspects::MSOLE_ICON
, xSupplier
->getAspect());
178 CPPUNIT_TEST_FIXTURE(Test
, testTdf121203
)
180 createSwDoc("tdf121203.docx");
181 // We imported the date field
182 uno::Reference
<beans::XPropertySet
> xTextPortion(getRun(getParagraph(1), 1), uno::UNO_QUERY
);
183 OUString aPortionType
;
184 xTextPortion
->getPropertyValue("TextPortionType") >>= aPortionType
;
185 CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType
);
187 // Custom sdt date content is imported correctly
188 uno::Reference
<text::XTextContent
> xContentControl
;
189 xTextPortion
->getPropertyValue("ContentControl") >>= xContentControl
;
190 uno::Reference
<beans::XPropertySet
> xContentControlProps(xContentControl
, uno::UNO_QUERY
);
192 xContentControlProps
->getPropertyValue("Date") >>= bDate
;
193 CPPUNIT_ASSERT(bDate
);
195 OUString sDateFormat
;
196 xContentControlProps
->getPropertyValue("DateFormat") >>= sDateFormat
;
199 xContentControlProps
->getPropertyValue("DateLanguage") >>= sLang
;
201 uno::Reference
<container::XEnumerationAccess
> xContentControlEnumAccess(xContentControl
,
203 uno::Reference
<container::XEnumeration
> xContentControlEnum
204 = xContentControlEnumAccess
->createEnumeration();
205 uno::Reference
<text::XTextRange
> xTextPortionRange(xContentControlEnum
->nextElement(),
207 OUString sCurrentDate
= xTextPortionRange
->getString();
208 CPPUNIT_ASSERT_EQUAL(OUString("dd-MMM-yy"), sDateFormat
);
209 CPPUNIT_ASSERT_EQUAL(OUString("en-GB"), sLang
);
210 CPPUNIT_ASSERT_EQUAL(OUString("17-Oct-2018 09:00"), sCurrentDate
);
213 CPPUNIT_TEST_FIXTURE(Test
, testTdf109053
)
215 createSwDoc("tdf109053.docx");
216 // Table was imported into a text frame which led to a one page document
217 // Originally the table takes two pages, so Writer should import it accordingly.
218 CPPUNIT_ASSERT_EQUAL(2, getPages());
221 CPPUNIT_TEST_FIXTURE(Test
, testTdf121664
)
223 createSwDoc("tdf121664.docx");
224 uno::Reference
<text::XLineNumberingProperties
> xLineNumbering(mxComponent
, uno::UNO_QUERY
);
225 CPPUNIT_ASSERT(xLineNumbering
.is());
226 // Without the accompanying fix in place, numbering did not restart on the
229 getProperty
<bool>(xLineNumbering
->getLineNumberingProperties(), "RestartAtEachPage"));
232 CPPUNIT_TEST_FIXTURE(Test
, testTdf108849
)
234 createSwDoc("tdf108849.docx");
235 // sectPr element that is child element of body must be the last child. However, Word accepts it
236 // in wrong places, and we should do the same (bug-to-bug compatibility) without creating extra sections.
237 CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
238 CPPUNIT_ASSERT_EQUAL_MESSAGE("Misplaced body-level sectPr's create extra sections!", 2,
242 CPPUNIT_TEST_FIXTURE(Test
, testTdf97038
)
244 createSwDoc("tdf97038.docx");
245 // Without the accompanying fix in place, this test would have failed, as the importer lost the
246 // fLayoutInCell shape property for wrap-though shapes.
247 CPPUNIT_ASSERT(getProperty
<bool>(getShapeByName(u
"Kep2"), "IsFollowingTextFlow"));
250 CPPUNIT_TEST_FIXTURE(Test
, testTdf114212
)
252 createSwDoc("tdf114212.docx");
253 // Without the accompanying fix in place, this test would have failed with:
256 OUString aTop
= parseDump("//anchored/fly[1]/infos/bounds", "top");
257 CPPUNIT_ASSERT_EQUAL(OUString("1428"), aTop
);
260 CPPUNIT_TEST_FIXTURE(Test
, testTdf109524
)
262 createSwDoc("tdf109524.docx");
263 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
264 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
266 // The table should have a small width (just to hold the short text in its single cell).
267 // Until it's correctly implemented, we assign it 100% relative width.
268 // Previously, the table (without explicitly set width) had huge actual width
269 // and extended far outside of page's right border.
270 CPPUNIT_ASSERT_EQUAL(true, getProperty
<bool>(xTables
->getByIndex(0), "IsWidthRelative"));
271 CPPUNIT_ASSERT_EQUAL(sal_Int16(100),
272 getProperty
<sal_Int16
>(xTables
->getByIndex(0), "RelativeWidth"));
275 CPPUNIT_TEST_FIXTURE(Test
, testTdf120547
)
277 createSwDoc("tdf120547.docx");
278 uno::Reference
<drawing::XShape
> xGroupShape
= getShape(1);
279 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY
);
280 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(3), xGroup
->getCount());
282 awt::Point aPosGroup
= xGroupShape
->getPosition();
283 awt::Size aSizeGroup
= xGroupShape
->getSize();
285 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosGroup
.X
);
286 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosGroup
.Y
);
287 CPPUNIT_ASSERT_EQUAL(sal_Int32(9091), aSizeGroup
.Width
);
288 CPPUNIT_ASSERT_EQUAL(sal_Int32(27940), aSizeGroup
.Height
);
290 // Without the fix in place, this test would have failed at many places
291 // as the three shapes in the group would have had an incorrect position,
292 // an incorrect width or an incorrect height.
294 uno::Reference
<drawing::XShape
> xShape1(xGroup
->getByIndex(0), uno::UNO_QUERY_THROW
);
295 awt::Point aPosShape1
= xShape1
->getPosition();
296 awt::Size aSizeShape1
= xShape1
->getSize();
298 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosShape1
.X
);
299 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosShape1
.Y
);
300 CPPUNIT_ASSERT_EQUAL(sal_Int32(9066), aSizeShape1
.Width
);
301 CPPUNIT_ASSERT_EQUAL(sal_Int32(27905), aSizeShape1
.Height
);
303 uno::Reference
<drawing::XShape
> xShape2(xGroup
->getByIndex(1), uno::UNO_QUERY_THROW
);
304 awt::Point aPosShape2
= xShape2
->getPosition();
305 awt::Size aSizeShape2
= xShape2
->getSize();
307 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosShape2
.X
);
308 CPPUNIT_ASSERT_EQUAL(sal_Int32(20745), aPosShape2
.Y
);
309 CPPUNIT_ASSERT_EQUAL(sal_Int32(9066), aSizeShape2
.Width
);
310 CPPUNIT_ASSERT_EQUAL(sal_Int32(7195), aSizeShape2
.Height
);
312 // The second shape is a group of 3 shapes
313 uno::Reference
<container::XIndexAccess
> xGroup2(xGroup
->getByIndex(1), uno::UNO_QUERY
);
314 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(3), xGroup2
->getCount());
316 uno::Reference
<drawing::XShape
> xShape3(xGroup
->getByIndex(2), uno::UNO_QUERY_THROW
);
317 awt::Point aPosShape3
= xShape3
->getPosition();
318 awt::Size aSizeShape3
= xShape3
->getSize();
320 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosShape3
.X
);
321 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aPosShape3
.Y
);
322 CPPUNIT_ASSERT_EQUAL(sal_Int32(9091), aSizeShape3
.Width
);
323 CPPUNIT_ASSERT_EQUAL(sal_Int32(8073), aSizeShape3
.Height
);
326 CPPUNIT_TEST_FIXTURE(Test
, testTdf118693
)
328 createSwDoc("tdf118693.docx");
329 uno::Reference
<drawing::XShape
> xGroupShape
= getShape(1);
330 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY
);
331 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), xGroup
->getCount());
333 awt::Point aPosGroup
= xGroupShape
->getPosition();
334 awt::Size aSizeGroup
= xGroupShape
->getSize();
336 CPPUNIT_ASSERT_EQUAL(sal_Int32(10162), aPosGroup
.X
);
337 CPPUNIT_ASSERT_EQUAL(sal_Int32(118), aPosGroup
.Y
);
338 // As of LO7.2 width by 1 too small, height by 2 too small. Reason unclear.
339 CPPUNIT_ASSERT_EQUAL(sal_Int32(6368), aSizeGroup
.Width
);
340 CPPUNIT_ASSERT_EQUAL(sal_Int32(4981), aSizeGroup
.Height
);
342 // Without the fix in place, this test would have failed at many places
343 // as the first shape in the group would have had an incorrect position,
344 // an incorrect width or an incorrect height.
346 uno::Reference
<drawing::XShape
> xShape1(xGroup
->getByIndex(0), uno::UNO_QUERY_THROW
);
347 awt::Point aPosShape1
= xShape1
->getPosition();
348 awt::Size aSizeShape1
= xShape1
->getSize();
350 CPPUNIT_ASSERT_EQUAL(sal_Int32(12861), aPosShape1
.X
);
351 CPPUNIT_ASSERT_EQUAL(sal_Int32(146), aPosShape1
.Y
);
352 CPPUNIT_ASSERT_EQUAL(sal_Int32(3669), aSizeShape1
.Width
);
353 CPPUNIT_ASSERT_EQUAL(sal_Int32(4912), aSizeShape1
.Height
);
355 uno::Reference
<drawing::XShape
> xShape2(xGroup
->getByIndex(1), uno::UNO_QUERY_THROW
);
356 awt::Point aPosShape2
= xShape2
->getPosition();
357 awt::Size aSizeShape2
= xShape2
->getSize();
359 CPPUNIT_ASSERT_EQUAL(sal_Int32(10162), aPosShape2
.X
);
360 CPPUNIT_ASSERT_EQUAL(sal_Int32(118), aPosShape2
.Y
);
361 CPPUNIT_ASSERT_EQUAL(sal_Int32(4595), aSizeShape2
.Width
);
362 CPPUNIT_ASSERT_EQUAL(sal_Int32(4981), aSizeShape2
.Height
);
365 CPPUNIT_TEST_FIXTURE(Test
, testGroupShapeFontName
)
367 createSwDoc("groupshape-fontname.docx");
368 // Font names inside a group shape were not imported
369 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY
);
370 uno::Reference
<text::XText
> xText
371 = uno::Reference
<text::XTextRange
>(xGroup
->getByIndex(1), uno::UNO_QUERY_THROW
)->getText();
373 CPPUNIT_ASSERT_EQUAL(
375 getProperty
<OUString
>(getRun(getParagraphOfText(1, xText
), 1), "CharFontName"));
376 CPPUNIT_ASSERT_EQUAL(
378 getProperty
<OUString
>(getRun(getParagraphOfText(1, xText
), 1), "CharFontNameComplex"));
379 CPPUNIT_ASSERT_EQUAL(
381 getProperty
<OUString
>(getRun(getParagraphOfText(1, xText
), 1), "CharFontNameAsian"));
384 CPPUNIT_TEST_FIXTURE(Test
, testTdf124600
)
386 createSwDoc("tdf124600.docx");
387 // uno::Reference<drawing::XShape> xShape = getShape(1);
388 // Without the accompanying fix in place, this test would have failed with:
391 // i.e. the shape had an unexpected left margin, but not in Word.
392 // Regina: LO needs a left margin to get the same rendering as Word, because Word aligns the
393 // shape with the outer edge of the border, but LibreOffice aligns with the snap rectangle.
394 // Expected: 0 is wrong. ToDo: The current margin is wrong and needs to be fixed. Then activate
395 // the test again with the correct margin.
396 // CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
397 // getProperty<sal_Int32>(xShape, "HoriOrientPosition"));
399 // Make sure that "Shape 1 text" (anchored in the header) has the same left margin as the body
401 OUString aShapeTextLeft
= parseDump("/root/page/header/txt/anchored/fly/infos/bounds", "left");
402 OUString aBodyTextLeft
= parseDump("/root/page/body/txt/infos/bounds", "left");
403 // Without the accompanying fix in place, this test would have failed with:
406 // i.e. there was a >0 left margin on the text of the shape, resulting in incorrect horizontal
408 CPPUNIT_ASSERT_DOUBLES_EQUAL(aBodyTextLeft
.toDouble(), aShapeTextLeft
.toDouble(), 1.0);
411 CPPUNIT_TEST_FIXTURE(Test
, testTdf120548
)
413 createSwDoc("tdf120548.docx");
414 // Without the accompanying fix in place, this test would have failed with 'Expected: 00ff0000;
415 // Actual: ffffffff', i.e. the numbering portion was black, not red.
416 CPPUNIT_ASSERT_EQUAL(
417 OUString("00ff0000"),
418 parseDump("//SwFieldPortion[@type='PortionType::Number']/SwFont", "color"));
421 CPPUNIT_TEST_FIXTURE(Test
, test120551
)
423 createSwDoc("tdf120551.docx");
424 auto nHoriOrientPosition
= getProperty
<sal_Int32
>(getShape(1), "HoriOrientPosition");
425 // Without the accompanying fix in place, this test would have failed with
426 // 'Expected: 430, Actual : -2542'.
427 // CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(430), nHoriOrientPosition);
428 // File 140335EMU = 389,8Hmm
429 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(390), nHoriOrientPosition
);
432 CPPUNIT_TEST_FIXTURE(Test
, testTdf111550
)
434 createSwDoc("tdf111550.docx");
435 // The test document has following ill-formed structure:
443 // <w:t>[outer:A2]</w:t>
444 // <w:br w:type="textWrapping"/>
451 // <w:t>[inner:A1]</w:t>
462 // i.e., a <w:tbl> as direct child of <w:p> inside another table.
463 // Word accepts that illegal OOXML, and treats it as equal to
474 // <w:t>[outer:A2]</w:t>
475 // <w:br w:type="textWrapping"/>
478 // <w:t>[inner:A1]</w:t>
488 // i.e., moves all contents of the outer paragraph into the inner table's first paragraph.
490 CPPUNIT_ASSERT_EQUAL(2, getParagraphs());
492 uno::Reference
<text::XTextContent
> outerTable
= getParagraphOrTable(1);
493 getCell(outerTable
, "A1", "[outer:A1]");
494 uno::Reference
<text::XText
> cellA2(getCell(outerTable
, "A2"), uno::UNO_QUERY_THROW
);
495 uno::Reference
<text::XTextContent
> innerTable
= getParagraphOrTable(1, cellA2
);
496 getCell(innerTable
, "A1", "[outer:A2]\n[inner:A1]");
499 CPPUNIT_TEST_FIXTURE(Test
, testTdf117843
)
501 createSwDoc("tdf117843.docx");
502 uno::Reference
<container::XNameAccess
> xPageStyles
= getStyles("PageStyles");
503 uno::Reference
<style::XStyle
> xPageStyle(xPageStyles
->getByName("Standard"), uno::UNO_QUERY
);
504 uno::Reference
<text::XText
> xHeaderText
505 = getProperty
<uno::Reference
<text::XText
>>(xPageStyle
, "HeaderText");
506 // This was 4025, increased top paragraph margin was unexpected.
507 CPPUNIT_ASSERT_EQUAL(
508 static_cast<sal_Int32
>(0),
509 getProperty
<sal_Int32
>(getParagraphOfText(1, xHeaderText
), "ParaTopMargin"));
512 // related tdf#124754
513 CPPUNIT_TEST_FIXTURE(Test
, testTdf43017
)
515 createSwDoc("tdf43017.docx");
516 uno::Reference
<text::XTextRange
> xParagraph
= getParagraph(1);
517 uno::Reference
<text::XTextRange
> xText
= getRun(xParagraph
, 2, "kick the bucket");
519 // Ensure that hyperlink text color is not blue (0x0000ff), but default (-1)
520 CPPUNIT_ASSERT_EQUAL_MESSAGE("Hyperlink color should be black!", sal_Int32(-1),
521 getProperty
<sal_Int32
>(xText
, "CharColor"));
524 CPPUNIT_TEST_FIXTURE(Test
, testTdf127778
)
526 createSwDoc("tdf127778.docx");
527 xmlDocUniquePtr pLayout
= parseLayoutDump();
528 // Without the accompanying fix in place, this test would have failed with:
529 // equality assertion failed
532 // i.e. the 2nd page had an unexpected header.
533 assertXPath(pLayout
, "//page[2]/header", 0);
537 CPPUNIT_TEST_FIXTURE(Test
, testTdf124754
)
539 createSwDoc("tdf124754.docx");
540 uno::Reference
<text::XText
> textbox(getShape(1), uno::UNO_QUERY
);
541 CPPUNIT_ASSERT_EQUAL(1, getParagraphs(textbox
));
543 uno::Reference
<text::XTextRange
> xParagraph
= getParagraphOfText(1, textbox
);
544 uno::Reference
<text::XTextRange
> xText
= getRun(xParagraph
, 2);
546 // Ensure that hyperlink text color is not black
547 CPPUNIT_ASSERT_EQUAL_MESSAGE("Hyperlink color should be not black!", sal_Int32(353217),
548 getProperty
<sal_Int32
>(xText
, "CharColor"));
551 CPPUNIT_TEST_FIXTURE(Test
, testTextCopy
)
553 createSwDoc("text-copy.docx");
554 // The document has a header on the second page that is copied as part of the import process.
555 // The header has a single paragraph: make sure shapes anchored to it are not lost.
556 // Note that the single paragraph itself has no text portions.
557 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
558 uno::Reference
<container::XEnumerationAccess
> xParaEnumAccess(xTextDocument
->getText(),
560 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
561 uno::Reference
<beans::XPropertySet
> xPara
;
562 while (xParaEnum
->hasMoreElements())
564 xPara
.set(xParaEnum
->nextElement(), uno::UNO_QUERY
);
566 auto aPageStyleName
= getProperty
<OUString
>(xPara
, "PageStyleName");
567 uno::Reference
<beans::XPropertySet
> xPageStyle(
568 getStyles("PageStyles")->getByName(aPageStyleName
), uno::UNO_QUERY
);
569 auto xHeaderText
= getProperty
<uno::Reference
<text::XText
>>(xPageStyle
, "HeaderText");
570 uno::Reference
<text::XTextRange
> xHeaderPara
= getParagraphOfText(1, xHeaderText
);
571 auto aTextPortionType
= getProperty
<OUString
>(getRun(xHeaderPara
, 1), "TextPortionType");
572 // Without the accompanying fix in place, this test would have failed with:
575 // i.e. the second page's header had no anchored shapes.
576 CPPUNIT_ASSERT_EQUAL(OUString("Frame"), aTextPortionType
);
579 CPPUNIT_TEST_FIXTURE(Test
, testTdf112443
)
581 createSwDoc("tdf112443.docx");
582 // the position of the flying text frame should be off page
583 // 30624 below its anchor
584 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
585 CPPUNIT_ASSERT(pTextDoc
);
586 SwDoc
* pDoc
= pTextDoc
->GetDocShell()->GetDoc();
587 SwRootFrame
* pRootFrame
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
588 const SwRect aPageRect
= pRootFrame
->getFrameArea();
589 const SwRect
aShapeRect(getShape(1)->getPosition().X
, getShape(1)->getPosition().Y
,
590 getShape(1)->getSize().Width
, getShape(1)->getSize().Height
);
591 CPPUNIT_ASSERT_MESSAGE("The textframe must be off-page!", !aPageRect
.Contains(aShapeRect
));
593 //OUString aTop = parseDump("//anchored/fly[1]/infos/bounds", "top");
594 //CPPUNIT_ASSERT_EQUAL(sal_Int32(30624), aTop.toInt32() );
597 // DOCX: Textbox wrap differs in MSO and LO
598 // Both should layout text regardless of existing text box
599 // and as result only one page should be generated.
600 CPPUNIT_TEST_FIXTURE(Test
, testTdf113182
)
602 createSwDoc("tdf113182.docx");
603 CPPUNIT_ASSERT_EQUAL(1, getPages());
606 CPPUNIT_TEST_FIXTURE(Test
, testBtlrFrameVml
)
608 createSwDoc("btlr-frame-vml.docx");
609 uno::Reference
<beans::XPropertySet
> xTextFrame(getShape(1), uno::UNO_QUERY
);
610 CPPUNIT_ASSERT(xTextFrame
.is());
612 auto nActual
= getProperty
<sal_Int16
>(xTextFrame
, "WritingMode");
613 // Without the accompanying fix in place, this test would have failed with 'Expected: 5; Actual:
614 // 4', i.e. writing direction was inherited from page, instead of explicit btlr.
615 CPPUNIT_ASSERT_EQUAL(text::WritingMode2::BT_LR
, nActual
);
618 CPPUNIT_TEST_FIXTURE(Test
, testTdf124398
)
620 createSwDoc("tdf124398.docx");
621 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY
);
622 CPPUNIT_ASSERT(xGroup
.is());
623 // Without the accompanying fix in place, this test would have failed with 'Expected: 2; Actual:
624 // 1', i.e. the chart children of the group shape was lost.
625 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(2), xGroup
->getCount());
627 uno::Reference
<drawing::XShapeDescriptor
> xShape(xGroup
->getByIndex(1), uno::UNO_QUERY
);
628 CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.drawing.OLE2Shape"), xShape
->getShapeType());
631 CPPUNIT_TEST_FIXTURE(Test
, testTdf104167
)
633 createSwDoc("tdf104167.docx");
634 // Make sure that heading 1 paragraphs start on a new page.
635 uno::Any xStyle
= getStyles("ParagraphStyles")->getByName("Heading 1");
636 // Without the accompanying fix in place, this test would have failed with:
639 // i.e. the <w:pageBreakBefore/> was lost on import.
640 CPPUNIT_ASSERT_EQUAL(style::BreakType_PAGE_BEFORE
,
641 getProperty
<style::BreakType
>(xStyle
, "BreakType"));
644 CPPUNIT_TEST_FIXTURE(Test
, testTdf113946
)
646 createSwDoc("tdf113946.docx");
647 OUString aTop
= parseDump("/root/page/body/txt/anchored/SwAnchoredDrawObject/bounds", "top");
648 // tdf#106792 Checked loading of tdf113946.docx. Before the change, the expected
649 // value of this test was "1696". Opening the file shows a single short line anchored
650 // at the doc start. Only diff is that in 'old' version it is slightly rotated, in 'new'
651 // version line is strict horizontal. Checked against MSWord2013, there the line
652 // is also not rotated -> the change is to the better, correct the expected result here.
653 CPPUNIT_ASSERT_EQUAL(OUString("1695"), aTop
);
656 CPPUNIT_TEST_FIXTURE(Test
, testTdf121804
)
658 createSwDoc("tdf121804.docx");
659 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY
);
660 uno::Reference
<text::XTextRange
> xShape(xGroup
->getByIndex(0), uno::UNO_QUERY
);
661 uno::Reference
<text::XTextRange
> xFirstPara
= getParagraphOfText(1, xShape
->getText());
662 uno::Reference
<text::XTextRange
> xFirstRun
= getRun(xFirstPara
, 1);
663 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(0),
664 getProperty
<sal_Int32
>(xFirstRun
, "CharEscapement"));
665 // This failed with a NoSuchElementException, super/subscript property was
666 // lost on import, so the whole paragraph was a single run.
667 uno::Reference
<text::XTextRange
> xSecondRun
= getRun(xFirstPara
, 2);
668 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(14000),
669 getProperty
<sal_Int32
>(xSecondRun
, "CharEscapement"));
670 uno::Reference
<text::XTextRange
> xThirdRun
= getRun(xFirstPara
, 3);
671 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32
>(-14000),
672 getProperty
<sal_Int32
>(xThirdRun
, "CharEscapement"));
675 CPPUNIT_TEST_FIXTURE(Test
, testTdf114217
)
677 // The floating table was not split between page 1 and page 2.
678 createSwDoc("tdf114217.docx");
679 SwDoc
* pDoc
= getSwDoc();
680 SwRootFrame
* pLayout
= pDoc
->getIDocumentLayoutAccess().GetCurrentLayout();
681 auto pPage1
= dynamic_cast<SwPageFrame
*>(pLayout
->Lower());
682 CPPUNIT_ASSERT(pPage1
);
683 const SwSortedObjs
& rPage1Objs
= *pPage1
->GetSortedObjs();
684 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs
.size());
685 auto pPage1Fly
= dynamic_cast<SwFlyAtContentFrame
*>(rPage1Objs
[0]);
686 CPPUNIT_ASSERT(pPage1Fly
);
687 auto pTab1
= dynamic_cast<SwTabFrame
*>(pPage1Fly
->GetLower());
688 CPPUNIT_ASSERT(pTab1
);
689 CPPUNIT_ASSERT(pTab1
->HasFollow());
692 CPPUNIT_TEST_FIXTURE(Test
, testTdf119200
)
694 createSwDoc("tdf119200.docx");
695 auto xPara
= getParagraph(1);
696 // Check that we import MathType functional symbols as symbols, not functions with missing args
697 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2208 } {}"), getFormula(getRun(xPara
, 1)));
698 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2209 } {}"), getFormula(getRun(xPara
, 2)));
699 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2282 } {}"), getFormula(getRun(xPara
, 3)));
700 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2283 } {}"), getFormula(getRun(xPara
, 4)));
701 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2284 } {}"), getFormula(getRun(xPara
, 5)));
702 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2286 } {}"), getFormula(getRun(xPara
, 6)));
703 CPPUNIT_ASSERT_EQUAL(OUString(u
" size 12{ func \u2287 } {}"), getFormula(getRun(xPara
, 7)));
706 CPPUNIT_TEST_FIXTURE(Test
, testTdf115094
)
708 createSwDoc("tdf115094.docx");
709 // anchor of graphic has to be the text in the text frame
710 // xray ThisComponent.DrawPage(1).Anchor.Text
711 uno::Reference
<text::XTextContent
> xShape(getShape(2), uno::UNO_QUERY
);
712 uno::Reference
<text::XTextRange
> xText1
= xShape
->getAnchor()->getText();
714 // xray ThisComponent.TextTables(0).getCellByName("A1")
715 uno::Reference
<text::XTextTablesSupplier
> xTablesSupplier(mxComponent
, uno::UNO_QUERY
);
716 uno::Reference
<container::XIndexAccess
> xTables(xTablesSupplier
->getTextTables(),
718 uno::Reference
<text::XTextTable
> xTable(xTables
->getByIndex(0), uno::UNO_QUERY
);
719 uno::Reference
<text::XTextRange
> xText2(xTable
->getCellByName("A1"), uno::UNO_QUERY
);
721 CPPUNIT_ASSERT_EQUAL(xText1
.get(), xText2
.get());
724 CPPUNIT_TEST_FIXTURE(Test
, testTdf115094v2
)
726 createSwDoc("tdf115094v2.docx");
727 // layoutInCell="1" combined with <wp:wrapNone/>
729 CPPUNIT_ASSERT(getProperty
<bool>(getShapeByName(u
"Grafik 18"), "IsFollowingTextFlow"));
730 CPPUNIT_ASSERT(getProperty
<bool>(getShapeByName(u
"Grafik 19"), "IsFollowingTextFlow"));
733 CPPUNIT_TEST_FIXTURE(Test
, testTdf122224
)
735 createSwDoc("tdf122224.docx");
736 uno::Reference
<text::XTextTablesSupplier
> xTextTablesSupplier(mxComponent
, uno::UNO_QUERY
);
737 uno::Reference
<container::XIndexAccess
> xTables(xTextTablesSupplier
->getTextTables(),
739 uno::Reference
<text::XTextTable
> xTable(xTables
->getByIndex(0), uno::UNO_QUERY
);
740 uno::Reference
<text::XTextRange
> xCell(xTable
->getCellByName("A2"), uno::UNO_QUERY_THROW
);
741 // This was "** Expression is faulty **", because of the unnecessary DOCX number format string
742 CPPUNIT_ASSERT_EQUAL(OUString("2000"), xCell
->getString());
745 CPPUNIT_TEST_FIXTURE(Test
, testTdf121440
)
747 createSwDoc("tdf121440.docx");
748 // Insert some text in front of footnote
749 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
750 CPPUNIT_ASSERT(pTextDoc
);
751 SwWrtShell
* pWrtShell
= pTextDoc
->GetDocShell()->GetWrtShell();
752 SwRootFrame
* pLayout(pWrtShell
->GetLayout());
753 CPPUNIT_ASSERT(!pLayout
->IsHideRedlines());
754 pWrtShell
->Insert("test");
756 // Ensure that inserted text is not superscripted
757 CPPUNIT_ASSERT_EQUAL_MESSAGE(
758 "Inserted text should be not a superscript!", static_cast<sal_Int32
>(0),
759 getProperty
<sal_Int32
>(getRun(getParagraph(1), 1), "CharEscapement"));
762 CPPUNIT_TEST_FIXTURE(Test
, testTdf124670
)
764 createSwDoc("tdf124670.docx");
765 CPPUNIT_ASSERT_EQUAL(1, getParagraphs());
766 // We need to take xml:space attribute into account, even in w:document element
767 uno::Reference
<text::XTextRange
> paragraph
= getParagraph(1);
768 CPPUNIT_ASSERT_EQUAL(
769 OUString("You won't believe, but that's how it was in markup of original bugdoc!"),
770 paragraph
->getString());
773 CPPUNIT_TEST_FIXTURE(Test
, testTdf126114
)
775 createSwDoc("tdf126114.docx");
776 // The problem was that after the drop-down form field, also the placeholder string
777 // was imported as text. Beside the duplication of the field, it also caused a crash.
778 // the word is from replacement of the drop-down field in ModelToViewHelper
779 CPPUNIT_ASSERT_EQUAL(OUString("gehuwd\n"), getBodyText());
782 CPPUNIT_TEST_FIXTURE(Test
, testTdf127825
)
784 createSwDoc("tdf127825.docx");
785 // The document has a shape with Japanese-style text in it. The shape has relative size and also
786 // has automatic height.
787 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
788 CPPUNIT_ASSERT(pTextDoc
);
789 SwWrtShell
* pWrtShell
= pTextDoc
->GetDocShell()->GetWrtShell();
790 CPPUNIT_ASSERT(pWrtShell
);
791 SwRootFrame
* pLayout
= pWrtShell
->GetLayout();
792 CPPUNIT_ASSERT(pLayout
);
793 SwFrame
* pPage
= pLayout
->GetLower();
794 CPPUNIT_ASSERT(pPage
);
795 SwFrame
* pBody
= pPage
->GetLower();
796 CPPUNIT_ASSERT(pBody
);
797 SwFrame
* pText
= pBody
->GetLower();
798 CPPUNIT_ASSERT(pText
);
799 CPPUNIT_ASSERT(pText
->GetDrawObjs());
800 const SwSortedObjs
& rDrawObjs
= *pText
->GetDrawObjs();
801 CPPUNIT_ASSERT(rDrawObjs
.size());
803 // Without the accompanying fix in place, this overlapped the footer area, not the body area.
804 CPPUNIT_ASSERT(rDrawObjs
[0]->GetObjRect().Overlaps(pBody
->getFrameArea()));
807 CPPUNIT_TEST_FIXTURE(Test
, testTdf103345
)
809 createSwDoc("numbering-circle.docx");
810 uno::Reference
<beans::XPropertySet
> xPropertySet(
811 getStyles("NumberingStyles")->getByName("WWNum1"), uno::UNO_QUERY
);
812 uno::Reference
<container::XIndexAccess
> xLevels(
813 xPropertySet
->getPropertyValue("NumberingRules"), uno::UNO_QUERY
);
814 uno::Sequence
<beans::PropertyValue
> aProps
;
815 xLevels
->getByIndex(0) >>= aProps
; // 1st level
817 for (beans::PropertyValue
const& prop
: std::as_const(aProps
))
819 if (prop
.Name
== "NumberingType")
821 CPPUNIT_ASSERT_EQUAL(style::NumberingType::CIRCLE_NUMBER
, prop
.Value
.get
<sal_Int16
>());
827 CPPUNIT_TEST_FIXTURE(Test
, testTdf125038
)
829 createSwDoc("tdf125038.docx");
830 OUString aActual
= getParagraph(1)->getString();
831 // Without the accompanying fix in place, this test would have failed with:
832 // - Expected: phone:...
833 // - Actual : result1result2phone:...
834 // i.e. the result if the inner MERGEFIELD fields ended up in the body text.
835 CPPUNIT_ASSERT_EQUAL(OUString("phone: \t1234567890"), aActual
);
838 CPPUNIT_TEST_FIXTURE(Test
, testTdf125038b
)
840 createSwDoc("tdf125038b.docx");
841 // Load a document with an IF field, where the IF field command contains a paragraph break.
842 uno::Reference
<text::XTextDocument
> xTextDocument(mxComponent
, uno::UNO_QUERY
);
843 uno::Reference
<container::XEnumerationAccess
> xParagraphAccess(xTextDocument
->getText(),
845 uno::Reference
<container::XEnumeration
> xParagraphs
= xParagraphAccess
->createEnumeration();
846 CPPUNIT_ASSERT(xParagraphs
->hasMoreElements());
847 uno::Reference
<text::XTextRange
> xParagraph(xParagraphs
->nextElement(), uno::UNO_QUERY
);
849 // Without the accompanying fix in place, this test would have failed with:
850 // - Expected: phone: 1234
852 // i.e. the first paragraph was empty and the second paragraph had the content.
853 CPPUNIT_ASSERT_EQUAL(OUString("phone: 1234"), xParagraph
->getString());
854 CPPUNIT_ASSERT(xParagraphs
->hasMoreElements());
855 xParagraphs
->nextElement();
857 // Without the accompanying fix in place, this test would have failed with:
858 // - Expression: !xParagraphs->hasMoreElements()
859 // i.e. the document had 3 paragraphs, while only 2 was expected.
860 CPPUNIT_ASSERT(!xParagraphs
->hasMoreElements());
863 CPPUNIT_TEST_FIXTURE(Test
, testTdf125038c
)
865 createSwDoc("tdf125038c.docx");
866 OUString aActual
= getParagraph(1)->getString();
867 // Without the accompanying fix in place, this test would have failed with:
868 // - Expected: email: test@test.test
870 // I.e. the result of the MERGEFIELD field inside an IF field was lost.
871 CPPUNIT_ASSERT_EQUAL(OUString("email: test@test.test"), aActual
);
874 CPPUNIT_TEST_FIXTURE(Test
, testTdf130214
)
876 createSwDoc("tdf130214.docx");
877 // Currently this file imports with errors because of tdf#126435; it must not segfault on load
880 CPPUNIT_TEST_FIXTURE(Test
, testTdf129659
)
882 createSwDoc("tdf129659.docx");
883 // don't crash on footnote with page break
886 CPPUNIT_TEST_FIXTURE(Test
, testTdf129912
)
888 createSwDoc("tdf129912.docx");
889 SwXTextDocument
* pTextDoc
= dynamic_cast<SwXTextDocument
*>(mxComponent
.get());
890 CPPUNIT_ASSERT(pTextDoc
);
891 SwWrtShell
* pWrtShell
= pTextDoc
->GetDocShell()->GetWrtShell();
892 CPPUNIT_ASSERT(pWrtShell
);
894 // Goto*FootnoteAnchor iterates the footnotes in a ring, so we need the amount of footnotes to stop the loop
895 sal_Int32 nCount
= pWrtShell
->GetDoc()->GetFootnoteIdxs().size();
896 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), nCount
);
898 // the expected footnote labels
899 // TODO: the 5th label is actually wrong (missing the "PR" after the symbol part), but the "b" is there?!
900 static constexpr OUStringLiteral pLabel5
= u
"\uF0D1\uF031\uF032b";
901 const OUString sFootnoteLabels
[]
902 = { OUString(u
'\xF0A7'), "1", "2", OUString(u
'\xF020'), pLabel5
};
903 CPPUNIT_ASSERT_EQUAL(sal_Int32(SAL_N_ELEMENTS(sFootnoteLabels
)), nCount
);
905 pWrtShell
->GotoPrevFootnoteAnchor();
909 SwFormatFootnote aFootnoteNote
;
910 CPPUNIT_ASSERT(pWrtShell
->GetCurFootnote(&aFootnoteNote
));
911 OUString sNumStr
= aFootnoteNote
.GetNumStr();
912 if (sNumStr
.isEmpty())
913 sNumStr
= OUString::number(aFootnoteNote
.GetNumber());
914 CPPUNIT_ASSERT_EQUAL(sFootnoteLabels
[nCount
], sNumStr
);
915 pWrtShell
->GotoPrevFootnoteAnchor();
920 CPPUNIT_TEST_FIXTURE(Test
, testTdf126426
)
922 createSwDoc("tdf126426.docx");
924 uno::Reference
<container::XIndexAccess
> xGroup(getShape(1), uno::UNO_QUERY_THROW
);
925 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xGroup
->getCount());
927 // get second shape in group
928 uno::Reference
<text::XTextRange
> xRange(xGroup
->getByIndex(1), uno::UNO_QUERY_THROW
);
929 uno::Reference
<container::XEnumerationAccess
> xParaEnumAccess(xRange
, uno::UNO_QUERY_THROW
);
930 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
932 uno::Reference
<text::XTextRange
> xPara(xParaEnum
->nextElement(), uno::UNO_QUERY_THROW
);
933 uno::Reference
<container::XEnumerationAccess
> xRunEnumAccess(xPara
, uno::UNO_QUERY_THROW
);
935 uno::Reference
<container::XEnumeration
> xRunEnum
= xRunEnumAccess
->createEnumeration();
937 // Text before: was before this bugfix
938 uno::Reference
<text::XTextRange
> xRun(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
939 CPPUNIT_ASSERT_EQUAL(OUString("Some text "), xRun
->getString());
942 // Link and this content was completely missing before
943 uno::Reference
<text::XTextRange
> xRun(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
944 CPPUNIT_ASSERT_EQUAL(OUString("Link"), xRun
->getString());
945 auto aURL
= getProperty
<OUString
>(xRun
, "HyperLinkURL");
946 CPPUNIT_ASSERT_EQUAL(OUString("http://libreoffice.org/"), aURL
);
949 // Need to ensure that text following hyperlink is still default color (-1)
950 uno::Reference
<text::XTextRange
> xRun(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
951 CPPUNIT_ASSERT_EQUAL(OUString(" and something more."), xRun
->getString());
952 CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), getProperty
<sal_Int32
>(xRun
, "CharColor"));
956 CPPUNIT_TEST_FIXTURE(Test
, testTdf119039
)
958 createSwDoc("tdf119039_bad_embedded_compound.docx");
959 // Should not crash/hang because of problematic embedded compound
962 CPPUNIT_TEST_FIXTURE(Test
, testTdf152200
)
964 createSwDoc("tdf152200-bad_fldChar_end.docx");
965 // Should not crash/hang because of wrong placement of ending fldChar
968 CPPUNIT_TEST_FIXTURE(Test
, testTdf153791
)
970 createSwDoc("tdf153791-shd_overrides_fontRef.docx");
972 // the first shape (a paragraph with no background)
973 auto xTextBox(getShape(1));
974 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, getProperty
<Color
>(xTextBox
, "CharColor"));
975 uno::Reference
<text::XTextRange
> xRange(xTextBox
, uno::UNO_QUERY_THROW
);
976 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xRange
->getString());
978 uno::Reference
<container::XEnumerationAccess
> xParaEnumAccess(xRange
, uno::UNO_QUERY_THROW
);
979 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
981 uno::Reference
<text::XTextRange
> xPara(xParaEnum
->nextElement(), uno::UNO_QUERY_THROW
);
982 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xPara
, "ParaBackColor"));
984 uno::Reference
<container::XEnumerationAccess
> xRunEnumAccess(xPara
, uno::UNO_QUERY_THROW
);
985 uno::Reference
<container::XEnumeration
> xRunEnum
= xRunEnumAccess
->createEnumeration();
987 uno::Reference
<text::XTextRange
> xRun(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
988 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xRun
->getString());
989 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xRun
, "CharBackColor"));
990 // In the absence of paragraph/character background, the whole paragraph is red.
991 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, getProperty
<Color
>(xRun
, "CharColor"));
993 // the second shape: two paragraphs
994 xTextBox
.set(getShape(2));
995 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, getProperty
<Color
>(xTextBox
, "CharColor"));
996 xRange
.set(xTextBox
, uno::UNO_QUERY_THROW
);
997 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum" SAL_NEWLINE_STRING
"Lorem ipsum"),
998 xRange
->getString());
1000 xParaEnumAccess
.set(xRange
, uno::UNO_QUERY_THROW
);
1001 xParaEnum
= xParaEnumAccess
->createEnumeration();
1003 // the first one has paragraph background
1004 xPara
.set(xParaEnum
->nextElement(), uno::UNO_QUERY_THROW
);
1005 CPPUNIT_ASSERT_EQUAL(Color(0xF0F0F0), getProperty
<Color
>(xPara
, "ParaBackColor"));
1007 xRunEnumAccess
.set(xPara
, uno::UNO_QUERY_THROW
);
1008 xRunEnum
= xRunEnumAccess
->createEnumeration();
1010 xRun
.set(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
1011 CPPUNIT_ASSERT_EQUAL(OUString("Lorem ipsum"), xRun
->getString());
1012 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xRun
, "CharBackColor"));
1013 // With paragraph background, the whole paragraph is auto.
1014 // Without the fix, this would fail with:
1015 // - Expected: rgba[ffffff00]
1016 // - Actual : rgba[ff0000ff]
1017 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xRun
, "CharColor"));
1019 // the second paragraph has two runs, the last one with character background
1020 xPara
.set(xParaEnum
->nextElement(), uno::UNO_QUERY_THROW
);
1021 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xPara
, "ParaBackColor"));
1023 xRunEnumAccess
.set(xPara
, uno::UNO_QUERY_THROW
);
1024 xRunEnum
= xRunEnumAccess
->createEnumeration();
1026 xRun
.set(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
1027 CPPUNIT_ASSERT_EQUAL(OUString("Lorem "), xRun
->getString());
1028 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xRun
, "CharBackColor"));
1029 // In the absence of paragraph/character background, the run is red
1030 CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED
, getProperty
<Color
>(xRun
, "CharColor"));
1032 xRun
.set(xRunEnum
->nextElement(), uno::UNO_QUERY_THROW
);
1033 CPPUNIT_ASSERT_EQUAL(OUString("ipsum"), xRun
->getString());
1034 CPPUNIT_ASSERT_EQUAL(Color(0xF0F0F0), getProperty
<Color
>(xRun
, "CharBackColor"));
1035 // With character background, the run is auto.
1036 // Without the fix, this would fail with:
1037 // - Expected: rgba[ffffff00]
1038 // - Actual : rgba[ff0000ff]
1039 CPPUNIT_ASSERT_EQUAL(COL_AUTO
, getProperty
<Color
>(xRun
, "CharColor"));
1042 CPPUNIT_TEST_FIXTURE(Test
, testTdf154319
)
1044 createSwDoc("tdf154319-ToC_with_s_and_d.docx");
1046 auto xSupplier(mxComponent
.queryThrow
<css::text::XDocumentIndexesSupplier
>());
1047 auto xIndexes
= xSupplier
->getDocumentIndexes();
1048 auto xTOCIndex(xIndexes
->getByIndex(0).queryThrow
<css::beans::XPropertySet
>());
1049 css::uno::Reference
<css::container::XIndexReplace
> xLevelFormats
;
1050 CPPUNIT_ASSERT(xTOCIndex
->getPropertyValue("LevelFormat") >>= xLevelFormats
);
1051 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), xLevelFormats
->getCount());
1053 const auto checkPropVal
= [](const auto& expected
, const css::beans::PropertyValues
& entry
,
1054 const OUString
& name
, sal_Int32 level
) {
1056 = std::find_if(entry
.begin(), entry
.end(),
1057 [&name
](const css::beans::PropertyValue
& p
) { return p
.Name
== name
; });
1058 OString msg
= "Property: " + name
.toUtf8() + ", level: " + OString::number(level
);
1059 CPPUNIT_ASSERT_MESSAGE(msg
.getStr(), it
!= entry
.end());
1060 CPPUNIT_ASSERT_EQUAL_MESSAGE(msg
.getStr(), css::uno::Any(expected
), it
->Value
);
1063 // tdf#154360: check tab stops between the number and the entry text
1064 // The last (10th) level does not correspond to any MS level (only 9 levels there)
1065 constexpr sal_Int32 levelTabStops
[]
1066 = { 776, 1552, 2328, 3104, 3881, 4657, 5433, 6209, 6985, -1 };
1068 //start with level 1, 0 is the header level
1069 for (sal_Int32 nLevel
= 1; nLevel
< xLevelFormats
->getCount(); ++nLevel
)
1071 css::uno::Sequence
<css::beans::PropertyValues
> aLevel
;
1072 xLevelFormats
->getByIndex(nLevel
) >>= aLevel
;
1074 sal_Int32 nTabStop
= levelTabStops
[nLevel
- 1];
1075 sal_Int32 nExpectedTokens
= nTabStop
< 0 ? 8 : 9;
1076 CPPUNIT_ASSERT_EQUAL(nExpectedTokens
, aLevel
.getLength());
1077 sal_Int32 nIndex
= 0;
1079 checkPropVal(OUString("TokenHyperlinkStart"), aLevel
[nIndex
++], "TokenType", nLevel
);
1081 checkPropVal(OUString("TokenEntryNumber"), aLevel
[nIndex
++], "TokenType", nLevel
);
1085 checkPropVal(OUString("TokenTabStop"), aLevel
[nIndex
], "TokenType", nLevel
);
1086 checkPropVal(levelTabStops
[nLevel
- 1], aLevel
[nIndex
++], "TabStopPosition", nLevel
);
1089 checkPropVal(OUString("TokenEntryText"), aLevel
[nIndex
++], "TokenType", nLevel
);
1091 checkPropVal(OUString("TokenTabStop"), aLevel
[nIndex
++], "TokenType", nLevel
);
1093 checkPropVal(OUString("TokenChapterInfo"), aLevel
[nIndex
++], "TokenType", nLevel
);
1095 checkPropVal(OUString("TokenText"), aLevel
[nIndex
], "TokenType", nLevel
);
1096 checkPropVal(OUString("\""), aLevel
[nIndex
++], "Text", nLevel
);
1098 checkPropVal(OUString("TokenPageNumber"), aLevel
[nIndex
++], "TokenType", nLevel
);
1100 checkPropVal(OUString("TokenHyperlinkEnd"), aLevel
[nIndex
++], "TokenType", nLevel
);
1104 CPPUNIT_TEST_FIXTURE(Test
, testTdf154695
)
1106 createSwDoc("tdf154695-ToC_no_numbers.docx");
1108 auto xSupplier(mxComponent
.queryThrow
<css::text::XDocumentIndexesSupplier
>());
1109 auto xIndexes
= xSupplier
->getDocumentIndexes();
1110 auto xTOCIndex(xIndexes
->getByIndex(0).queryThrow
<css::beans::XPropertySet
>());
1111 css::uno::Reference
<css::container::XIndexReplace
> xLevelFormats
;
1112 CPPUNIT_ASSERT(xTOCIndex
->getPropertyValue("LevelFormat") >>= xLevelFormats
);
1113 CPPUNIT_ASSERT_EQUAL(sal_Int32(11), xLevelFormats
->getCount());
1115 const auto checkPropVal
= [](const auto& expected
, const css::beans::PropertyValues
& entry
,
1116 const OUString
& name
, sal_Int32 level
) {
1118 = std::find_if(entry
.begin(), entry
.end(),
1119 [&name
](const css::beans::PropertyValue
& p
) { return p
.Name
== name
; });
1120 OString msg
= "Property: " + name
.toUtf8() + ", level: " + OString::number(level
);
1121 CPPUNIT_ASSERT_MESSAGE(msg
.getStr(), it
!= entry
.end());
1122 CPPUNIT_ASSERT_EQUAL_MESSAGE(msg
.getStr(), css::uno::Any(expected
), it
->Value
);
1125 //start with level 1, 0 is the header level
1126 for (sal_Int32 nLevel
= 1; nLevel
< xLevelFormats
->getCount(); ++nLevel
)
1128 css::uno::Sequence
<css::beans::PropertyValues
> aLevel
;
1129 xLevelFormats
->getByIndex(nLevel
) >>= aLevel
;
1131 CPPUNIT_ASSERT_EQUAL(sal_Int32(6), aLevel
.getLength());
1133 checkPropVal(OUString("TokenHyperlinkStart"), aLevel
[0], "TokenType", nLevel
);
1135 checkPropVal(OUString("TokenEntryNumber"), aLevel
[1], "TokenType", nLevel
);
1137 // There's no tab stop between [#E] and [E]!
1139 checkPropVal(OUString("TokenEntryText"), aLevel
[2], "TokenType", nLevel
);
1141 checkPropVal(OUString("TokenTabStop"), aLevel
[3], "TokenType", nLevel
);
1143 checkPropVal(OUString("TokenPageNumber"), aLevel
[4], "TokenType", nLevel
);
1145 checkPropVal(OUString("TokenHyperlinkEnd"), aLevel
[5], "TokenType", nLevel
);
1149 CPPUNIT_TEST_FIXTURE(Test
, testTdf156078
)
1151 // Given a DOCX with compat level 15, and a tab stop outside of paragraph right indent
1152 createSwDoc("tdf156078_rightTabOutsideParaRightIndent.docx");
1154 // Export it to a PNG (96 ppi)
1155 uno::Sequence
<beans::PropertyValue
> aFilterData(
1156 comphelper::InitPropertySequence({ { "PixelWidth", uno::Any(sal_Int32(816)) },
1157 { "PixelHeight", uno::Any(sal_Int32(1056)) } }));
1158 uno::Sequence
<beans::PropertyValue
> aDescriptor(comphelper::InitPropertySequence(
1159 { { "FilterName", uno::Any(OUString("writer_png_Export")) },
1160 { "FilterData", uno::Any(aFilterData
) } }));
1161 uno::Reference
<frame::XStorable
> xStorable(mxComponent
, uno::UNO_QUERY
);
1162 xStorable
->storeToURL(maTempFile
.GetURL(), aDescriptor
);
1163 CPPUNIT_ASSERT(maTempFile
.IsValid());
1166 GraphicFilter::LoadGraphic(maTempFile
.GetURL(), {}, exported
);
1167 Bitmap bmp
= exported
.GetBitmapEx().GetBitmap();
1168 Bitmap::ScopedReadAccess
pAccess(bmp
);
1170 // "1" must export to the top right corner; check its pixels
1171 bool numberPixelsFound
= false;
1172 for (tools::Long y
= 90; y
< 130; ++y
)
1173 for (tools::Long x
= 680; x
< 720; ++x
)
1174 if (Color(pAccess
->GetPixel(y
, x
)).IsDark())
1175 numberPixelsFound
= true;
1177 CPPUNIT_ASSERT(numberPixelsFound
);
1180 CPPUNIT_TEST_FIXTURE(Test
, testTdf141969
)
1182 // Given a file with a table with a style setting font height, and a text re-defining the height
1183 createSwDoc("tdf141969-font_in_table_with_style.docx");
1185 auto xTable
= getParagraphOrTable(2);
1186 uno::Reference
<text::XText
> xCell(getCell(xTable
, "A1"), uno::UNO_QUERY_THROW
);
1187 auto xParaOfCell
= getParagraphOfText(1, xCell
);
1188 auto xRun
= getRun(xParaOfCell
, 1);
1190 CPPUNIT_ASSERT_EQUAL(OUString("<<link:website>>"), xRun
->getString());
1191 // Without a fix, this would fail with
1194 CPPUNIT_ASSERT_EQUAL(8.0f
, getProperty
<float>(xRun
, "CharHeight"));
1197 // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in ooxmlEXPORT
1199 CPPUNIT_PLUGIN_IMPLEMENT();
1201 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */