Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / qa / extras / rtfexport / rtfexport.cxx
blob0f1ea5e695ea7b3cb50445a7b0ca3a2f9451f286
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/Gradient2.hpp>
13 #include <com/sun/star/awt/XBitmap.hpp>
14 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
15 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
16 #include <com/sun/star/drawing/FillStyle.hpp>
17 #include <com/sun/star/table/ShadowFormat.hpp>
18 #include <com/sun/star/text/RelOrientation.hpp>
19 #include <com/sun/star/text/XFootnotesSupplier.hpp>
20 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
21 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
22 #include <com/sun/star/text/RubyAdjust.hpp>
23 #include <com/sun/star/text/RubyPosition.hpp>
24 #include <com/sun/star/text/XTextColumns.hpp>
25 #include <com/sun/star/text/XTextDocument.hpp>
26 #include <com/sun/star/text/XTextFramesSupplier.hpp>
27 #include <com/sun/star/text/XTextTable.hpp>
28 #include <com/sun/star/text/XLineNumberingProperties.hpp>
29 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
30 #include <com/sun/star/text/XBookmarksSupplier.hpp>
32 #include <tools/UnitConversion.hxx>
33 #include <basegfx/utils/gradienttools.hxx>
34 #include <docmodel/uno/UnoGradientTools.hxx>
36 using namespace css;
38 class Test : public SwModelTestBase
40 public:
41 Test()
42 : SwModelTestBase("/sw/qa/extras/rtfexport/data/", "Rich Text Format")
47 DECLARE_RTFEXPORT_TEST(testZoom, "zoom.rtf")
49 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
50 uno::Reference<view::XViewSettingsSupplier> xViewSettingsSupplier(
51 xModel->getCurrentController(), uno::UNO_QUERY);
52 uno::Reference<beans::XPropertySet> xPropertySet(xViewSettingsSupplier->getViewSettings());
53 sal_Int16 nValue = 0;
54 xPropertySet->getPropertyValue("ZoomValue") >>= nValue;
55 CPPUNIT_ASSERT_EQUAL(sal_Int16(42), nValue);
58 DECLARE_RTFEXPORT_TEST(testFdo38176, "fdo38176.rtf") { CPPUNIT_ASSERT_EQUAL(9, getLength()); }
60 DECLARE_RTFEXPORT_TEST(testFdo49683, "fdo49683.rtf")
62 uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(
63 mxComponent, uno::UNO_QUERY);
64 uno::Reference<document::XDocumentProperties> xDocumentProperties(
65 xDocumentPropertiesSupplier->getDocumentProperties());
66 uno::Sequence<OUString> aKeywords(xDocumentProperties->getKeywords());
67 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), aKeywords.getLength());
68 CPPUNIT_ASSERT_EQUAL(OUString("one"), aKeywords[0]);
69 CPPUNIT_ASSERT_EQUAL(OUString("two"), aKeywords[1]);
72 DECLARE_RTFEXPORT_TEST(testFdo44174, "fdo44174.rtf")
74 uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
75 uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(
76 xModel->getCurrentController(), uno::UNO_QUERY);
77 uno::Reference<beans::XPropertySet> xPropertySet(xTextViewCursorSupplier->getViewCursor(),
78 uno::UNO_QUERY);
79 OUString aValue;
80 xPropertySet->getPropertyValue("PageStyleName") >>= aValue;
81 CPPUNIT_ASSERT_EQUAL(OUString("First Page"), aValue);
84 DECLARE_RTFEXPORT_TEST(testFdo50087, "fdo50087.rtf")
86 uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(
87 mxComponent, uno::UNO_QUERY);
88 uno::Reference<document::XDocumentProperties> xDocumentProperties(
89 xDocumentPropertiesSupplier->getDocumentProperties());
90 CPPUNIT_ASSERT_EQUAL(OUString("Title"), xDocumentProperties->getTitle());
91 CPPUNIT_ASSERT_EQUAL(OUString("Subject"), xDocumentProperties->getSubject());
92 CPPUNIT_ASSERT_EQUAL(OUString("First line.\nSecond line."),
93 xDocumentProperties->getDescription());
96 DECLARE_RTFEXPORT_TEST(testFdo50831, "fdo50831.rtf")
98 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
99 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
100 uno::UNO_QUERY);
101 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
102 uno::Reference<beans::XPropertySet> xPropertySet(xParaEnum->nextElement(), uno::UNO_QUERY);
103 float fValue = 0;
104 xPropertySet->getPropertyValue("CharHeight") >>= fValue;
105 CPPUNIT_ASSERT_EQUAL(10.f, fValue);
108 CPPUNIT_TEST_FIXTURE(Test, testFdo48335)
110 loadAndReload("fdo48335.odt");
111 CPPUNIT_ASSERT_EQUAL(3, getPages());
113 * The problem was that we exported a fake pagebreak, make sure it's just a soft one now.
115 * oParas = ThisComponent.Text.createEnumeration
116 * oPara = oParas.nextElement
117 * oPara = oParas.nextElement
118 * oPara = oParas.nextElement
119 * oRuns = oPara.createEnumeration
120 * oRun = oRuns.nextElement
121 * xray oRun.TextPortionType 'was Text, should be SoftPageBreak
123 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
124 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
125 uno::UNO_QUERY);
126 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
127 for (int i = 0; i < 2; i++)
128 xParaEnum->nextElement();
129 uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(),
130 uno::UNO_QUERY);
131 uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
132 uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
133 OUString aValue;
134 xPropertySet->getPropertyValue("TextPortionType") >>= aValue;
135 CPPUNIT_ASSERT_EQUAL(OUString("SoftPageBreak"), aValue);
138 DECLARE_RTFEXPORT_TEST(testFdo38244, "fdo38244.rtf")
140 // See ooxmlexport's testFdo38244().
141 // Test comment range feature.
142 uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
143 uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
144 uno::UNO_QUERY);
145 uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
146 uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(),
147 uno::UNO_QUERY);
148 uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
149 xRunEnum->nextElement();
150 uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
151 CPPUNIT_ASSERT_EQUAL(OUString("Annotation"),
152 getProperty<OUString>(xPropertySet, "TextPortionType"));
153 xRunEnum->nextElement();
154 xPropertySet.set(xRunEnum->nextElement(), uno::UNO_QUERY);
155 CPPUNIT_ASSERT_EQUAL(OUString("AnnotationEnd"),
156 getProperty<OUString>(xPropertySet, "TextPortionType"));
158 // Test initials.
159 uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
160 uno::Reference<container::XEnumerationAccess> xFieldsAccess(
161 xTextFieldsSupplier->getTextFields());
162 uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
163 xPropertySet.set(xFields->nextElement(), uno::UNO_QUERY);
164 CPPUNIT_ASSERT_EQUAL(OUString("M"), getProperty<OUString>(xPropertySet, "Initials"));
167 CPPUNIT_TEST_FIXTURE(Test, testCommentsNested)
169 loadAndReload("comments-nested.odt");
170 CPPUNIT_ASSERT_EQUAL(1, getPages());
171 uno::Reference<beans::XPropertySet> xOuter
172 = getProperty<uno::Reference<beans::XPropertySet>>(getRun(getParagraph(1), 2), "TextField");
173 CPPUNIT_ASSERT_EQUAL(OUString("Outer"), getProperty<OUString>(xOuter, "Content").trim());
175 uno::Reference<beans::XPropertySet> xInner
176 = getProperty<uno::Reference<beans::XPropertySet>>(getRun(getParagraph(1), 4), "TextField");
177 CPPUNIT_ASSERT_EQUAL(OUString("Inner"), getProperty<OUString>(xInner, "Content").trim());
180 DECLARE_RTFEXPORT_TEST(testMathAccents, "math-accents.rtf")
182 OUString aActual = getFormula(getRun(getParagraph(1), 1));
183 CPPUNIT_ASSERT_EQUAL(
184 OUString("acute {a} grave {a} check {a} breve {a} circle {a} widevec {a} "
185 "widetilde {a} widehat {a} dot {a} widevec {a} widevec {a} widetilde "
186 "{a} underline {a}"),
187 aActual);
190 CPPUNIT_TEST_FIXTURE(Test, testMathEqarray)
192 loadAndReload("math-eqarray.rtf");
193 OUString aActual = getFormula(getRun(getParagraph(1), 1));
194 CPPUNIT_ASSERT_EQUAL(
195 OUString("y = left lbrace stack { 0 , x < 0 # 1 , x = 0 # {x} ^ {2} , x > 0 } right none"),
196 aActual);
199 DECLARE_RTFEXPORT_TEST(testMathD, "math-d.rtf")
201 OUString aActual = getFormula(getRun(getParagraph(1), 1));
202 CPPUNIT_ASSERT_EQUAL(
203 OUString("left (x mline y mline z right ) left (1 right ) left [2 right ] left "
204 "ldbracket 3 right rdbracket left lline 4 right rline left ldline 5 "
205 "right rdline left langle 6 right rangle left langle a mline b right "
206 "rangle left ({x} over {y} right )"),
207 aActual);
210 CPPUNIT_TEST_FIXTURE(Test, testMathEscaping)
212 loadAndReload("math-escaping.rtf");
213 OUString aActual = getFormula(getRun(getParagraph(1), 1));
214 CPPUNIT_ASSERT_EQUAL(OUString(u"\u00E1 \\{"), aActual);
217 CPPUNIT_TEST_FIXTURE(Test, testMathLim)
219 loadAndReload("math-lim.rtf");
220 OUString aActual = getFormula(getRun(getParagraph(1), 1));
221 CPPUNIT_ASSERT_EQUAL(OUString(u"lim from {x \u2192 1} {x}"), aActual);
224 DECLARE_RTFEXPORT_TEST(testMathMatrix, "math-matrix.rtf")
226 OUString aActual = getFormula(getRun(getParagraph(1), 1));
227 CPPUNIT_ASSERT_EQUAL(OUString("left [matrix {1 # 2 ## 3 # 4} right ]"), aActual);
230 DECLARE_RTFEXPORT_TEST(testMathBox, "math-mbox.rtf")
232 OUString aActual = getFormula(getRun(getParagraph(1), 1));
233 CPPUNIT_ASSERT_EQUAL(OUString("a"), aActual);
236 CPPUNIT_TEST_FIXTURE(Test, testMathMso2007)
238 loadAndReload("math-mso2007.rtf");
239 OUString aActual = getFormula(getRun(getParagraph(1), 1));
240 OUString aExpected(u"A = \u03C0 {r} ^ {2}");
241 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
243 aActual = getFormula(getRun(getParagraph(2), 1));
244 aExpected = OUString(u"{left (x + a right )} ^ {n} = sum from {k = 0} to {n} {left (stack { n "
245 u"# k } right ) {x} ^ {k} {a} ^ {n \u2212 k}}");
246 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
248 aActual = getFormula(getRun(getParagraph(3), 1));
249 aExpected = OUString(u"{left (1 + x right )} ^ {n} = 1 + {nx} over {1 !} + {n left (n \u2212 1 "
250 u"right ) {x} ^ {2}} over {2 !} + \u2026");
251 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
253 aActual = getFormula(getRun(getParagraph(4), 1));
254 aExpected = OUString(u"f left (x right ) = {a} rsub {0} + sum from {n = 1} to {\u221E} {left "
255 u"({a} rsub {n} cos {n\u03C0x} over {L} + {b} rsub {n} sin {n\u03C0x} "
256 u"over {L} right )}");
257 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
259 aActual = getFormula(getRun(getParagraph(5), 1));
260 aExpected = "{a} ^ {2} + {b} ^ {2} = {c} ^ {2}";
261 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
263 aActual = getFormula(getRun(getParagraph(6), 1));
264 aExpected = OUString(u"x = {\u2212 b \u00B1 sqrt {{b} ^ {2} \u2212 4 ac}} over {2 a}");
265 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
267 aActual = getFormula(getRun(getParagraph(7), 1));
268 aExpected = OUString(u"{e} ^ {x} = 1 + {x} over {1 !} + {{x} ^ {2}} over {2 !} + {{x} ^ {3}} "
269 u"over {3 !} + \u2026 , \u2212 \u221E < x < \u221E");
270 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
272 aActual = getFormula(getRun(getParagraph(8), 1));
273 aExpected = OUString(u"sin \u03B1 \u00B1 sin \u03B2 = 2 sin {1} over {2} left (\u03B1 \u00B1 "
274 u"\u03B2 right ) cos {1} over {2} left (\u03B1 \u2213 \u03B2 right )");
275 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
277 aActual = getFormula(getRun(getParagraph(9), 1));
278 aExpected = OUString(u"cos \u03B1 + cos \u03B2 = 2 cos {1} over {2} left (\u03B1 + \u03B2 "
279 u"right ) cos {1} over {2} left (\u03B1 \u2212 \u03B2 right )");
280 CPPUNIT_ASSERT_EQUAL(aExpected, aActual);
283 CPPUNIT_TEST_FIXTURE(Test, testMathNary)
285 loadAndReload("math-nary.rtf");
286 OUString aActual = getFormula(getRun(getParagraph(1), 1));
287 CPPUNIT_ASSERT_EQUAL(
288 OUString("lllint from {1} to {2} {x + 1} prod from {a} {b} sum to {2} {x}"), aActual);
291 DECLARE_RTFEXPORT_TEST(testMathLimupp, "math-limupp.rtf")
293 OUString aActual = getFormula(getRun(getParagraph(1), 1));
294 CPPUNIT_ASSERT_EQUAL(OUString("{abcd} overbrace {4}"), aActual);
296 aActual = getFormula(getRun(getParagraph(2), 1));
297 CPPUNIT_ASSERT_EQUAL(OUString("{xyz} underbrace {3}"), aActual);
300 DECLARE_RTFEXPORT_TEST(testMathStrikeh, "math-strikeh.rtf")
302 OUString aActual = getFormula(getRun(getParagraph(1), 1));
303 CPPUNIT_ASSERT_EQUAL(OUString("overstrike {abc}"), aActual);
306 DECLARE_RTFEXPORT_TEST(testMathPlaceholders, "math-placeholders.rtf")
308 OUString aActual = getFormula(getRun(getParagraph(1), 1));
309 CPPUNIT_ASSERT_EQUAL(OUString("sum from <?> to <?> <?>"), aActual);
312 CPPUNIT_TEST_FIXTURE(Test, testMathRad)
314 loadAndReload("math-rad.rtf");
315 OUString aActual = getFormula(getRun(getParagraph(1), 1));
316 CPPUNIT_ASSERT_EQUAL(OUString("sqrt {4} nroot {3} {x + 1}"), aActual);
319 DECLARE_RTFEXPORT_TEST(testMathSepchr, "math-sepchr.rtf")
321 OUString aActual = getFormula(getRun(getParagraph(1), 1));
322 CPPUNIT_ASSERT_EQUAL(OUString("AxByBzC"), aActual);
325 DECLARE_RTFEXPORT_TEST(testMathSubscripts, "math-subscripts.rtf")
327 OUString aActual = getFormula(getRun(getParagraph(1), 1));
328 CPPUNIT_ASSERT_EQUAL(
329 OUString("{x} ^ {y} + {e} ^ {x} {x} ^ {b} {x} rsub {b} {a} rsub {c} rsup {b} "
330 "{x} lsub {2} lsup {1} {{x csup {6} csub {3}} lsub {4} lsup {5}} rsub "
331 "{2} rsup {1}"),
332 aActual);
335 CPPUNIT_TEST_FIXTURE(Test, testMathVerticalstacks)
337 loadAndReload("math-vertical-stacks.rtf");
338 CPPUNIT_ASSERT_EQUAL(OUString("{a} over {b}"), getFormula(getRun(getParagraph(1), 1)));
339 CPPUNIT_ASSERT_EQUAL(OUString("{a} / {b}"), getFormula(getRun(getParagraph(2), 1)));
340 CPPUNIT_ASSERT_EQUAL(OUString("stack { a # b }"), getFormula(getRun(getParagraph(3), 1)));
341 CPPUNIT_ASSERT_EQUAL(OUString("stack { a # stack { b # c } }"),
342 getFormula(getRun(getParagraph(4), 1)));
345 DECLARE_RTFEXPORT_TEST(testTdf49073, "tdf49073.rtf")
347 // test case for Asian phontic guide (ruby text.)
348 sal_Unicode aRuby[3] = { 0x304D, 0x3082, 0x3093 };
349 OUString sRuby(aRuby, SAL_N_ELEMENTS(aRuby));
350 CPPUNIT_ASSERT_EQUAL(sRuby, getProperty<OUString>(getParagraph(1)->getStart(), "RubyText"));
351 OUString sStyle = getProperty<OUString>(getParagraph(1)->getStart(), "RubyCharStyleName");
352 uno::Reference<beans::XPropertySet> xPropertySet(
353 getStyles("CharacterStyles")->getByName(sStyle), uno::UNO_QUERY);
354 CPPUNIT_ASSERT_EQUAL(5.f, getProperty<float>(xPropertySet, "CharHeight"));
355 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::RubyAdjust_CENTER),
356 getProperty<sal_Int16>(getParagraph(2)->getStart(), "RubyAdjust"));
357 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::RubyAdjust_BLOCK),
358 getProperty<sal_Int16>(getParagraph(3)->getStart(), "RubyAdjust"));
359 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::RubyAdjust_INDENT_BLOCK),
360 getProperty<sal_Int16>(getParagraph(4)->getStart(), "RubyAdjust"));
361 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::RubyAdjust_LEFT),
362 getProperty<sal_Int16>(getParagraph(5)->getStart(), "RubyAdjust"));
363 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::RubyAdjust_RIGHT),
364 getProperty<sal_Int16>(getParagraph(6)->getStart(), "RubyAdjust"));
365 CPPUNIT_ASSERT_EQUAL(sal_Int16(text::RubyPosition::INTER_CHARACTER),
366 getProperty<sal_Int16>(getParagraph(7)->getStart(), "RubyPosition"));
369 CPPUNIT_TEST_FIXTURE(Test, testMathRuns)
371 loadAndReload("math-runs.rtf");
372 // was [](){}, i.e. first curly bracket had an incorrect position
373 CPPUNIT_ASSERT_EQUAL(OUString("\\{ left [ right ] left ( right ) \\}"),
374 getFormula(getRun(getParagraph(1), 1)));
377 CPPUNIT_TEST_FIXTURE(Test, testFdo77979)
379 loadAndReload("fdo77979.odt");
380 CPPUNIT_ASSERT_EQUAL(1, getPages());
381 // font name is encoded with \fcharset of font
382 CPPUNIT_ASSERT_EQUAL(OUString(u"\u5FAE\u8F6F\u96C5\u9ED1"),
383 getProperty<OUString>(getRun(getParagraph(1), 1), "CharFontName"));
386 CPPUNIT_TEST_FIXTURE(Test, testFdo53113)
388 loadAndReload("fdo53113.odt");
389 CPPUNIT_ASSERT_EQUAL(1, getShapes());
390 CPPUNIT_ASSERT_EQUAL(1, getPages());
392 * The problem was that a custom shape was missing its second (and all the other remaining) coordinates.
394 * oShape = ThisComponent.DrawPage(0)
395 * oPathPropVec = oShape.CustomShapeGeometry(1).Value
396 * oCoordinates = oPathPropVec(0).Value
397 * xray oCoordinates(1).First.Value ' 535
398 * xray oCoordinates(1).Second.Value ' 102
401 const uno::Sequence<beans::PropertyValue> aProps
402 = getProperty<uno::Sequence<beans::PropertyValue>>(getShape(1), "CustomShapeGeometry");
403 uno::Sequence<beans::PropertyValue> aPathProps;
404 for (beans::PropertyValue const& rProp : aProps)
406 if (rProp.Name == "Path")
407 rProp.Value >>= aPathProps;
409 uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aPairs;
410 for (beans::PropertyValue const& rProp : std::as_const(aPathProps))
412 if (rProp.Name == "Coordinates")
413 rProp.Value >>= aPairs;
415 CPPUNIT_ASSERT_EQUAL(sal_Int32(16), aPairs.getLength());
416 CPPUNIT_ASSERT_EQUAL(sal_Int32(535), aPairs[1].First.Value.get<sal_Int32>());
417 CPPUNIT_ASSERT_EQUAL(sal_Int32(102), aPairs[1].Second.Value.get<sal_Int32>());
420 CPPUNIT_TEST_FIXTURE(Test, testFdo55939)
422 loadAndReload("fdo55939.odt");
423 CPPUNIT_ASSERT_EQUAL(1, getPages());
424 // The problem was that the exported RTF was invalid.
425 // Also, the 'Footnote text.' had an additional newline at its end.
426 uno::Reference<text::XTextRange> xParagraph(getParagraph(1));
427 getRun(xParagraph, 1, "Main text before footnote.");
428 // Why the tab has to be removed here?
429 CPPUNIT_ASSERT_EQUAL(OUString("Footnote text."), getProperty<uno::Reference<text::XTextRange>>(
430 getRun(xParagraph, 2), "Footnote")
431 ->getText()
432 ->getString()
433 .replaceAll("\t", ""));
434 getRun(xParagraph, 3,
435 " Text after the footnote."); // However, this leading space is intentional and OK.
438 CPPUNIT_TEST_FIXTURE(Test, testTextFrames)
440 loadAndReload("textframes.odt");
441 CPPUNIT_ASSERT_EQUAL(3, getShapes());
442 CPPUNIT_ASSERT_EQUAL(1, getPages());
443 // The output was simply invalid, so let's check if all 3 frames were imported back.
444 uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
445 uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(),
446 uno::UNO_QUERY);
447 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), xIndexAccess->getCount());
450 CPPUNIT_TEST_FIXTURE(Test, testFdo53604)
452 loadAndReload("fdo53604.odt");
453 CPPUNIT_ASSERT_EQUAL(1, getPages());
454 // Invalid output on empty footnote.
455 uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
456 uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
457 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xFootnotes->getCount());
460 CPPUNIT_TEST_FIXTURE(Test, testFdo52286)
462 loadAndReload("fdo52286.odt");
463 CPPUNIT_ASSERT_EQUAL(1, getPages());
464 // The problem was that font size wasn't reduced in sub/super script.
465 CPPUNIT_ASSERT_EQUAL(
466 sal_Int32(58), getProperty<sal_Int32>(getRun(getParagraph(1), 2), "CharEscapementHeight"));
467 CPPUNIT_ASSERT_EQUAL(
468 sal_Int32(58), getProperty<sal_Int32>(getRun(getParagraph(2), 2), "CharEscapementHeight"));
471 DECLARE_RTFEXPORT_TEST(testFdo61507, "fdo61507.rtf")
474 * Unicode-only characters in \title confused Wordpad. Once the exporter
475 * was fixed to guard the problematic characters with \upr and \ud, the
476 * importer didn't cope with these new keywords.
479 uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(
480 mxComponent, uno::UNO_QUERY);
481 uno::Reference<document::XDocumentProperties> xDocumentProperties(
482 xDocumentPropertiesSupplier->getDocumentProperties());
483 CPPUNIT_ASSERT_EQUAL(OUString(u"\u00C9\u00C1\u0150\u0170\u222D"),
484 xDocumentProperties->getTitle());
486 // Only "Hello.", no additional characters.
487 CPPUNIT_ASSERT_EQUAL(6, getLength());
490 DECLARE_RTFEXPORT_TEST(testFdo30983, "fdo30983.rtf")
492 // These were 'page text area', not 'entire page', i.e. both the horizontal
493 // and vertical positions were incorrect.
494 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME,
495 getProperty<sal_Int16>(getShape(1), "HoriOrientRelation"));
496 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME,
497 getProperty<sal_Int16>(getShape(1), "VertOrientRelation"));
500 CPPUNIT_TEST_FIXTURE(Test, testPlaceholder)
502 loadAndReload("placeholder.odt");
503 CPPUNIT_ASSERT_EQUAL(1, getPages());
504 // Only the field text was exported, make sure we still have a field with the correct Hint text.
505 uno::Reference<text::XTextRange> xRun(getRun(getParagraph(1), 2));
506 CPPUNIT_ASSERT_EQUAL(OUString("TextField"), getProperty<OUString>(xRun, "TextPortionType"));
507 uno::Reference<beans::XPropertySet> xField
508 = getProperty<uno::Reference<beans::XPropertySet>>(xRun, "TextField");
509 CPPUNIT_ASSERT_EQUAL(OUString("place holder"), getProperty<OUString>(xField, "Hint"));
512 DECLARE_RTFEXPORT_TEST(testMnor, "mnor.rtf")
514 // \mnor wasn't handled, leading to missing quotes around "divF" and so on.
515 OUString aActual = getFormula(getRun(getParagraph(1), 1));
516 CPPUNIT_ASSERT_EQUAL(
517 OUString(
518 u"iiint from {V} to <?> {\"divF\"} dV = llint from {S} to <?> {\"F\" \u2219 \"n\" dS}"),
519 aActual);
522 DECLARE_RTFEXPORT_TEST(testI120928, "i120928.rtf")
524 // \listpicture and \levelpicture0 was ignored, leading to missing graphic bullet in numbering.
525 uno::Reference<beans::XPropertySet> xPropertySet(
526 getStyles("NumberingStyles")->getByName("WWNum1"), uno::UNO_QUERY);
527 uno::Reference<container::XIndexAccess> xLevels(
528 xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
529 uno::Sequence<beans::PropertyValue> aProps;
530 xLevels->getByIndex(0) >>= aProps; // 1st level
532 uno::Reference<awt::XBitmap> xBitmap;
533 sal_Int16 nNumberingType = -1;
535 for (beans::PropertyValue const& rProp : std::as_const(aProps))
537 if (rProp.Name == "NumberingType")
538 nNumberingType = rProp.Value.get<sal_Int16>();
539 else if (rProp.Name == "GraphicBitmap")
540 xBitmap = rProp.Value.get<uno::Reference<awt::XBitmap>>();
542 CPPUNIT_ASSERT_EQUAL(style::NumberingType::BITMAP, nNumberingType);
543 CPPUNIT_ASSERT(xBitmap.is());
546 DECLARE_RTFEXPORT_TEST(testBookmark, "bookmark.rtf")
548 uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
549 uno::Reference<text::XTextContent> xBookmark(
550 xBookmarksSupplier->getBookmarks()->getByName("firstword"), uno::UNO_QUERY);
551 CPPUNIT_ASSERT_EQUAL(OUString("Hello"), xBookmark->getAnchor()->getString());
554 DECLARE_RTFEXPORT_TEST(testHyperlink, "hyperlink.rtf")
556 CPPUNIT_ASSERT_EQUAL(
557 OUString(), getProperty<OUString>(getRun(getParagraph(1), 1, "Hello"), "HyperLinkURL"));
558 CPPUNIT_ASSERT_EQUAL(
559 OUString("http://en.wikipedia.org/wiki/World"),
560 getProperty<OUString>(getRun(getParagraph(1), 2, "world"), "HyperLinkURL"));
561 CPPUNIT_ASSERT_EQUAL(OUString(),
562 getProperty<OUString>(getRun(getParagraph(1), 3, "!"), "HyperLinkURL"));
565 DECLARE_RTFEXPORT_TEST(testHyperlinkTdf100105, "hyperlink_empty.rtf")
567 // export of empty link was invalid, group was closed before it was opened
568 uno::Reference<text::XTextDocument> xTextDoc(mxComponent, uno::UNO_QUERY);
569 uno::Reference<text::XTextCursor> xCursor(xTextDoc->getText()->createTextCursor());
570 xCursor->gotoStart(false);
571 CPPUNIT_ASSERT_EQUAL(OUString("http://example.net"),
572 getProperty<OUString>(xCursor, "HyperLinkURL"));
573 // getRun doesn't provide a 0-length hyperlink
574 CPPUNIT_ASSERT_EQUAL(
575 OUString(), getProperty<OUString>(getRun(getParagraph(1), 1, "foobar"), "HyperLinkURL"));
578 DECLARE_RTFEXPORT_TEST(test78758, "fdo78758.rtf")
580 CPPUNIT_ASSERT_EQUAL(
581 OUString("#__RefHeading___Toc264438068"),
582 getProperty<OUString>(getRun(getParagraph(2), 1, "EE5E EeEEE5EE"), "HyperLinkURL"));
583 CPPUNIT_ASSERT_EQUAL(OUString("#__RefHeading___Toc264438068"),
584 getProperty<OUString>(getRun(getParagraph(2), 2, "e"), "HyperLinkURL"));
585 CPPUNIT_ASSERT_EQUAL(OUString("#__RefHeading___Toc264438068"),
586 getProperty<OUString>(getRun(getParagraph(2), 3, "\t46"), "HyperLinkURL"));
589 DECLARE_RTFEXPORT_TEST(testTextFrameBorders, "textframe-borders.rtf")
591 uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
592 uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(),
593 uno::UNO_QUERY);
594 uno::Reference<beans::XPropertySet> xFrame(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
595 CPPUNIT_ASSERT_EQUAL(Color(0xD99594), getProperty<Color>(xFrame, "BackColor"));
597 table::BorderLine2 aBorder = getProperty<table::BorderLine2>(xFrame, "TopBorder");
598 CPPUNIT_ASSERT_EQUAL(Color(0xC0504D), Color(ColorTransparency, aBorder.Color));
599 CPPUNIT_ASSERT_EQUAL(sal_uInt32(35), aBorder.LineWidth);
601 table::ShadowFormat aShadowFormat = getProperty<table::ShadowFormat>(xFrame, "ShadowFormat");
602 CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, aShadowFormat.Location);
603 CPPUNIT_ASSERT_EQUAL(sal_Int16(48), aShadowFormat.ShadowWidth);
604 CPPUNIT_ASSERT_EQUAL(Color(0x622423), Color(ColorTransparency, aShadowFormat.Color));
607 DECLARE_RTFEXPORT_TEST(testTextframeGradient, "textframe-gradient.rtf")
609 uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
610 uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(),
611 uno::UNO_QUERY);
612 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
614 uno::Reference<beans::XPropertySet> xFrame(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
615 CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT,
616 getProperty<drawing::FillStyle>(xFrame, "FillStyle"));
617 awt::Gradient2 aGradient = getProperty<awt::Gradient2>(xFrame, "FillGradient");
619 // prepare compare colors
620 const basegfx::BColor aColA(0.85098039215686272, 0.58431372549019611, 0.58039215686274515);
621 const basegfx::BColor aColB(0.75294117647058822, 0.31372549019607843, 0.30196078431372547);
622 const basegfx::BColor aColC(0.40000000000000002, 0.40000000000000002, 0.40000000000000002);
623 const basegfx::BColor aColD(0.0, 0.0, 0.0);
625 // MCGR: Use the completely imported transparency gradient to check for correctness
626 basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops);
628 CPPUNIT_ASSERT_EQUAL(size_t(3), aColorStops.size());
629 CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style);
630 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0));
631 CPPUNIT_ASSERT_EQUAL(aColorStops[0].getStopColor(), aColA);
632 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 0.5));
633 CPPUNIT_ASSERT_EQUAL(aColorStops[1].getStopColor(), aColB);
634 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[2].getStopOffset(), 1.0));
635 CPPUNIT_ASSERT_EQUAL(aColorStops[2].getStopColor(), aColA);
637 xFrame.set(xIndexAccess->getByIndex(1), uno::UNO_QUERY);
638 CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT,
639 getProperty<drawing::FillStyle>(xFrame, "FillStyle"));
640 aGradient = getProperty<awt::Gradient2>(xFrame, "FillGradient");
642 // MCGR: Use the completely imported transparency gradient to check for correctness
643 aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops);
645 CPPUNIT_ASSERT_EQUAL(size_t(3), aColorStops.size());
646 CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style);
647 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[0].getStopOffset(), 0.0));
648 CPPUNIT_ASSERT_EQUAL(aColorStops[0].getStopColor(), aColC);
649 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 0.5));
650 CPPUNIT_ASSERT_EQUAL(aColorStops[1].getStopColor(), aColD);
651 CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[2].getStopOffset(), 1.0));
652 CPPUNIT_ASSERT_EQUAL(aColorStops[2].getStopColor(), aColC);
655 DECLARE_RTFEXPORT_TEST(testRecordChanges, "record-changes.rtf")
657 // \revisions wasn't imported/exported.
658 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(mxComponent, "RecordChanges"));
661 DECLARE_RTFEXPORT_TEST(testTextframeTable, "textframe-table.rtf")
663 uno::Reference<text::XTextRange> xTextRange(getShape(1), uno::UNO_QUERY);
664 uno::Reference<text::XText> xText = xTextRange->getText();
665 CPPUNIT_ASSERT_EQUAL(OUString("First para."), getParagraphOfText(1, xText)->getString());
666 uno::Reference<text::XTextTable> xTable(getParagraphOrTable(2, xText), uno::UNO_QUERY);
667 CPPUNIT_ASSERT_EQUAL(OUString("A"), uno::Reference<text::XTextRange>(
668 xTable->getCellByName("A1"), uno::UNO_QUERY_THROW)
669 ->getString());
670 CPPUNIT_ASSERT_EQUAL(OUString("B"), uno::Reference<text::XTextRange>(
671 xTable->getCellByName("B1"), uno::UNO_QUERY_THROW)
672 ->getString());
673 CPPUNIT_ASSERT_EQUAL(OUString("Last para."), getParagraphOfText(3, xText)->getString());
676 DECLARE_RTFEXPORT_TEST(testFdo66682, "fdo66682.rtf")
678 uno::Reference<beans::XPropertySet> xPropertySet(
679 getStyles("NumberingStyles")->getByName("WWNum1"), uno::UNO_QUERY);
680 uno::Reference<container::XIndexAccess> xLevels(
681 xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
682 uno::Sequence<beans::PropertyValue> aProps;
683 xLevels->getByIndex(0) >>= aProps; // 1st level
685 OUString aListFormat;
686 for (beans::PropertyValue const& rProp : std::as_const(aProps))
688 if (rProp.Name == "ListFormat")
689 aListFormat = rProp.Value.get<OUString>();
691 // Suffix was '\0' instead of ' '.
692 CPPUNIT_ASSERT_EQUAL(OUString(" %1% "), aListFormat);
695 DECLARE_RTFEXPORT_TEST(testParaShadow, "para-shadow.rtf")
697 // The problem was that \brdrsh was ignored.
698 table::ShadowFormat aShadow
699 = getProperty<table::ShadowFormat>(getParagraph(2), "ParaShadowFormat");
700 CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(ColorTransparency, aShadow.Color));
701 CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, aShadow.Location);
702 CPPUNIT_ASSERT_EQUAL(sal_Int16(convertTwipToMm100(60)), aShadow.ShadowWidth);
705 CPPUNIT_TEST_FIXTURE(Test, testCharacterBorder)
707 loadAndReload("charborder.odt");
708 CPPUNIT_ASSERT_EQUAL(1, getPages());
709 uno::Reference<beans::XPropertySet> xRun(getRun(getParagraph(1), 1), uno::UNO_QUERY);
710 // RTF has just one border attribute (chbrdr) for text border so all side has
711 // the same border with the same padding
712 // Border
714 const table::BorderLine2 aTopBorder
715 = getProperty<table::BorderLine2>(xRun, "CharTopBorder");
716 CPPUNIT_ASSERT_BORDER_EQUAL(table::BorderLine2(0xFF6600, 0, 318, 0, 0, 318), aTopBorder);
717 CPPUNIT_ASSERT_BORDER_EQUAL(aTopBorder,
718 getProperty<table::BorderLine2>(xRun, "CharLeftBorder"));
719 CPPUNIT_ASSERT_BORDER_EQUAL(aTopBorder,
720 getProperty<table::BorderLine2>(xRun, "CharBottomBorder"));
721 CPPUNIT_ASSERT_BORDER_EQUAL(aTopBorder,
722 getProperty<table::BorderLine2>(xRun, "CharRightBorder"));
725 // Padding (brsp)
727 const sal_Int32 nTopPadding = getProperty<sal_Int32>(xRun, "CharTopBorderDistance");
728 // In the original ODT file the padding is 150, but the unit conversion round it down.
729 CPPUNIT_ASSERT_EQUAL(sal_Int32(141), nTopPadding);
730 CPPUNIT_ASSERT_EQUAL(nTopPadding, getProperty<sal_Int32>(xRun, "CharLeftBorderDistance"));
731 CPPUNIT_ASSERT_EQUAL(nTopPadding, getProperty<sal_Int32>(xRun, "CharBottomBorderDistance"));
732 CPPUNIT_ASSERT_EQUAL(nTopPadding, getProperty<sal_Int32>(xRun, "CharRightBorderDistance"));
735 // Shadow (brdrsh)
736 /* RTF use just one bool value for shadow so the next conversions
737 are made during an export-import round
738 color: any -> black
739 location: any -> bottom-right
740 width: any -> border width */
742 const table::ShadowFormat aShadow
743 = getProperty<table::ShadowFormat>(xRun, "CharShadowFormat");
744 CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(ColorTransparency, aShadow.Color));
745 CPPUNIT_ASSERT_EQUAL(table::ShadowLocation_BOTTOM_RIGHT, aShadow.Location);
746 CPPUNIT_ASSERT_EQUAL(sal_Int16(318), aShadow.ShadowWidth);
750 DECLARE_RTFEXPORT_TEST(testFdo66743, "fdo66743.rtf")
752 uno::Reference<text::XTextTable> xTable(getParagraphOrTable(1), uno::UNO_QUERY);
753 uno::Reference<table::XCell> xCell = xTable->getCellByName("A1");
754 // This was too dark, 0x7f7f7f.
755 CPPUNIT_ASSERT_EQUAL(Color(0xd8d8d8), getProperty<Color>(xCell, "BackColor"));
758 DECLARE_RTFEXPORT_TEST(testFdo68787, "fdo68787.rtf")
760 uno::Reference<beans::XPropertySet> xPageStyle(getStyles("PageStyles")->getByName("Standard"),
761 uno::UNO_QUERY);
762 // This was 0, the 'lack of \chftnsep' <-> '0 line width' mapping was missing in the RTF tokenizer / exporter.
763 CPPUNIT_ASSERT_EQUAL(sal_Int32(25),
764 getProperty<sal_Int32>(xPageStyle, "FootnoteLineRelativeWidth"));
767 DECLARE_RTFEXPORT_TEST(testFdo74709, "fdo74709.rtf")
769 uno::Reference<table::XCell> xCell = getCell(getParagraphOrTable(1), "B1");
770 // This was 0, as top/bottom/left/right padding wasn't imported.
771 CPPUNIT_ASSERT_EQUAL(sal_Int32(convertTwipToMm100(360)),
772 getProperty<sal_Int32>(xCell, "RightBorderDistance"));
775 CPPUNIT_TEST_FIXTURE(Test, testTdf84832)
777 loadAndReload("tdf84832.docx");
778 uno::Reference<table::XCell> xCell = getCell(getParagraphOrTable(2), "A1");
779 // This was 0, as left padding wasn't exported.
780 CPPUNIT_ASSERT_EQUAL(sal_Int32(convertTwipToMm100(108)),
781 getProperty<sal_Int32>(xCell, "LeftBorderDistance"));
784 DECLARE_RTFEXPORT_TEST(testRelsize, "relsize.rtf")
786 uno::Reference<drawing::XShape> xShape = getShape(1);
787 CPPUNIT_ASSERT_EQUAL(sal_Int16(40), getProperty<sal_Int16>(xShape, "RelativeWidth"));
788 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME,
789 getProperty<sal_Int16>(xShape, "RelativeWidthRelation"));
790 CPPUNIT_ASSERT_EQUAL(sal_Int16(20), getProperty<sal_Int16>(xShape, "RelativeHeight"));
791 CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME,
792 getProperty<sal_Int16>(xShape, "RelativeHeightRelation"));
795 DECLARE_RTFEXPORT_TEST(testLineNumbering, "linenumbering.rtf")
797 uno::Reference<text::XLineNumberingProperties> xLineNumberingProperties(mxComponent,
798 uno::UNO_QUERY_THROW);
799 uno::Reference<beans::XPropertySet> xPropertySet
800 = xLineNumberingProperties->getLineNumberingProperties();
801 CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPropertySet, "IsOn"));
802 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), getProperty<sal_Int32>(xPropertySet, "Interval"));
805 DECLARE_RTFEXPORT_TEST(testFdo77600, "fdo77600.rtf")
807 // This was 'Liberation Serif'.
808 CPPUNIT_ASSERT_EQUAL(OUString("Arial"),
809 getProperty<OUString>(getRun(getParagraph(1), 3), "CharFontName"));
812 DECLARE_RTFEXPORT_TEST(testFdo80167, "fdo80167.rtf")
814 // Problem was that after export, the page break was missing, so this was 1.
815 CPPUNIT_ASSERT_EQUAL(2, getPages());
818 CPPUNIT_TEST_FIXTURE(Test, testFdo32613)
820 loadAndReload("fdo32613.odt");
821 CPPUNIT_ASSERT_EQUAL(1, getShapes());
822 CPPUNIT_ASSERT_EQUAL(1, getPages());
823 // This was AS_CHARACTER, RTF export did not support writing anchored pictures.
824 CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
825 getProperty<text::TextContentAnchorType>(getShape(1), "AnchorType"));
828 CPPUNIT_PLUGIN_IMPLEMENT();
830 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */