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/.
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>
38 class Test
: public SwModelTestBase
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());
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(),
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(),
101 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
102 uno::Reference
<beans::XPropertySet
> xPropertySet(xParaEnum
->nextElement(), uno::UNO_QUERY
);
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(),
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(),
131 uno::Reference
<container::XEnumeration
> xRunEnum
= xRunEnumAccess
->createEnumeration();
132 uno::Reference
<beans::XPropertySet
> xPropertySet(xRunEnum
->nextElement(), uno::UNO_QUERY
);
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(),
145 uno::Reference
<container::XEnumeration
> xParaEnum
= xParaEnumAccess
->createEnumeration();
146 uno::Reference
<container::XEnumerationAccess
> xRunEnumAccess(xParaEnum
->nextElement(),
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"));
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}"),
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"),
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 )"),
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 "
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")
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(),
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(
518 u
"iiint from {V} to <?> {\"divF\"} dV = llint from {S} to <?> {\"F\" \u2219 \"n\" dS}"),
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(),
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(),
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
)
670 CPPUNIT_ASSERT_EQUAL(OUString("B"), uno::Reference
<text::XTextRange
>(
671 xTable
->getCellByName("B1"), uno::UNO_QUERY_THROW
)
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
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"));
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"));
736 /* RTF use just one bool value for shadow so the next conversions
737 are made during an export-import round
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"),
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: */