xref: /core/sw/qa/extras/odfexport/odfexport.cxx (revision 62d1a50659bfbf472748d844fba0f58be2d11c30)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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  */
9 
10 #include <tools/color.hxx>
11 #include <algorithm>
12 #include <memory>
13 #include <swmodeltestbase.hxx>
14 
15 #include <com/sun/star/awt/Gradient2.hpp>
16 #include <com/sun/star/awt/Key.hpp>
17 #include <com/sun/star/awt/KeyModifier.hpp>
18 #include <com/sun/star/beans/NamedValue.hpp>
19 #include <com/sun/star/container/XIndexReplace.hpp>
20 #include <com/sun/star/drawing/FillStyle.hpp>
21 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
22 #include <com/sun/star/table/ShadowFormat.hpp>
23 #include <com/sun/star/text/XBookmarksSupplier.hpp>
24 #include <com/sun/star/text/RelOrientation.hpp>
25 #include <com/sun/star/text/XDocumentIndex.hpp>
26 #include <com/sun/star/text/XTextSectionsSupplier.hpp>
27 #include <com/sun/star/text/XTextTablesSupplier.hpp>
28 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
29 #include <com/sun/star/graphic/XGraphic.hpp>
30 #include <officecfg/Office/Common.hxx>
31 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
32 #include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
33 #include <com/sun/star/text/XTextField.hpp>
34 #include <com/sun/star/util/XModifiable.hpp>
35 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
36 #include <com/sun/star/container/XIndexContainer.hpp>
37 #include <com/sun/star/document/XStorageBasedDocument.hpp>
38 #include <com/sun/star/text/XTextFramesSupplier.hpp>
39 #include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
40 #include <com/sun/star/text/XTextDocument.hpp>
41 #include <com/sun/star/util/XRefreshable.hpp>
42 #include <com/sun/star/text/XTextTable.hpp>
43 #include <com/sun/star/ui/ImageType.hpp>
44 #include <com/sun/star/ui/XImageManager.hpp>
45 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
46 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
47 
48 #include <comphelper/storagehelper.hxx>
49 #include <comphelper/fileformat.h>
50 #include <comphelper/documentconstants.hxx>
51 #include <svl/PasswordHelper.hxx>
52 #include <comphelper/scopeguard.hxx>
53 #include <docmodel/uno/UnoGradientTools.hxx>
54 #include <vcl/image.hxx>
55 
56 #include <docufld.hxx> // for SwHiddenTextField::ParseIfFieldDefinition() method call
57 #include <ftnidx.hxx>
58 #include <txtftn.hxx>
59 
60 namespace
61 {
62 class Test : public SwModelTestBase
63 {
64 public:
Test()65     Test() : SwModelTestBase(u"/sw/qa/extras/odfexport/data/"_ustr, u"writer8"_ustr) {}
66 };
67 
CPPUNIT_TEST_FIXTURE(Test,testMathObjectFlatExport)68 CPPUNIT_TEST_FIXTURE(Test, testMathObjectFlatExport)
69 {
70     comphelper::ScopeGuard g([this]() {
71         mpFilter = "writer8";
72         std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
73             comphelper::ConfigurationChanges::create());
74         officecfg::Office::Common::Cache::Writer::OLE_Objects::set(20, pBatch);
75         return pBatch->commit();
76     });
77     mpFilter = "OpenDocument Text Flat XML"; // doesn't happen with ODF package
78     std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
79         comphelper::ConfigurationChanges::create());
80     officecfg::Office::Common::Cache::Writer::OLE_Objects::set(1, pBatch);
81     pBatch->commit();
82     loadAndReload("2_MathType3.docx");
83 
84     uno::Reference<util::XModifiable> xModifiable(mxComponent, uno::UNO_QUERY);
85     CPPUNIT_ASSERT(!xModifiable->isModified());
86     // see above, set the OLE cache to 1 for this test
87     // and the problem was that the formulas that were in the cache
88     // (the second one) were lost
89     OUString formula1(getFormula(getRun(getParagraph(1), 1)));
90     CPPUNIT_ASSERT_EQUAL(u" size 12{1+1=2} {}"_ustr, formula1);
91     OUString formula2(getFormula(getRun(getParagraph(2), 1)));
92     CPPUNIT_ASSERT_EQUAL(u" size 12{2+2=4} {}"_ustr, formula2);
93 }
94 
95 DECLARE_ODFEXPORT_TEST(testTdf144319, "tdf144319.odt")
96 {
97     CPPUNIT_ASSERT_EQUAL(7, getShapes());
98     CPPUNIT_ASSERT_EQUAL(1, getPages());
99     OUString formula1(getFormula(getRun(getParagraph(3), 1)));
100     CPPUNIT_ASSERT_EQUAL(u"{ x = frac { { - b +- sqrt { b ^ 2 - 4 a c } } } { { 2 a } } }"_ustr, formula1);
101     OUString formula2(getFormula(getRun(getParagraph(4), 1)));
102     CPPUNIT_ASSERT_EQUAL(u"{ sum csup n csub { i = 1 } i ^ 3 = left ( frac { { n left ( { n + 1 } right ) } } { 2 } right ) ^ 2 }"_ustr, formula2);
103     OUString formula3(getFormula(getRun(getParagraph(5), 1)));
104     CPPUNIT_ASSERT_EQUAL(u"{ sum ^ n _ { i = 1 } i ^ 3 = left ( frac { { n left ( { n + 1 } right ) } } { 2 } right ) ^ 2 }"_ustr, formula3);
105     OUString formula4(getFormula(getRun(getParagraph(6), 1)));
106     CPPUNIT_ASSERT_EQUAL(u"{ sum ^ n _ { i = 1 } i ^ 3 = left ( frac { { n left ( { n + 1 } right ) } } { 2 } right ) ^ 2 }"_ustr, formula4);
107 
108     // Without the fix in place, this test would have failed with
109     // - the property is of unexpected type or void: Model
110     OUString formula5(getFormula(getRun(getParagraph(7), 1)));
111     CPPUNIT_ASSERT_EQUAL(u"{ y ^ 2 { nitalic m p } = left ( { x ^ 3 + 7 } right ) { nitalic m p } }"_ustr, formula5);
112 }
113 
testTdf43569_CheckIfFieldParse()114 void testTdf43569_CheckIfFieldParse()
115 {
116     {
117         OUString paramCondition;
118         OUString paramTrue;
119         OUString paramFalse;
120 
121         SwHiddenTextField::ParseIfFieldDefinition(u"IF A B C", paramCondition, paramTrue, paramFalse);
122 
123         CPPUNIT_ASSERT_EQUAL(u"A"_ustr, paramCondition);
124         CPPUNIT_ASSERT_EQUAL(u"B"_ustr, paramTrue);
125         CPPUNIT_ASSERT_EQUAL(u"C"_ustr, paramFalse);
126     }
127 
128     {
129         OUString paramCondition;
130         OUString paramTrue;
131         OUString paramFalse;
132 
133         SwHiddenTextField::ParseIfFieldDefinition(u"  IF AAA BBB CCC  ", paramCondition, paramTrue, paramFalse);
134 
135         CPPUNIT_ASSERT_EQUAL(u"AAA"_ustr, paramCondition);
136         CPPUNIT_ASSERT_EQUAL(u"BBB"_ustr, paramTrue);
137         CPPUNIT_ASSERT_EQUAL(u"CCC"_ustr, paramFalse);
138     }
139 
140     {
141         OUString paramCondition;
142         OUString paramTrue;
143         OUString paramFalse;
144 
145         SwHiddenTextField::ParseIfFieldDefinition(u"  IF AAA \"BBB\" \"CCC\"  ", paramCondition, paramTrue, paramFalse);
146 
147         CPPUNIT_ASSERT_EQUAL(u"AAA"_ustr, paramCondition);
148         CPPUNIT_ASSERT_EQUAL(u"BBB"_ustr, paramTrue);
149         CPPUNIT_ASSERT_EQUAL(u"CCC"_ustr, paramFalse);
150     }
151 
152     // true-case and false-case have spaces inside
153     {
154         OUString paramCondition;
155         OUString paramTrue;
156         OUString paramFalse;
157 
158         SwHiddenTextField::ParseIfFieldDefinition(u"  IF A A A \"B B B\" \"C C C\"  ", paramCondition, paramTrue, paramFalse);
159 
160         CPPUNIT_ASSERT_EQUAL(u"A A A"_ustr, paramCondition);
161         CPPUNIT_ASSERT_EQUAL(u"B B B"_ustr, paramTrue);
162         CPPUNIT_ASSERT_EQUAL(u"C C C"_ustr, paramFalse);
163     }
164 
165     // true-case and false-case have leading/trailing space
166     {
167         OUString paramCondition;
168         OUString paramTrue;
169         OUString paramFalse;
170 
171         SwHiddenTextField::ParseIfFieldDefinition(u"IF A1 A2 A3 \"B1 B2 \" \" C1 C2\"  ", paramCondition, paramTrue, paramFalse);
172 
173         CPPUNIT_ASSERT_EQUAL(u"A1 A2 A3"_ustr, paramCondition);
174         CPPUNIT_ASSERT_EQUAL(u"B1 B2 "_ustr, paramTrue);
175         CPPUNIT_ASSERT_EQUAL(u" C1 C2"_ustr, paramFalse);
176     }
177 
178     // true-case and false-case are empty
179     {
180         OUString paramCondition;
181         OUString paramTrue;
182         OUString paramFalse;
183 
184         SwHiddenTextField::ParseIfFieldDefinition(u"IF condition \"\" \"\"  ", paramCondition, paramTrue, paramFalse);
185 
186         CPPUNIT_ASSERT_EQUAL(u"condition"_ustr, paramCondition);
187         CPPUNIT_ASSERT_EQUAL(u""_ustr, paramTrue);
188         CPPUNIT_ASSERT_EQUAL(u""_ustr, paramFalse);
189     }
190 }
191 
192 // Input document contains only one IF-field,
193 // and it should be imported as com.sun.star.text.TextField.ConditionalText in any case,
194 // instead of insertion of the pair of two field-marks: <field:fieldmark-start> + <field:fieldmark-end>.
CPPUNIT_TEST_FIXTURE(Test,testTdf43569)195 CPPUNIT_TEST_FIXTURE(Test, testTdf43569)
196 {
197     loadAndReload("tdf43569_conditionalfield.doc");
198     // check if our parser is valid
199     testTdf43569_CheckIfFieldParse();
200 
201     // now check field creation during import
202     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
203     uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
204     uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
205 
206     // at least one field should be detected
207     CPPUNIT_ASSERT(xFields->hasMoreElements());
208 }
209 
CPPUNIT_TEST_FIXTURE(Test,testTdf130314)210 CPPUNIT_TEST_FIXTURE(Test, testTdf130314)
211 {
212     loadAndReload("tdf130314.docx");
213     // Without the fix in place, this test would have hung
214     CPPUNIT_ASSERT_EQUAL(2, getPages());
215 }
216 
CPPUNIT_TEST_FIXTURE(Test,testTdf133487)217 CPPUNIT_TEST_FIXTURE(Test, testTdf133487)
218 {
219     loadAndReload("MadeByLO7.odt");
220     CPPUNIT_ASSERT_EQUAL(3, getShapes());
221     CPPUNIT_ASSERT_EQUAL(1, getPages());
222     xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
223     // shape in background has lowest index
224     assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p[2]/draw:custom-shape", "z-index", u"0");
225     assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name = /office:document-content/office:body/office:text/text:p[2]/draw:custom-shape[@draw:z-index = '0']/attribute::draw:style-name]/style:graphic-properties", "run-through", u"background");
226     // shape in foreground, previously index 1
227     assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p[1]/draw:custom-shape", "z-index", u"2");
228     assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name = /office:document-content/office:body/office:text/text:p[1]/draw:custom-shape[@draw:z-index = '2']/attribute::draw:style-name]/style:graphic-properties", "run-through", u"foreground");
229     // shape in foreground, previously index 0
230     assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p[3]/draw:custom-shape", "z-index", u"1");
231     assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name = /office:document-content/office:body/office:text/text:p[3]/draw:custom-shape[@draw:z-index = '1']/attribute::draw:style-name]/style:graphic-properties", "run-through", u"foreground");
232 }
233 
CPPUNIT_TEST_FIXTURE(Test,testTdf141467)234 CPPUNIT_TEST_FIXTURE(Test, testTdf141467)
235 {
236     loadAndReload("Formcontrol needs high z-index.odt");
237     CPPUNIT_ASSERT_EQUAL(2, getShapes());
238     CPPUNIT_ASSERT_EQUAL(1, getPages());
239     xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
240     // shape in foreground has lowest index
241     assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p[2]/draw:custom-shape", "z-index", u"0");
242     assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name = /office:document-content/office:body/office:text/text:p[2]/draw:custom-shape[@draw:z-index = '0']/attribute::draw:style-name]/style:graphic-properties", "run-through", u"foreground");
243     // form control, previously index 0
244     assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p[2]/draw:control", "z-index", u"1");
245     // no run-through on form's style
246     assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name = /office:document-content/office:body/office:text/text:p[2]/draw:control[@draw:z-index = '1']/attribute::draw:style-name]/style:graphic-properties/attribute::run-through", 0);
247 }
248 
249 DECLARE_ODFEXPORT_TEST(testTdf139126, "tdf139126.odt")
250 {
251     CPPUNIT_ASSERT_EQUAL(1, getPages());
252     uno::Reference<text::XTextTablesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
253     uno::Reference<container::XNameAccess> xTables = xSupplier->getTextTables();
254     uno::Reference<text::XTextTable> xTable(xTables->getByName(u"Table1"_ustr), uno::UNO_QUERY);
255 
256     uno::Reference<text::XTextRange> xD2(xTable->getCellByName(u"D2"_ustr), uno::UNO_QUERY);
257     CPPUNIT_ASSERT_EQUAL(u"4.0"_ustr, xD2->getString());
258 
259     // Without the fix in place, this test would have failed with
260     // - Expected: ** Expression is faulty **
261     // - Actual  : 17976931348623200...
262     uno::Reference<text::XTextRange> xE2(xTable->getCellByName(u"E2"_ustr), uno::UNO_QUERY);
263     CPPUNIT_ASSERT_EQUAL(u"** Expression is faulty **"_ustr, xE2->getString());
264 }
265 
CPPUNIT_TEST_FIXTURE(Test,testTdf125877)266 CPPUNIT_TEST_FIXTURE(Test, testTdf125877)
267 {
268     loadAndReload("tdf95806.docx");
269     CPPUNIT_ASSERT_EQUAL(1, getPages());
270     uno::Reference<text::XTextTablesSupplier> xSupplier(mxComponent, uno::UNO_QUERY);
271     uno::Reference<container::XIndexAccess> xTables(xSupplier->getTextTables(), uno::UNO_QUERY);
272 
273     // This was 0 (lost table during ODT export in footnotes)
274     // Note: fix also tdf#95806: painting table layout is correct
275     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount());
276 
277     // floating table: there is a frame now
278     uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
279     uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
280     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
281 }
282 
CPPUNIT_TEST_FIXTURE(Test,testTdf150149)283 CPPUNIT_TEST_FIXTURE(Test, testTdf150149)
284 {
285     loadAndReload("tdf150149.fodt");
286     CPPUNIT_ASSERT_EQUAL(1, getPages());
287     xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
288     // This was 0 (lost table header in multi-column section)
289     assertXPath(pXmlDoc, "//table:table-header-rows", 1);
290     assertXPath(pXmlDoc, "//table:table-header-rows/table:table-row/table:table-cell", 3);
291 }
292 
293 DECLARE_ODFEXPORT_TEST(testTdf103567, "tdf103567.odt")
294 {
295     CPPUNIT_ASSERT_EQUAL(1, getShapes());
296     CPPUNIT_ASSERT_EQUAL(1, getPages());
297     uno::Reference<drawing::XShape> const xShape(getShape(1));
298 
299     // contour wrap polygon
300     css::drawing::PointSequenceSequence const pointss(
301         getProperty<css::drawing::PointSequenceSequence>(xShape, u"ContourPolyPolygon"_ustr));
302     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), pointss.getLength());
303     // for some reason this property exists with 199 points if it wasn't
304     // imported, that would be a fail
305     CPPUNIT_ASSERT_EQUAL(sal_Int32(5), pointss[0].getLength());
306     CPPUNIT_ASSERT_EQUAL(sal_Int32(   0), pointss[0][0].X);
307     CPPUNIT_ASSERT_EQUAL(sal_Int32(2672), pointss[0][0].Y);
308     CPPUNIT_ASSERT_EQUAL(sal_Int32(   0), pointss[0][1].X);
309     CPPUNIT_ASSERT_EQUAL(sal_Int32(1111), pointss[0][1].Y);
310     CPPUNIT_ASSERT_EQUAL(sal_Int32(2672), pointss[0][2].X);
311     CPPUNIT_ASSERT_EQUAL(sal_Int32(1111), pointss[0][2].Y);
312     CPPUNIT_ASSERT_EQUAL(sal_Int32(2672), pointss[0][3].X);
313     CPPUNIT_ASSERT_EQUAL(sal_Int32(2672), pointss[0][3].Y);
314     CPPUNIT_ASSERT_EQUAL(sal_Int32(   0), pointss[0][4].X);
315     CPPUNIT_ASSERT_EQUAL(sal_Int32(2672), pointss[0][4].Y);
316 
317     // image map, one rectangle
318     uno::Reference<container::XIndexContainer> const xImageMap(
319         getProperty<uno::Reference<container::XIndexContainer>>(xShape, u"ImageMap"_ustr));
320 
321     uno::Reference<beans::XPropertySet> const xEntry(xImageMap->getByIndex(0), uno::UNO_QUERY);
322     CPPUNIT_ASSERT_EQUAL(u"http://example.com/"_ustr, getProperty<OUString>(xEntry, u"URL"_ustr));
323     awt::Rectangle const rect(getProperty<awt::Rectangle>(xEntry, u"Boundary"_ustr));
324     CPPUNIT_ASSERT_EQUAL(sal_Int32( 726), rect.X);
325     CPPUNIT_ASSERT_EQUAL(sal_Int32(1718), rect.Y);
326     CPPUNIT_ASSERT_EQUAL(sal_Int32(1347), rect.Width);
327     CPPUNIT_ASSERT_EQUAL(sal_Int32( 408), rect.Height);
328 }
329 
CPPUNIT_TEST_FIXTURE(Test,testUserFieldDecl)330 CPPUNIT_TEST_FIXTURE(Test, testUserFieldDecl)
331 {
332     loadAndReload("user-field-decl.odt");
333     CPPUNIT_ASSERT_EQUAL(1, getPages());
334     xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
335     // Without the accompanying fix in place, this test would have failed with 'Expected: 2;
336     // Actual: 1', i.e. the in-table field had no declaration (in the header), while the
337     // outside-table one had the declaration.
338     assertXPath(pXmlDoc, "//style:header/text:user-field-decls/text:user-field-decl", 2);
339 }
340 
CPPUNIT_TEST_FIXTURE(Test,testUserFieldDeclFly)341 CPPUNIT_TEST_FIXTURE(Test, testUserFieldDeclFly)
342 {
343     loadAndReload("user-field-decl-fly.odt");
344     CPPUNIT_ASSERT_EQUAL(1, getShapes());
345     CPPUNIT_ASSERT_EQUAL(1, getPages());
346     xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
347     // Without the accompanying fix in place, this test would have failed with 'Expected: 2;
348     // Actual: 1', i.e. the in-textframe field had no declaration (in the header), while the
349     // outside-textframe one had the declaration.
350     assertXPath(pXmlDoc, "//style:header/text:user-field-decls/text:user-field-decl", 2);
351 }
352 
CPPUNIT_TEST_FIXTURE(Test,testFramebackgrounds)353 CPPUNIT_TEST_FIXTURE(Test, testFramebackgrounds)
354 {
355     auto verify = [this]() {
356         CPPUNIT_ASSERT_EQUAL(16, getShapes());
357         CPPUNIT_ASSERT_EQUAL(1, getPages());
358        //Counting the Number of Frames and checking with the expected count
359         uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
360         uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
361         CPPUNIT_ASSERT_EQUAL(sal_Int32(16), xIndexAccess->getCount());
362         uno::Reference<drawing::XShape> xTextFrame;
363         awt::Gradient aGradientxTextFrame;
364         //Frame 1
365         xTextFrame = getShape(1);
366         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
367         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
368         //Frame 2
369         xTextFrame = getShape(2);
370         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
371         CPPUNIT_ASSERT_EQUAL(Color(0x006600), getProperty<Color>(xTextFrame, u"FillColor"_ustr));
372         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
373         //Frame 3
374         xTextFrame = getShape(3);
375         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
376         CPPUNIT_ASSERT_EQUAL(Color(0x006600), getProperty<Color>(xTextFrame, u"FillColor"_ustr));
377         CPPUNIT_ASSERT_EQUAL(sal_Int32(45), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
378         //Frame 4
379         xTextFrame = getShape(4);
380         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
381         CPPUNIT_ASSERT_EQUAL(Color(0x579D1C), getProperty<Color>(xTextFrame, u"FillColor"_ustr));
382         aGradientxTextFrame = getProperty<awt::Gradient>(xTextFrame, u"FillTransparenceGradient"_ustr);
383         CPPUNIT_ASSERT_EQUAL(css::awt::GradientStyle_LINEAR, aGradientxTextFrame.Style);
384         //Frame 5
385         xTextFrame = getShape(5);
386         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
387         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
388         CPPUNIT_ASSERT_EQUAL(u"Subtle Tango Green"_ustr, getProperty<OUString>(xTextFrame, u"FillGradientName"_ustr));
389         //Frame 6
390         xTextFrame = getShape(6);
391         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
392         CPPUNIT_ASSERT_EQUAL(u"Subtle Tango Green"_ustr, getProperty<OUString>(xTextFrame, u"FillGradientName"_ustr));
393         CPPUNIT_ASSERT_EQUAL(sal_Int32(45), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
394         //Frame 7
395         xTextFrame = getShape(7);
396         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
397         CPPUNIT_ASSERT_EQUAL(u"Subtle Tango Green"_ustr, getProperty<OUString>(xTextFrame, u"FillGradientName"_ustr));
398         aGradientxTextFrame = getProperty<awt::Gradient>(xTextFrame, u"FillTransparenceGradient"_ustr);
399         CPPUNIT_ASSERT_EQUAL(css::awt::GradientStyle_LINEAR, aGradientxTextFrame.Style);
400         //Frame 8
401         xTextFrame = getShape(8);
402         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_HATCH, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
403         CPPUNIT_ASSERT_EQUAL(u"Black 0 Degrees"_ustr, getProperty<OUString>(xTextFrame, u"FillHatchName"_ustr));
404         CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xTextFrame, u"FillBackground"_ustr));
405         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
406         //Frame 9
407         xTextFrame = getShape(9);
408         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_HATCH, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
409         CPPUNIT_ASSERT_EQUAL(u"Black 0 Degrees"_ustr, getProperty<OUString>(xTextFrame, u"FillHatchName"_ustr));
410         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextFrame, u"FillBackground"_ustr));
411         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
412         //Frame 10
413         xTextFrame = getShape(10);
414         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_HATCH, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
415         CPPUNIT_ASSERT_EQUAL(u"Black 0 Degrees"_ustr, getProperty<OUString>(xTextFrame, u"FillHatchName"_ustr));
416         CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xTextFrame, u"FillBackground"_ustr));
417         CPPUNIT_ASSERT_EQUAL(sal_Int32(45), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
418         //Frame 11
419         xTextFrame = getShape(11);
420         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_HATCH, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
421         CPPUNIT_ASSERT_EQUAL(u"Black 0 Degrees"_ustr, getProperty<OUString>(xTextFrame, u"FillHatchName"_ustr));
422         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextFrame, u"FillBackground"_ustr));
423         CPPUNIT_ASSERT_EQUAL(sal_Int32(45), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
424         //Frame 12
425         xTextFrame = getShape(12);
426         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_HATCH, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
427         CPPUNIT_ASSERT_EQUAL(u"Black 0 Degrees"_ustr, getProperty<OUString>(xTextFrame, u"FillHatchName"_ustr));
428         CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xTextFrame, u"FillBackground"_ustr));
429         aGradientxTextFrame = getProperty<awt::Gradient>(xTextFrame, u"FillTransparenceGradient"_ustr);
430         CPPUNIT_ASSERT_EQUAL(css::awt::GradientStyle_LINEAR, aGradientxTextFrame.Style);
431         //Frame 13
432         xTextFrame = getShape(13);
433         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_HATCH, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
434         CPPUNIT_ASSERT_EQUAL(u"Black 0 Degrees"_ustr, getProperty<OUString>(xTextFrame, u"FillHatchName"_ustr));
435         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextFrame, u"FillBackground"_ustr));
436         aGradientxTextFrame = getProperty<awt::Gradient>(xTextFrame, u"FillTransparenceGradient"_ustr);
437         CPPUNIT_ASSERT_EQUAL(css::awt::GradientStyle_LINEAR, aGradientxTextFrame.Style);
438         //Frame 14
439         xTextFrame = getShape(14);
440         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
441         CPPUNIT_ASSERT_EQUAL(u"Sky"_ustr, getProperty<OUString>(xTextFrame, u"FillBitmapName"_ustr));
442         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
443         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapPositionOffsetX"_ustr));
444         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapPositionOffsetY"_ustr));
445         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapOffsetX"_ustr));
446         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapOffsetY"_ustr));
447         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextFrame, u"FillBitmapTile"_ustr));
448         //Frame 15
449         xTextFrame = getShape(15);
450         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
451         CPPUNIT_ASSERT_EQUAL(u"Sky"_ustr, getProperty<OUString>(xTextFrame, u"FillBitmapName"_ustr));
452         CPPUNIT_ASSERT_EQUAL(sal_Int32(45), getProperty<sal_Int32>(xTextFrame, u"FillTransparence"_ustr));
453         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapPositionOffsetX"_ustr));
454         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapPositionOffsetY"_ustr));
455         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapOffsetX"_ustr));
456         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapOffsetY"_ustr));
457         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextFrame, u"FillBitmapTile"_ustr));
458         //Frame 16
459         xTextFrame = getShape(16);
460         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_BITMAP, getProperty<drawing::FillStyle>(xTextFrame, u"FillStyle"_ustr));
461         CPPUNIT_ASSERT_EQUAL(u"Sky"_ustr, getProperty<OUString>(xTextFrame, u"FillBitmapName"_ustr));
462         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapPositionOffsetX"_ustr));
463         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapPositionOffsetY"_ustr));
464         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapOffsetX"_ustr));
465         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xTextFrame, u"FillBitmapOffsetY"_ustr));
466         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTextFrame, u"FillBitmapTile"_ustr));
467         aGradientxTextFrame = getProperty<awt::Gradient>(xTextFrame, u"FillTransparenceGradient"_ustr);
468         CPPUNIT_ASSERT_EQUAL(css::awt::GradientStyle_LINEAR, aGradientxTextFrame.Style);
469     };
470 
471     createSwDoc("framebackgrounds.odt");
472     verify();
473     saveAndReload(mpFilter);
474     verify();
475 
476     xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
477     // check that there are 3 background-image elements
478     assertXPath(pXmlDoc, "//style:style[@style:parent-style-name='Frame' and @style:family='graphic']/style:graphic-properties[@draw:fill='bitmap']/style:background-image[@style:repeat='stretch']", 3);
479     // tdf#90640: check that one of them is 55% opaque
480     assertXPath(pXmlDoc, "//style:style[@style:parent-style-name='Frame' and @style:family='graphic']/style:graphic-properties[@draw:fill='bitmap' and @fo:background-color='transparent' and @draw:opacity='55%']/style:background-image[@style:repeat='stretch' and @draw:opacity='55%']", 1);
481     // tdf#90640: check that one of them is 43% opaque
482     // (emulated - hopefully not with rounding errors)
483     assertXPath(pXmlDoc, "//style:style[@style:parent-style-name='Frame' and @style:family='graphic']/style:graphic-properties[@draw:fill='bitmap' and @fo:background-color='transparent' and @draw:opacity-name='Transparency_20_1']/style:background-image[@style:repeat='stretch' and @draw:opacity='43%']", 1);
484 }
485 
CPPUNIT_TEST_FIXTURE(Test,testSHA1Correct)486 CPPUNIT_TEST_FIXTURE(Test, testSHA1Correct)
487 {   // tdf#114939 this has both an affected password as well as content.xml
488     const char* const sPass = "1012345678901234567890123456789012345678901234567890";
489     createSwDoc("sha1_correct.odt", sPass);
490 
491     CPPUNIT_ASSERT_EQUAL(1, getPages());
492     getParagraph(1, u"012"_ustr);
493 
494     saveAndReload(mpFilter, sPass);
495 
496     CPPUNIT_ASSERT_EQUAL(1, getPages());
497     getParagraph(1, u"012"_ustr);
498 }
499 
CPPUNIT_TEST_FIXTURE(Test,testSHA1Wrong)500 CPPUNIT_TEST_FIXTURE(Test, testSHA1Wrong)
501 {   // tdf#114939 this has both an affected password as well as content.xml
502     const char* const sPass = "1012345678901234567890123456789012345678901234567890";
503     createSwDoc("sha1_wrong.odt", sPass);
504 
505     CPPUNIT_ASSERT_EQUAL(1, getPages());
506     getParagraph(1, u"012"_ustr);
507 
508     saveAndReload(mpFilter, sPass);
509 
510     CPPUNIT_ASSERT_EQUAL(1, getPages());
511     getParagraph(1, u"012"_ustr);
512 }
513 
CPPUNIT_TEST_FIXTURE(Test,testOOoxmlEmbedded)514 CPPUNIT_TEST_FIXTURE(Test, testOOoxmlEmbedded)
515 {
516     loadAndReload("oooxml_embedded.sxw");
517     uno::Reference<text::XTextEmbeddedObjectsSupplier> xTEOSupplier(mxComponent, uno::UNO_QUERY);
518     uno::Reference<container::XNameAccess> xAccess(xTEOSupplier->getEmbeddedObjects());
519     uno::Sequence<OUString> aSeq(xAccess->getElementNames());
520     CPPUNIT_ASSERT_EQUAL(sal_Int32(4), aSeq.getLength());
521     uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier1(xAccess->getByName(u"Object1"_ustr), uno::UNO_QUERY);
522     uno::Reference<lang::XComponent> xObj1(xEOSupplier1->getEmbeddedObject());
523     uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier2(xAccess->getByName(u"Object2"_ustr), uno::UNO_QUERY);
524     uno::Reference<lang::XComponent> xObj2(xEOSupplier2->getEmbeddedObject());
525     uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier3(xAccess->getByName(u"Object3"_ustr), uno::UNO_QUERY);
526     uno::Reference<lang::XComponent> xObj3(xEOSupplier3->getEmbeddedObject());
527     uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier4(xAccess->getByName(u"Object4"_ustr), uno::UNO_QUERY);
528     uno::Reference<lang::XComponent> xObj4(xEOSupplier4->getEmbeddedObject());
529     //checking first object
530     uno::Reference<document::XStorageBasedDocument> xSBDoc1(xObj1, uno::UNO_QUERY);
531     uno::Reference<embed::XStorage> xStorage1(xSBDoc1->getDocumentStorage());
532     CPPUNIT_ASSERT_EQUAL(sal_Int32(SOFFICE_FILEFORMAT_8), comphelper::OStorageHelper::GetXStorageFormat(xStorage1));
533     //checking second object
534     uno::Reference<document::XStorageBasedDocument> xSBDoc2(xObj2, uno::UNO_QUERY);
535     uno::Reference<embed::XStorage> xStorage2(xSBDoc2->getDocumentStorage());
536     CPPUNIT_ASSERT_EQUAL(sal_Int32(SOFFICE_FILEFORMAT_8), comphelper::OStorageHelper::GetXStorageFormat(xStorage2));
537     //checking third object
538     uno::Reference<document::XStorageBasedDocument> xSBDoc3(xObj3, uno::UNO_QUERY);
539     uno::Reference<embed::XStorage> xStorage3(xSBDoc3->getDocumentStorage());
540     CPPUNIT_ASSERT_EQUAL(sal_Int32(SOFFICE_FILEFORMAT_8), comphelper::OStorageHelper::GetXStorageFormat(xStorage3));
541     //checking fourth object
542     uno::Reference<document::XStorageBasedDocument> xSBDoc4(xObj4, uno::UNO_QUERY);
543     uno::Reference<embed::XStorage> xStorage4(xSBDoc4->getDocumentStorage());
544     CPPUNIT_ASSERT_EQUAL(sal_Int32(SOFFICE_FILEFORMAT_8), comphelper::OStorageHelper::GetXStorageFormat(xStorage4));
545 }
546 
547 DECLARE_ODFEXPORT_TEST(testTdf152710, "tdf152710.odt")
548 {
549     // Without this fix in place, this test would have crash at import time
550     CPPUNIT_ASSERT_EQUAL(2, getPages());
551 }
552 
553 DECLARE_ODFEXPORT_TEST(testredlineTextFrame, "redlineTextFrame.odt")
554 {
555     CPPUNIT_ASSERT_EQUAL(2, getShapes());
556     CPPUNIT_ASSERT_EQUAL(1, getPages());
557     //Note this is for a crash test
558     //Counting the Number of Frames and checking with the expected count
559     uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
560     uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
561     CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xIndexAccess->getCount());
562 }
563 
564 DECLARE_ODFEXPORT_TEST(testTdf107292, "tdf107292.odt")
565 {
566     // tracked deletions at the same position were loaded in reverse order
567     CPPUNIT_ASSERT_EQUAL(1, getPages());
568 
569     // Without this fix in place, this test would have failed with
570     // - Expected: Lorem ipsum dolor sit...
571     // - Actual  :  dolor ipsumLorem sit...
572     CPPUNIT_ASSERT_EQUAL(u"Lorem ipsum dolor sit..."_ustr, getParagraph(1)->getString());
573 }
574 
575 DECLARE_ODFEXPORT_TEST(testTdf140437, "tdf140437.odt")
576 {
577     // Without the fix in place, the document would have failed to load
578     CPPUNIT_ASSERT_EQUAL(1, getPages());
579 
580     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
581     uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
582     uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
583 
584     // at least one field should be detected
585     CPPUNIT_ASSERT(xFields->hasMoreElements());
586 }
587 
CPPUNIT_TEST_FIXTURE(Test,testTdf131621)588 CPPUNIT_TEST_FIXTURE(Test, testTdf131621)
589 {
590     loadAndReload("tdf131621.ott");
591     CPPUNIT_ASSERT_EQUAL(12, getShapes());
592     //Crash test, Check number of pages
593     CPPUNIT_ASSERT_EQUAL( 1, getPages() );
594 }
595 
CPPUNIT_TEST_FIXTURE(Test,testTdf135144)596 CPPUNIT_TEST_FIXTURE(Test, testTdf135144)
597 {
598     loadAndReload("tdf135144.docx");
599     //Crashes at import time after roundtrip
600     CPPUNIT_ASSERT_EQUAL(3, getPages());
601     CPPUNIT_ASSERT_EQUAL(4, getShapes());
602 }
603 
604 DECLARE_ODFEXPORT_TEST(testTdf130950, "tdf130950.odt")
605 {
606     //Crashes at import time
607     CPPUNIT_ASSERT_EQUAL(1, getPages());
608     CPPUNIT_ASSERT_EQUAL(2, getShapes());
609 }
610 
611 DECLARE_ODFEXPORT_TEST(testFdo38244, "fdo38244.odt")
612 {
613     CPPUNIT_ASSERT_EQUAL(1, getPages());
614     // See ooxmlexport's testFdo38244().
615 
616     // Test comment range feature.
617     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
618     uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
619     uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
620     uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
621     uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
622     xRunEnum->nextElement();
623     uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
624     CPPUNIT_ASSERT_EQUAL(u"Annotation"_ustr, getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr));
625     xRunEnum->nextElement();
626     xPropertySet.set(xRunEnum->nextElement(), uno::UNO_QUERY);
627     CPPUNIT_ASSERT_EQUAL(u"AnnotationEnd"_ustr, getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr));
628 
629     // Test properties
630     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
631     uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
632     uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
633     xPropertySet.set(xFields->nextElement(), uno::UNO_QUERY);
634     CPPUNIT_ASSERT_EQUAL(u"__Fieldmark__4_1833023242"_ustr, getProperty<OUString>(xPropertySet, u"Name"_ustr));
635     CPPUNIT_ASSERT_EQUAL(u"M"_ustr, getProperty<OUString>(xPropertySet, u"Initials"_ustr));
636 }
637 
CPPUNIT_TEST_FIXTURE(Test,testSenderInitials)638 CPPUNIT_TEST_FIXTURE(Test, testSenderInitials)
639 {
640     loadAndReload("sender-initials.fodt");
641     // Test sender-initial properties (both annotation metadata and text field)
642     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
643     uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
644     uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
645     // first 3 are annotations, last 2 are text fields
646     for (unsigned i = 0; i < 3; ++i)
647     {
648         uno::Reference<beans::XPropertySet> xPropertySet(xFields->nextElement(), uno::UNO_QUERY);
649         CPPUNIT_ASSERT_EQUAL(u"I"_ustr, getProperty<OUString>(xPropertySet, u"Initials"_ustr));
650     }
651     for (unsigned i = 0; i < 2; ++i)
652     {
653         uno::Reference<beans::XPropertySet> xPropertySet(xFields->nextElement(), uno::UNO_QUERY);
654         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPropertySet, u"IsFixed"_ustr));
655         CPPUNIT_ASSERT_EQUAL(u"I"_ustr, getProperty<OUString>(xPropertySet, u"Content"_ustr));
656     }
657 }
658 
659 DECLARE_ODFEXPORT_TEST(testResolvedComment, "resolved-comment.odt")
660 {
661     CPPUNIT_ASSERT_EQUAL(1, getPages());
662     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
663     uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
664     uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
665     uno::Reference<beans::XPropertySet> xPropertySet(xFields->nextElement(), uno::UNO_QUERY);
666     CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xPropertySet, u"Resolved"_ustr));
667     xPropertySet.set(xFields->nextElement(), uno::UNO_QUERY);
668     CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xPropertySet, u"Resolved"_ustr));
669 }
670 
CPPUNIT_TEST_FIXTURE(Test,testTdf92379)671 CPPUNIT_TEST_FIXTURE(Test, testTdf92379)
672 {
673     auto verify = [this]() {
674         // frame style fo:background-color was not imported
675         uno::Reference<container::XNameAccess> xStyles(getStyles(u"FrameStyles"_ustr));
676         uno::Reference<beans::XPropertySet> xStyle(xStyles->getByName(u"encarts"_ustr),
677                 uno::UNO_QUERY);
678         CPPUNIT_ASSERT_EQUAL(Color(0xffcc99), getProperty<Color>(xStyle, u"BackColorRGB"_ustr));
679         CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xStyle, u"BackColorTransparency"_ustr));
680         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xStyle, u"FillStyle"_ustr));
681         CPPUNIT_ASSERT_EQUAL(Color(0xffcc99), getProperty<Color>(xStyle, u"FillColor"_ustr));
682         CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xStyle, u"FillTransparence"_ustr));
683 
684         uno::Reference<beans::XPropertySet> xFrameStyle2(xStyles->getByName(u"Untitled1"_ustr),
685                 uno::UNO_QUERY);
686         CPPUNIT_ASSERT_EQUAL(COL_WHITE, getProperty<Color>(xFrameStyle2, u"BackColorRGB"_ustr));
687         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xFrameStyle2, u"BackTransparent"_ustr));
688         CPPUNIT_ASSERT_EQUAL(sal_Int32(100), getProperty<sal_Int32>(xFrameStyle2, u"BackColorTransparency"_ustr));
689         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xFrameStyle2, u"FillStyle"_ustr));
690     // unfortunately this is actually the pool default value, which would be hard to fix - but it isn't a problem because style is NONE
691     //    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xFrameStyle2, "FillColor"));
692     //    CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xFrameStyle2, "FillTransparence"));
693 
694         // paragraph style fo:background-color was wrongly inherited despite being
695         // overridden in derived style
696         uno::Reference<container::XNameAccess> xParaStyles(getStyles(u"ParagraphStyles"_ustr));
697         uno::Reference<beans::XPropertySet> xStyle1(xParaStyles->getByName(
698                 u"Titre Avis expert"_ustr), uno::UNO_QUERY);
699         CPPUNIT_ASSERT_EQUAL(Color(0x661900), getProperty<Color>(xStyle1, u"ParaBackColor"_ustr));
700         CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xStyle1, u"ParaBackTransparent"_ustr));
701         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xStyle1, u"FillStyle"_ustr));
702         CPPUNIT_ASSERT_EQUAL(Color(0x661900), getProperty<Color>(xStyle1, u"FillColor"_ustr));
703         CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xStyle1, u"FillTransparence"_ustr));
704         CPPUNIT_ASSERT_EQUAL(COL_WHITE, getProperty<Color>(xStyle1, u"CharColor"_ustr));
705 
706         uno::Reference<beans::XPropertySet> xStyle2(xParaStyles->getByName(
707                 u"Avis expert questions"_ustr), uno::UNO_QUERY);
708         CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, getProperty<Color>(xStyle2, u"ParaBackColor"_ustr));
709         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xStyle2, u"ParaBackTransparent"_ustr));
710         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xStyle2, u"FillStyle"_ustr));
711     // unfortunately this is actually the pool default value, which would be hard to fix - but it isn't a problem because style is NONE
712     //    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xStyle2, "FillColor"));
713     //    CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xStyle2, "FillTransparence"));
714         CPPUNIT_ASSERT_EQUAL(Color(0x661900), getProperty<Color>(xStyle2, u"CharColor"_ustr));
715 
716         uno::Reference<beans::XPropertySet> xStyle31(xParaStyles->getByName(
717                 u"avis expert questions non cadres"_ustr), uno::UNO_QUERY);
718         CPPUNIT_ASSERT_EQUAL(Color(0x801900), getProperty<Color>(xStyle31, u"ParaBackColor"_ustr));
719         CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xStyle31, u"ParaBackTransparent"_ustr));
720         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_SOLID, getProperty<drawing::FillStyle>(xStyle31, u"FillStyle"_ustr));
721         CPPUNIT_ASSERT_EQUAL(Color(0x801900), getProperty<Color>(xStyle31, u"FillColor"_ustr));
722         CPPUNIT_ASSERT_EQUAL(sal_Int16(0), getProperty<sal_Int16>(xStyle31, u"FillTransparence"_ustr));
723         CPPUNIT_ASSERT_EQUAL(Color(0x661900), getProperty<Color>(xStyle31, u"CharColor"_ustr));
724 
725         uno::Reference<beans::XPropertySet> xStyle32(xParaStyles->getByName(
726                 u"Avis expert rXponses"_ustr), uno::UNO_QUERY);
727         CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, getProperty<Color>(xStyle32, u"ParaBackColor"_ustr));
728         CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xStyle32, u"ParaBackTransparent"_ustr));
729         CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_NONE, getProperty<drawing::FillStyle>(xStyle32, u"FillStyle"_ustr));
730     // unfortunately this is actually the pool default value, which would be hard to fix - but it isn't a problem because style is NONE
731     //    CPPUNIT_ASSERT_EQUAL(sal_Int32(0xffffff), getProperty<sal_Int32>(xStyle32, "FillColor"));
732     //    CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xStyle32, "FillTransparence"));
733         CPPUNIT_ASSERT_EQUAL(Color(0x461900), getProperty<Color>(xStyle32, u"CharColor"_ustr));
734     };
735 
736     createSwDoc("tdf92379.fodt");
737     verify();
738     saveAndReload(mpFilter);
739     verify();
740 
741     xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
742     // check that fo:background-color attribute is exported properly
743     assertXPath(pXmlDoc, "//style:style[@style:family='graphic' and @style:name='encarts']/style:graphic-properties[@fo:background-color='#ffcc99']", 1);
744     assertXPath(pXmlDoc, "//style:style[@style:family='graphic' and @style:name='Untitled1']/style:graphic-properties[@fo:background-color='transparent']", 1);
745 
746     // check that fo:background-color attribute is exported properly
747     assertXPath(pXmlDoc, "//style:style[@style:family='paragraph' and @style:display-name='Titre Avis expert']/style:paragraph-properties[@fo:background-color='#661900']", 1);
748     assertXPath(pXmlDoc, "//style:style[@style:family='paragraph' and @style:display-name='Avis expert questions']/style:paragraph-properties[@fo:background-color='transparent']", 1);
749     assertXPath(pXmlDoc, "//style:style[@style:family='paragraph' and @style:display-name='avis expert questions non cadres']/style:paragraph-properties[@fo:background-color='#801900']", 1);
750     assertXPath(pXmlDoc, "//style:style[@style:family='paragraph' and @style:display-name='Avis expert rXponses']/style:paragraph-properties[@fo:background-color='transparent']", 1);
751 }
752 
753 DECLARE_ODFEXPORT_TEST(testFdo79358, "fdo79358.odt")
754 {
755     CPPUNIT_ASSERT_EQUAL(1, getPages());
756     // the boolean properties of the index were not exported properly
757     uno::Reference<text::XDocumentIndexesSupplier> xIndexSupplier(mxComponent, uno::UNO_QUERY);
758     uno::Reference<container::XIndexAccess> xIndexes = xIndexSupplier->getDocumentIndexes();
759     uno::Reference<text::XDocumentIndex> xTOCIndex(xIndexes->getByIndex(0), uno::UNO_QUERY);
760     uno::Reference<beans::XPropertySet> xTOCProps(xTOCIndex, uno::UNO_QUERY);
761     CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xTOCProps, u"CreateFromOutline"_ustr));
762     CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xTOCProps, u"CreateFromMarks"_ustr));
763     CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xTOCProps, u"CreateFromLevelParagraphStyles"_ustr));
764     // check that the source styles are preserved too while at it
765     uno::Reference<container::XIndexReplace> xLevels(
766         getProperty< uno::Reference<container::XIndexReplace> >(xTOCProps,
767             u"LevelParagraphStyles"_ustr));
768     uno::Sequence<OUString> seq { u"Heading"_ustr };
769     CPPUNIT_ASSERT_EQUAL(uno::Any(seq), xLevels->getByIndex(1));
770     CPPUNIT_ASSERT_EQUAL(uno::Any(uno::Sequence<OUString>()), xLevels->getByIndex(2));
771 }
772 
773 DECLARE_ODFEXPORT_TEST(testTextframeGradient, "textframe-gradient.odt")
774 {
775     CPPUNIT_ASSERT_EQUAL(2, getShapes());
776     CPPUNIT_ASSERT_EQUAL(1, getPages());
777     uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY);
778     uno::Reference<container::XIndexAccess> xIndexAccess(xTextFramesSupplier->getTextFrames(), uno::UNO_QUERY);
779     CPPUNIT_ASSERT_EQUAL(sal_Int32(2), xIndexAccess->getCount());
780 
781     uno::Reference<beans::XPropertySet> xFrame(xIndexAccess->getByIndex(0), uno::UNO_QUERY);
782     CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xFrame, u"FillStyle"_ustr));
783     awt::Gradient2 aGradient = getProperty<awt::Gradient2>(xFrame, u"FillGradient"_ustr);
784 
785     // MCGR: Use the completely imported gradient to check for correctness
786     basegfx::BColorStops aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops);
787 
788     CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size());
789     CPPUNIT_ASSERT_EQUAL(0.0, aColorStops[0].getStopOffset());
790     CPPUNIT_ASSERT_EQUAL(Color(0xc0504d), Color(aColorStops[0].getStopColor()));
791     CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0));
792     CPPUNIT_ASSERT_EQUAL(Color(0xd99594), Color(aColorStops[1].getStopColor()));
793     CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_AXIAL, aGradient.Style);
794 
795     xFrame.set(xIndexAccess->getByIndex(1), uno::UNO_QUERY);
796     CPPUNIT_ASSERT_EQUAL(drawing::FillStyle_GRADIENT, getProperty<drawing::FillStyle>(xFrame, u"FillStyle"_ustr));
797     aGradient = getProperty<awt::Gradient2>(xFrame, u"FillGradient"_ustr);
798 
799     // MCGR: Use the completely imported gradient to check for correctness
800     aColorStops = model::gradient::getColorStopsFromUno(aGradient.ColorStops);
801 
802     CPPUNIT_ASSERT_EQUAL(size_t(2), aColorStops.size());
803     CPPUNIT_ASSERT_EQUAL(0.0, aColorStops[0].getStopOffset());
804     CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(aColorStops[0].getStopColor()));
805     CPPUNIT_ASSERT(basegfx::fTools::equal(aColorStops[1].getStopOffset(), 1.0));
806     CPPUNIT_ASSERT_EQUAL(COL_GRAY7, Color(aColorStops[1].getStopColor()));
807     CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_AXIAL, aGradient.Style);
808 }
809 
CPPUNIT_TEST_FIXTURE(Test,testDuplicateCrossRefHeadingBookmark)810 CPPUNIT_TEST_FIXTURE(Test, testDuplicateCrossRefHeadingBookmark)
811 {
812     loadAndReload("CrossRefHeadingBookmark.fodt");
813     // the file contains invalid duplicate heading cross reference bookmarks
814     // but we have to round trip them, tdf#94804
815 
816     uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent,
817         uno::UNO_QUERY);
818     uno::Reference<container::XNameAccess> xBookmarks =
819         xBookmarksSupplier->getBookmarks();
820     uno::Reference<text::XTextContent> xBookmark1(
821         xBookmarks->getByName(u"__RefHeading__8284_1826734303"_ustr), uno::UNO_QUERY);
822     CPPUNIT_ASSERT(xBookmark1.is());
823     CPPUNIT_ASSERT_THROW(xBookmarks->getByName(u"__RefHeading__1673_25705824"_ustr), container::NoSuchElementException);
824 
825     uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
826     uno::Reference<util::XRefreshable>(xTextFieldsSupplier->getTextFields(), uno::UNO_QUERY_THROW)->refresh();
827 
828     uno::Reference<container::XEnumerationAccess> xFieldsAccess(xTextFieldsSupplier->getTextFields());
829     uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
830     uno::Any aField1 = xFields->nextElement();
831     uno::Reference<text::XTextField> xField1(aField1, uno::UNO_QUERY);
832     CPPUNIT_ASSERT_EQUAL(u"1.1"_ustr, xField1->getPresentation(false));
833     uno::Any aField2 = xFields->nextElement();
834     uno::Reference<text::XTextField> xField2(aField2, uno::UNO_QUERY);
835     CPPUNIT_ASSERT_EQUAL(u"1.1"_ustr, xField2->getPresentation(false));
836 }
837 
838 DECLARE_ODFEXPORT_TEST(testFdo60769, "fdo60769.odt")
839 {
840     CPPUNIT_ASSERT_EQUAL(1, getPages());
841     // Test multi-paragraph comment range feature.
842     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
843     uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
844     uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
845     uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
846     uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
847     while (xRunEnum->hasMoreElements())
848     {
849         uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
850         OUString aType =  getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr);
851         // First paragraph: no field end, no anchor
852         CPPUNIT_ASSERT(aType == "Text" || aType == "Annotation");
853     }
854 
855     xRunEnumAccess.set(xParaEnum->nextElement(), uno::UNO_QUERY);
856     while (xRunEnum->hasMoreElements())
857     {
858         uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
859         OUString aType =  getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr);
860         // Second paragraph: no field start
861         CPPUNIT_ASSERT(aType == "Text" || aType == "AnnotationEnd");
862     }
863 }
864 
865 DECLARE_ODFEXPORT_TEST(testTdf115815, "tdf115815.odt")
866 {
867     CPPUNIT_ASSERT_EQUAL(1, getPages());
868     // Test comment range feature on tracked deletion.
869     uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
870     uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY);
871     uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
872     uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
873     uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
874     bool bAnnotationStart = false;
875     bool bBeforeAnnotation = true;
876     OUString sTextBeforeAnnotation;
877     while (xRunEnum->hasMoreElements())
878     {
879         uno::Reference<beans::XPropertySet> xPropertySet(xRunEnum->nextElement(), uno::UNO_QUERY);
880         OUString aType = getProperty<OUString>(xPropertySet, u"TextPortionType"_ustr);
881         // there is no AnnotationEnd with preceding AnnotationStart,
882         // i.e. annotation with lost range
883         CPPUNIT_ASSERT(aType != "AnnotationEnd" || !bAnnotationStart);
884 
885         bAnnotationStart = (aType == "Annotation");
886 
887         // collect paragraph text before the first annotation
888         if (bBeforeAnnotation)
889         {
890             if (bAnnotationStart)
891                 bBeforeAnnotation = false;
892             else if (aType == "Text")
893             {
894                 uno::Reference<text::XTextRange> xRun(xPropertySet, uno::UNO_QUERY);
895                 sTextBeforeAnnotation += xRun->getString();
896             }
897         }
898     }
899 
900     // This was "Lorem ipsum" (collapsed annotation range)
901     CPPUNIT_ASSERT_EQUAL(u"Lorem "_ustr, sTextBeforeAnnotation);
902 }
903 
CPPUNIT_TEST_FIXTURE(Test,testFdo58949)904 CPPUNIT_TEST_FIXTURE(Test, testFdo58949)
905 {
906     comphelper::ScopeGuard g([]() {
907         std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
908             comphelper::ConfigurationChanges::create());
909         officecfg::Office::Common::Filter::Microsoft::Import::MathTypeToMath::set(true, pBatch);
910         pBatch->commit();
911     });
912 
913     std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
914         comphelper::ConfigurationChanges::create());
915     officecfg::Office::Common::Filter::Microsoft::Import::MathTypeToMath::set(false, pBatch);
916     pBatch->commit();
917     loadAndReload("fdo58949.docx");
918 
919     /*
920      * The problem was that the exporter didn't insert "Obj102" to the
921      * resulting zip file. No idea how to check for "broken" (missing OLE data
922      * and replacement image) OLE objects using UNO, so we'll check the zip file directly.
923      */
924 
925     save(u"writer8"_ustr);
926 
927     uno::Sequence<uno::Any> aArgs{ uno::Any(maTempFile.GetURL()) };
928     uno::Reference<container::XNameAccess> xNameAccess(m_xSFactory->createInstanceWithArguments(u"com.sun.star.packages.zip.ZipFileAccess"_ustr, aArgs), uno::UNO_QUERY);
929     const css::uno::Sequence<OUString> aNames(xNameAccess->getElementNames());
930     // The exported document must have three objects named ObjNNN. The names are assigned in
931     // OLEHandler::copyOLEOStream using a static counter, and actual numbers depend on previous
932     // tests; so just count the matching names here.
933     int nMatches = 0;
934     for (const OUString& sName : aNames)
935     {
936         OUString sRest;
937         if (sName.startsWith("Obj", &sRest))
938         {
939             // all following characters must be decimal digits; minimal value is 100
940             bool bMatch = sRest.getLength() >= 3
941                           && std::all_of(sRest.getStr(), sRest.getStr() + sRest.getLength(),
942                                  [](sal_Unicode ch) { return ch >= '0' && ch <= '9'; });
943             if (bMatch)
944                 ++nMatches;
945         }
946     }
947     CPPUNIT_ASSERT_EQUAL(3, nMatches);
948 }
949 
CPPUNIT_TEST_FIXTURE(Test,testTdf134987)950 CPPUNIT_TEST_FIXTURE(Test, testTdf134987)
951 {
952     loadAndReload("tdf134987.docx");
953     uno::Reference<text::XTextEmbeddedObjectsSupplier> xTEOSupplier(mxComponent, uno::UNO_QUERY);
954     uno::Reference<container::XNameAccess> xAccess(xTEOSupplier->getEmbeddedObjects());
955     uno::Sequence<OUString> aSeq(xAccess->getElementNames());
956     CPPUNIT_ASSERT_EQUAL(sal_Int32(3), aSeq.getLength());
957 
958     OUString aMediaType;
959     // checking first object (formula)
960     {
961         uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier(xAccess->getByName(u"Object1"_ustr), uno::UNO_QUERY);
962         uno::Reference<lang::XComponent> xObj(xEOSupplier->getEmbeddedObject());
963         CPPUNIT_ASSERT(xObj.is());
964 
965         uno::Reference<document::XStorageBasedDocument> xSBDoc(xObj, uno::UNO_QUERY);
966         uno::Reference<embed::XStorage> xStorage(xSBDoc->getDocumentStorage());
967         CPPUNIT_ASSERT(xStorage.is());
968 
969         uno::Reference< beans::XPropertySet > xStorProps(xStorage, uno::UNO_QUERY_THROW);
970         CPPUNIT_ASSERT(xStorProps->getPropertyValue(u"MediaType"_ustr) >>= aMediaType);
971         CPPUNIT_ASSERT(aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII));
972     }
973     // checking second object (chart)
974     {
975         uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier(xAccess->getByName(u"Diagram 1"_ustr), uno::UNO_QUERY);
976         uno::Reference<lang::XComponent> xObj(xEOSupplier->getEmbeddedObject());
977         CPPUNIT_ASSERT(xObj.is());
978 
979         uno::Reference<document::XStorageBasedDocument> xSBDoc(xObj, uno::UNO_QUERY);
980         uno::Reference<embed::XStorage> xStorage(xSBDoc->getDocumentStorage());
981         CPPUNIT_ASSERT(xStorage.is());
982 
983         uno::Reference< beans::XPropertySet > xStorProps(xStorage, uno::UNO_QUERY_THROW);
984         CPPUNIT_ASSERT(xStorProps->getPropertyValue(u"MediaType"_ustr) >>= aMediaType);
985         CPPUNIT_ASSERT(aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII));
986     }
987     // checking third object (chart)
988     {
989         uno::Reference<document::XEmbeddedObjectSupplier> xEOSupplier(xAccess->getByName(u"Diagram 2"_ustr), uno::UNO_QUERY);
990         uno::Reference<lang::XComponent> xObj(xEOSupplier->getEmbeddedObject());
991         CPPUNIT_ASSERT(xObj.is());
992 
993         uno::Reference<document::XStorageBasedDocument> xSBDoc(xObj, uno::UNO_QUERY);
994         uno::Reference<embed::XStorage> xStorage(xSBDoc->getDocumentStorage());
995         CPPUNIT_ASSERT(xStorage.is());
996 
997         uno::Reference< beans::XPropertySet > xStorProps(xStorage, uno::UNO_QUERY_THROW);
998         CPPUNIT_ASSERT(xStorProps->getPropertyValue(u"MediaType"_ustr) >>= aMediaType);
999         CPPUNIT_ASSERT(aMediaType.equalsIgnoreAsciiCase(MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII));
1000     }
1001 }
1002 
1003 DECLARE_ODFEXPORT_TEST(testStylePageNumber, "ooo321_stylepagenumber.odt")
1004 {
1005     CPPUNIT_ASSERT_EQUAL(5, getPages());
1006     uno::Reference<text::XTextContent> xTable1(getParagraphOrTable(1));
1007 // actually no break attribute is written in this case
1008 //    CPPUNIT_ASSERT_EQUAL(style::BreakType_PAGE_BEFORE, getProperty<style::BreakType>(xTable1, "BreakType"));
1009     CPPUNIT_ASSERT_EQUAL(u"Left Page"_ustr, getProperty<OUString>(xTable1, u"PageDescName"_ustr));
1010     CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xTable1, u"PageNumberOffset"_ustr));
1011 
1012     uno::Reference<text::XTextContent> xPara1(getParagraphOrTable(2));
1013     CPPUNIT_ASSERT_EQUAL(u"Right Page"_ustr, getProperty<OUString>(xPara1, u"PageDescName"_ustr));
1014     CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xPara1, u"PageNumberOffset"_ustr));
1015 
1016     // i#114163 tdf#77111: OOo < 3.3 bug, it wrote "auto" as "0" for tables
1017     uno::Reference<beans::XPropertySet> xTable0(getParagraphOrTable(3), uno::UNO_QUERY);
1018     CPPUNIT_ASSERT_EQUAL(u"Left Page"_ustr, getProperty<OUString>(xTable0, u"PageDescName"_ustr));
1019     CPPUNIT_ASSERT_EQUAL(uno::Any(), xTable0->getPropertyValue(u"PageNumberOffset"_ustr));
1020 
1021     uno::Reference<beans::XPropertySet> xPara0(getParagraphOrTable(4), uno::UNO_QUERY);
1022     CPPUNIT_ASSERT_EQUAL(u"Right Page"_ustr, getProperty<OUString>(xPara0, u"PageDescName"_ustr));
1023     CPPUNIT_ASSERT_EQUAL(uno::Any(), xPara0->getPropertyValue(u"PageNumberOffset"_ustr));
1024 
1025     uno::Reference<container::XNameAccess> xParaStyles = getStyles(u"ParagraphStyles"_ustr);
1026     uno::Reference<beans::XPropertySet> xStyle1(xParaStyles->getByName(u"stylewithbreak1"_ustr), uno::UNO_QUERY);
1027     CPPUNIT_ASSERT_EQUAL(u"Right Page"_ustr, getProperty<OUString>(xStyle1, u"PageDescName"_ustr));
1028     CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xStyle1, u"PageNumberOffset"_ustr));
1029 
1030     uno::Reference<beans::XPropertySet> xStyle0(xParaStyles->getByName(u"stylewithbreak0"_ustr), uno::UNO_QUERY);
1031     CPPUNIT_ASSERT_EQUAL(u"First Page"_ustr, getProperty<OUString>(xStyle0, u"PageDescName"_ustr));
1032     CPPUNIT_ASSERT_EQUAL(uno::Any(), xStyle0->getPropertyValue(u"PageNumberOffset"_ustr));
1033 }
1034 
1035 DECLARE_ODFEXPORT_TEST(testCharacterBorder, "charborder.odt")
1036 {
1037     CPPUNIT_ASSERT_EQUAL(1, getPages());
1038     // Make sure paragraph and character attributes don't interfere
1039     // First paragraph has a paragraph border and a character border included by the paragraph style
1040 
1041     // Paragraph border of first paragraph
1042     {
1043         const table::BorderLine2 aFirstParTopBorder(0x6666FF,2,26,26,7,55);
1044         const sal_Int32 aFirstParTopPadding(150);
1045         uno::Reference<beans::XPropertySet> xSet(getParagraph(1), uno::UNO_QUERY);
1046 
1047         // Top border
1048         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParTopBorder, getProperty<table::BorderLine2>(xSet,u"TopBorder"_ustr));
1049         CPPUNIT_ASSERT_EQUAL(aFirstParTopPadding, getProperty<sal_Int32>(xSet,u"TopBorderDistance"_ustr));
1050 
1051         // Bottom border (same as top border)
1052         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParTopBorder, getProperty<table::BorderLine2>(xSet,u"BottomBorder"_ustr));
1053         CPPUNIT_ASSERT_EQUAL(aFirstParTopPadding, getProperty<sal_Int32>(xSet,u"BottomBorderDistance"_ustr));
1054 
1055         // Left border (same as top border)
1056         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParTopBorder, getProperty<table::BorderLine2>(xSet,u"LeftBorder"_ustr));
1057         CPPUNIT_ASSERT_EQUAL(aFirstParTopPadding, getProperty<sal_Int32>(xSet,u"LeftBorderDistance"_ustr));
1058 
1059         // Right border (same as top border)
1060         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParTopBorder, getProperty<table::BorderLine2>(xSet,u"RightBorder"_ustr));
1061         CPPUNIT_ASSERT_EQUAL(aFirstParTopPadding, getProperty<sal_Int32>(xSet,u"RightBorderDistance"_ustr));
1062 
1063         // Shadow
1064         const table::ShadowFormat aShadow = getProperty<table::ShadowFormat>(xSet,u"ParaShadowFormat"_ustr);
1065         CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(ColorTransparency, aShadow.Color));
1066         CPPUNIT_ASSERT_EQUAL(false, static_cast<bool>(aShadow.IsTransparent));
1067         CPPUNIT_ASSERT_EQUAL(table::ShadowLocation(0), aShadow.Location);
1068         CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aShadow.ShadowWidth);
1069     }
1070 
1071     // Character border for first paragraph
1072     {
1073         const table::BorderLine2 aFirstParCharTopBorder(0xFF3333,0,37,0,2,37);
1074         const sal_Int32 aFirstParCharTopPadding(450);
1075         uno::Reference<beans::XPropertySet> xSet(getParagraph(1), uno::UNO_QUERY);
1076 
1077         // Top border
1078         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharTopBorder"_ustr));
1079         CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharTopBorderDistance"_ustr));
1080 
1081         // Bottom border (same as top border)
1082         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharBottomBorder"_ustr));
1083         CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharBottomBorderDistance"_ustr));
1084 
1085         // Left border (same as top border)
1086         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharLeftBorder"_ustr));
1087         CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharLeftBorderDistance"_ustr));
1088 
1089         // Right border (same as top border)
1090         CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharRightBorder"_ustr));
1091         CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharRightBorderDistance"_ustr));
1092 
1093         // Shadow
1094         const table::ShadowFormat aShadow = getProperty<table::ShadowFormat>(xSet,u"CharShadowFormat"_ustr);
1095         CPPUNIT_ASSERT_EQUAL(Color(0xFF3333), Color(ColorTransparency, aShadow.Color));
1096         CPPUNIT_ASSERT_EQUAL(false, static_cast<bool>(aShadow.IsTransparent));
1097         CPPUNIT_ASSERT_EQUAL(table::ShadowLocation(2), aShadow.Location);
1098         CPPUNIT_ASSERT_EQUAL(sal_Int16(280), aShadow.ShadowWidth);
1099 
1100         // Check autostyle
1101         {
1102             uno::Reference< style::XAutoStyleFamily > xAutoStyleFamily(getAutoStyles(u"ParagraphStyles"_ustr));
1103             uno::Reference < container::XEnumeration > xAutoStylesEnum( xAutoStyleFamily->createEnumeration() );
1104             CPPUNIT_ASSERT_EQUAL(true, static_cast<bool>(xAutoStylesEnum->hasMoreElements()));
1105 
1106             // Top border
1107             CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharTopBorder"_ustr));
1108             CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharTopBorderDistance"_ustr));
1109 
1110             // Bottom border
1111             CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharBottomBorder"_ustr));
1112             CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharBottomBorderDistance"_ustr));
1113 
1114             // Left border
1115             CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharLeftBorder"_ustr));
1116             CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharLeftBorderDistance"_ustr));
1117 
1118             // Right border
1119             CPPUNIT_ASSERT_BORDER_EQUAL(aFirstParCharTopBorder, getProperty<table::BorderLine2>(xSet,u"CharRightBorder"_ustr));
1120             CPPUNIT_ASSERT_EQUAL(aFirstParCharTopPadding, getProperty<sal_Int32>(xSet,u"CharRightBorderDistance"_ustr));
1121         }
1122     }
1123 
1124     // Second paragraph's second text portion has a character style named CharDiffBor
1125     // This style includes border with different sides
1126     {
1127 
1128         table::BorderLine2 aBorderArray[4] =
1129         {
1130             table::BorderLine2(0xFF3333,0,37,0,14,37),     // Top (fine dashed line)
1131             table::BorderLine2(0x99FF66,26,26,53,11,106),  // Bottom
1132             table::BorderLine2(0x6666FF,9,26,9,12,71),     // Left
1133             table::BorderLine2(0,0,0,0,table::BorderLineStyle::NONE,0) // Right
1134         };
1135 
1136         sal_Int32 aDistances[4] = { 400 /*Top*/, 300 /*Bottom*/, 250 /*Left*/, 0 /*Right*/ };
1137 
1138         // Get second text portion of second paragraph
1139         uno::Reference < beans::XPropertySet > xSet( getRun(getParagraph(2),2), uno::UNO_QUERY );
1140 
1141         // Top border
1142         CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[0], getProperty<table::BorderLine2>(xSet,u"CharTopBorder"_ustr));
1143         CPPUNIT_ASSERT_EQUAL(aDistances[0], getProperty<sal_Int32>(xSet,u"CharTopBorderDistance"_ustr));
1144 
1145         // Bottom border
1146         CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[1], getProperty<table::BorderLine2>(xSet,u"CharBottomBorder"_ustr));
1147         CPPUNIT_ASSERT_EQUAL(aDistances[1], getProperty<sal_Int32>(xSet,u"CharBottomBorderDistance"_ustr));
1148 
1149         // Left border
1150         CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[2], getProperty<table::BorderLine2>(xSet,u"CharLeftBorder"_ustr));
1151         CPPUNIT_ASSERT_EQUAL(aDistances[2], getProperty<sal_Int32>(xSet,u"CharLeftBorderDistance"_ustr));
1152 
1153         // Right border
1154         CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[3], getProperty<table::BorderLine2>(xSet,u"CharRightBorder"_ustr));
1155         CPPUNIT_ASSERT_EQUAL(aDistances[3], getProperty<sal_Int32>(xSet,u"CharRightBorderDistance"_ustr));
1156 
1157         // Shadow
1158         const table::ShadowFormat aShadow = getProperty<table::ShadowFormat>(xSet,u"CharShadowFormat"_ustr);
1159         CPPUNIT_ASSERT_EQUAL(COL_BLACK, Color(ColorTransparency, aShadow.Color));
1160         CPPUNIT_ASSERT_EQUAL(false, static_cast<bool>(aShadow.IsTransparent));
1161         CPPUNIT_ASSERT_EQUAL(table::ShadowLocation(3), aShadow.Location);
1162         CPPUNIT_ASSERT_EQUAL(sal_Int16(79), aShadow.ShadowWidth);
1163 
1164         // Check character style
1165         {
1166             uno::Reference< container::XNameAccess > xStyleFamily = getStyles(u"CharacterStyles"_ustr);
1167             uno::Reference < beans::XPropertySet > xStyleSet(xStyleFamily->getByName(u"CharDiffBor"_ustr), uno::UNO_QUERY);
1168 
1169             // Top border
1170             CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[0], getProperty<table::BorderLine2>(xStyleSet,u"CharTopBorder"_ustr));
1171             CPPUNIT_ASSERT_EQUAL(aDistances[0], getProperty<sal_Int32>(xStyleSet,u"CharTopBorderDistance"_ustr));
1172 
1173             // Bottom border
1174             CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[1], getProperty<table::BorderLine2>(xStyleSet,u"CharBottomBorder"_ustr));
1175             CPPUNIT_ASSERT_EQUAL(aDistances[1], getProperty<sal_Int32>(xStyleSet,u"CharBottomBorderDistance"_ustr));
1176 
1177             // Left border
1178             CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[2], getProperty<table::BorderLine2>(xStyleSet,u"CharLeftBorder"_ustr));
1179             CPPUNIT_ASSERT_EQUAL(aDistances[2], getProperty<sal_Int32>(xStyleSet,u"CharLeftBorderDistance"_ustr));
1180 
1181             // Right border
1182             CPPUNIT_ASSERT_BORDER_EQUAL(aBorderArray[3], getProperty<table::BorderLine2>(xStyleSet,u"CharRightBorder"_ustr));
1183             CPPUNIT_ASSERT_EQUAL(aDistances[3], getProperty<sal_Int32>(xStyleSet,u"CharRightBorderDistance"_ustr));
1184         }
1185     }
1186 }
1187 
CPPUNIT_TEST_FIXTURE(Test,testProtectionKey)1188 CPPUNIT_TEST_FIXTURE(Test, testProtectionKey)
1189 {
1190     auto verify = [this]() {
1191         static OUString constexpr password(u"1012345678901234567890123456789012345678901234567890"_ustr);
1192 
1193         // check 1 invalid OOo legacy password and 3 valid ODF 1.2 passwords
1194         uno::Reference<text::XTextSectionsSupplier> xTextSectionsSupplier(mxComponent, uno::UNO_QUERY);
1195         uno::Reference<container::XIndexAccess> xSections(xTextSectionsSupplier->getTextSections(), uno::UNO_QUERY);
1196         uno::Reference<beans::XPropertySet> xSect0(xSections->getByIndex(0), uno::UNO_QUERY);
1197         uno::Sequence<sal_Int8> const key0(getProperty<uno::Sequence<sal_Int8>>(xSect0, u"ProtectionKey"_ustr));
1198         CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key0, password));
1199         uno::Reference<beans::XPropertySet> xSect1(xSections->getByIndex(1), uno::UNO_QUERY);
1200         uno::Sequence<sal_Int8> const key1(getProperty<uno::Sequence<sal_Int8>>(xSect1, u"ProtectionKey"_ustr));
1201         CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key1, password));
1202         uno::Reference<beans::XPropertySet> xSect2(xSections->getByIndex(2), uno::UNO_QUERY);
1203         uno::Sequence<sal_Int8> const key2(getProperty<uno::Sequence<sal_Int8>>(xSect2, u"ProtectionKey"_ustr));
1204         CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key2, password));
1205         uno::Reference<beans::XPropertySet> xSect3(xSections->getByIndex(3), uno::UNO_QUERY);
1206         uno::Sequence<sal_Int8> const key3(getProperty<uno::Sequence<sal_Int8>>(xSect3, u"ProtectionKey"_ustr));
1207         CPPUNIT_ASSERT(SvPasswordHelper::CompareHashPassword(key3, password));
1208     };
1209 
1210     createSwDoc("protection-key.fodt");
1211     verify();
1212     saveAndReload(mpFilter);
1213     verify();
1214 
1215     // we can't assume that the user entered the password; check that we
1216     // round-trip the password as-is
1217     xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr);
1218     assertXPath(pXmlDoc, "//text:section[@text:name='Section0' and @text:protected='true' and @text:protection-key='vbnhxyBKtPHCA1wB21zG1Oha8ZA=']");
1219     assertXPath(pXmlDoc, "//text:section[@text:name='Section1' and @text:protected='true' and @text:protection-key='nLHas0RIwepGDaH4c2hpyIUvIS8=']");
1220     assertXPath(pXmlDoc, "//text:section[@text:name='Section2' and @text:protected='true' and @text:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256' and @text:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=']");
1221     assertXPath(pXmlDoc, "//text:section[@text:name='Section3' and @text:protected='true' and @text:protection-key-digest-algorithm='http://www.w3.org/2000/09/xmldsig#sha256' and @text:protection-key='1tnJohagR2T0yF/v69hLPuumSTsj32CumW97nkKGuSQ=']");
1222 }
1223 
CPPUNIT_TEST_FIXTURE(Test,testTdf128188)1224 CPPUNIT_TEST_FIXTURE(Test, testTdf128188)
1225 {
1226     loadAndReload("footnote-collect-at-end-of-section.fodt");
1227     SwDoc* pDoc = getSwDoc();
1228     SwFootnoteIdxs const& rFootnotes(pDoc->GetFootnoteIdxs());
1229     // Section1
1230     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnotes[0]->GetFootnote().GetNumber());
1231     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnotes[0]->GetFootnote().GetNumberRLHidden());
1232     CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), rFootnotes[1]->GetFootnote().GetNumber());
1233     CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), rFootnotes[1]->GetFootnote().GetNumberRLHidden());
1234     // Section2
1235     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnotes[2]->GetFootnote().GetNumber());
1236     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnotes[2]->GetFootnote().GetNumberRLHidden());
1237     // deleted
1238     CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), rFootnotes[3]->GetFootnote().GetNumber());
1239     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnotes[3]->GetFootnote().GetNumberRLHidden());
1240     // deleted
1241     CPPUNIT_ASSERT_EQUAL(sal_uInt16(3), rFootnotes[4]->GetFootnote().GetNumber());
1242     CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), rFootnotes[4]->GetFootnote().GetNumberRLHidden());
1243     CPPUNIT_ASSERT_EQUAL(sal_uInt16(4), rFootnotes[5]->GetFootnote().GetNumber());
1244     CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), rFootnotes[5]->GetFootnote().GetNumberRLHidden());
1245 }
1246 
1247 DECLARE_ODFEXPORT_TEST(testFdo43807, "fdo43807.odt")
1248 {
1249     CPPUNIT_ASSERT_EQUAL(1, getPages());
1250     uno::Reference<beans::XPropertySet> xSet(getParagraph(1), uno::UNO_QUERY);
1251     CPPUNIT_ASSERT_EQUAL(u"Drop Caps"_ustr,getProperty<OUString>(xSet,u"DropCapCharStyleName"_ustr));
1252 
1253     xSet.set(getParagraph(2), uno::UNO_QUERY);
1254     CPPUNIT_ASSERT_EQUAL(u"User Defined Drop Caps"_ustr,getProperty<OUString>(xSet,u"DropCapCharStyleName"_ustr));
1255 }
1256 
CPPUNIT_TEST_FIXTURE(Test,testTdf103091)1257 CPPUNIT_TEST_FIXTURE(Test, testTdf103091)
1258 {
1259     loadAndReload("tdf103091.fodt");
1260     // check that all conditional paragraph style conditions are imported
1261     uno::Reference<container::XNameAccess> xParaStyles(getStyles(u"ParagraphStyles"_ustr));
1262     uno::Reference<beans::XPropertySet> xStyle1(xParaStyles->getByName(
1263             u"Text body"_ustr), uno::UNO_QUERY);
1264     auto conditions(getProperty<uno::Sequence<beans::NamedValue>>(xStyle1, u"ParaStyleConditions"_ustr));
1265 
1266     CPPUNIT_ASSERT_EQUAL(sal_Int32(28), conditions.getLength());
1267     CPPUNIT_ASSERT_EQUAL(u"TableHeader"_ustr, conditions[0].Name);
1268     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Addressee"_ustr), conditions[0].Value);
1269     CPPUNIT_ASSERT_EQUAL(u"Table"_ustr, conditions[1].Name);
1270     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Bibliography 1"_ustr), conditions[1].Value);
1271     CPPUNIT_ASSERT_EQUAL(u"Frame"_ustr, conditions[2].Name);
1272     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Bibliography Heading"_ustr), conditions[2].Value);
1273     CPPUNIT_ASSERT_EQUAL(u"Section"_ustr, conditions[3].Name);
1274     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Caption"_ustr), conditions[3].Value);
1275     CPPUNIT_ASSERT_EQUAL(u"Footnote"_ustr, conditions[4].Name);
1276     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Salutation"_ustr), conditions[4].Value);
1277     CPPUNIT_ASSERT_EQUAL(u"Endnote"_ustr, conditions[5].Name);
1278     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 1"_ustr), conditions[5].Value);
1279     CPPUNIT_ASSERT_EQUAL(u"Header"_ustr, conditions[6].Name);
1280     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 2"_ustr), conditions[6].Value);
1281     CPPUNIT_ASSERT_EQUAL(u"Footer"_ustr, conditions[7].Name);
1282     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 3"_ustr), conditions[7].Value);
1283     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel1"_ustr, conditions[8].Name);
1284     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 4"_ustr), conditions[8].Value);
1285     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel2"_ustr, conditions[9].Name);
1286     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 5"_ustr), conditions[9].Value);
1287     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel3"_ustr, conditions[10].Name);
1288     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 6"_ustr), conditions[10].Value);
1289     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel4"_ustr, conditions[11].Name);
1290     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 7"_ustr), conditions[11].Value);
1291     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel5"_ustr, conditions[12].Name);
1292     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 8"_ustr), conditions[12].Value);
1293     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel6"_ustr, conditions[13].Name);
1294     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 9"_ustr), conditions[13].Value);
1295     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel7"_ustr, conditions[14].Name);
1296     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents 10"_ustr), conditions[14].Value);
1297     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel8"_ustr, conditions[15].Name);
1298     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Contents Heading"_ustr), conditions[15].Value);
1299     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel9"_ustr, conditions[16].Name);
1300     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Standard"_ustr), conditions[16].Value);
1301     CPPUNIT_ASSERT_EQUAL(u"OutlineLevel10"_ustr, conditions[17].Name);
1302     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Drawing"_ustr), conditions[17].Value);
1303     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel1"_ustr, conditions[18].Name);
1304     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Endnote"_ustr), conditions[18].Value);
1305     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel2"_ustr, conditions[19].Name);
1306     CPPUNIT_ASSERT_EQUAL(uno::Any(u"First line indent"_ustr), conditions[19].Value);
1307     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel3"_ustr, conditions[20].Name);
1308     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Footer"_ustr), conditions[20].Value);
1309     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel4"_ustr, conditions[21].Name);
1310     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Footer left"_ustr), conditions[21].Value);
1311     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel5"_ustr, conditions[22].Name);
1312     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Footer right"_ustr), conditions[22].Value);
1313     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel6"_ustr, conditions[23].Name);
1314     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Footnote"_ustr), conditions[23].Value);
1315     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel7"_ustr, conditions[24].Name);
1316     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Frame contents"_ustr), conditions[24].Value);
1317     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel8"_ustr, conditions[25].Name);
1318     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Hanging indent"_ustr), conditions[25].Value);
1319     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel9"_ustr, conditions[26].Name);
1320     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Header"_ustr), conditions[26].Value);
1321     CPPUNIT_ASSERT_EQUAL(u"NumberingLevel10"_ustr, conditions[27].Name);
1322     CPPUNIT_ASSERT_EQUAL(uno::Any(u"Header left"_ustr), conditions[27].Value);
1323 }
1324 
1325 DECLARE_ODFEXPORT_TEST(testTextframeTransparentShadow, "textframe-transparent-shadow.odt")
1326 {
1327     CPPUNIT_ASSERT_EQUAL(1, getShapes());
1328     CPPUNIT_ASSERT_EQUAL(1, getPages());
1329     uno::Reference<drawing::XShape> xPicture = getShape(1);
1330     // ODF stores opacity of 75%, that means 25% transparency.
1331     CPPUNIT_ASSERT_EQUAL(sal_Int32(25), getProperty<sal_Int32>(xPicture, u"ShadowTransparence"_ustr));
1332 }
1333 
1334 DECLARE_ODFEXPORT_TEST(testRelhPage, "relh-page.odt")
1335 {
1336     CPPUNIT_ASSERT_EQUAL(1, getShapes());
1337     CPPUNIT_ASSERT_EQUAL(1, getPages());
1338     uno::Reference<drawing::XShape> xTextFrame = getShape(1);
1339     // This was text::RelOrientation::FRAME (the default), RelativeHeightRelation was not handled in xmloff.
1340     CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME, getProperty<sal_Int16>(xTextFrame, u"RelativeHeightRelation"_ustr));
1341     // Make sure rel-height-rel doesn't affect width.
1342     CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME, getProperty<sal_Int16>(xTextFrame, u"RelativeWidthRelation"_ustr));
1343 
1344     // This was 2601, 20% height was relative from margin, not page.
1345     xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1346     CPPUNIT_ASSERT_EQUAL(sal_Int32(3168), getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "height").toInt32());
1347 }
1348 
1349 DECLARE_ODFEXPORT_TEST(testRelhPageTdf80282, "relh-page-tdf80282.odt")
1350 {
1351     CPPUNIT_ASSERT_EQUAL(1, getShapes());
1352     CPPUNIT_ASSERT_EQUAL(1, getPages());
1353     uno::Reference<drawing::XShape> xTextFrame = getShape(1);
1354     xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1355     assertXPath(pXmlDoc, "//anchored/fly/infos/bounds", "height", u"8391");
1356     assertXPath(pXmlDoc, "//anchored/fly/infos/bounds", "width", u"5953");
1357 }
1358 
1359 DECLARE_ODFEXPORT_TEST(testRelwPage, "relw-page.odt")
1360 {
1361     CPPUNIT_ASSERT_EQUAL(1, getShapes());
1362     CPPUNIT_ASSERT_EQUAL(1, getPages());
1363     uno::Reference<drawing::XShape> xTextFrame = getShape(1);
1364     // This was text::RelOrientation::FRAME (the default), RelativeWidthRelation was not handled in xmloff.
1365     CPPUNIT_ASSERT_EQUAL(text::RelOrientation::PAGE_FRAME, getProperty<sal_Int16>(xTextFrame, u"RelativeWidthRelation"_ustr));
1366     // Make sure rel-width-rel doesn't affect height.
1367     CPPUNIT_ASSERT_EQUAL(text::RelOrientation::FRAME, getProperty<sal_Int16>(xTextFrame, u"RelativeHeightRelation"_ustr));
1368 
1369     // This was 3762, 40% width was relative from margin, not page.
1370     xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1371     CPPUNIT_ASSERT_EQUAL(sal_Int32(4896), getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "width").toInt32());
1372 }
1373 
1374 DECLARE_ODFEXPORT_TEST(testTextFrameVertAdjust, "textframe-vertadjust.odt")
1375 {
1376     CPPUNIT_ASSERT_EQUAL(3, getShapes());
1377     CPPUNIT_ASSERT_EQUAL(1, getPages());
1378     // Test import/export of new frame attribute called TextVerticalAdjust
1379 
1380     // 1st frame's context is adjusted to the top
1381     uno::Reference<beans::XPropertySet> xFrame(getTextFrameByName(u"Rectangle 1"_ustr), uno::UNO_QUERY);
1382     CPPUNIT_ASSERT_EQUAL(drawing::TextVerticalAdjust_TOP, getProperty<drawing::TextVerticalAdjust>(xFrame, u"TextVerticalAdjust"_ustr));
1383     // 2nd frame's context is adjusted to the center
1384     xFrame.set(getTextFrameByName(u"Rectangle 2"_ustr), uno::UNO_QUERY);
1385     CPPUNIT_ASSERT_EQUAL(drawing::TextVerticalAdjust_CENTER, getProperty<drawing::TextVerticalAdjust>(xFrame, u"TextVerticalAdjust"_ustr));
1386     // 3rd frame's context is adjusted to the bottom
1387     xFrame.set(getTextFrameByName(u"Rectangle 3"_ustr), uno::UNO_QUERY);
1388     CPPUNIT_ASSERT_EQUAL(drawing::TextVerticalAdjust_BOTTOM, getProperty<drawing::TextVerticalAdjust>(xFrame, u"TextVerticalAdjust"_ustr));
1389 }
1390 
CPPUNIT_TEST_FIXTURE(Test,testTdf69500)1391 CPPUNIT_TEST_FIXTURE(Test, testTdf69500)
1392 {
1393     createSwDoc();
1394 
1395     static constexpr OUString sToolBarName = u"private:resource/toolbar/custom_toolbar_1"_ustr;
1396 
1397     auto getUIConfigManager = [this]() {
1398         css::uno::Reference<css::uno::XComponentContext> xContext
1399             = comphelper::getProcessComponentContext();
1400         uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
1401         CPPUNIT_ASSERT(xModel.is());
1402         uno::Reference<ui::XUIConfigurationManagerSupplier> xConfigSupplier(xModel, uno::UNO_QUERY);
1403         CPPUNIT_ASSERT(xConfigSupplier.is());
1404         uno::Reference<ui::XUIConfigurationManager> xConfigManager
1405             = xConfigSupplier->getUIConfigurationManager();
1406         return xConfigManager;
1407     };
1408 
1409     // Create and persist a custom toolbar to the document
1410     {
1411         uno::Reference<ui::XUIConfigurationManager> xConfigManager = getUIConfigManager();
1412 
1413         uno::Reference<container::XIndexContainer> xIndexContainer(xConfigManager->createSettings(),
1414                                                                    uno::UNO_SET_THROW);
1415         uno::Reference<container::XIndexAccess> xIndexAccess(xIndexContainer, uno::UNO_QUERY_THROW);
1416         uno::Reference<beans::XPropertySet> xProps(xIndexContainer, uno::UNO_QUERY_THROW);
1417 
1418         xProps->setPropertyValue(u"UIName"_ustr, uno::Any(u"Custom Toolbar 1"_ustr));
1419 
1420         xConfigManager->insertSettings(sToolBarName, xIndexAccess);
1421 
1422         uno::Reference<ui::XUIConfigurationPersistence> xPersistence(xConfigManager,
1423                                                                      uno::UNO_QUERY_THROW);
1424         xPersistence->store();
1425     }
1426 
1427     saveAndReload(mpFilter);
1428 
1429     // Without the fix, the toolbar will be gone after save-and-reload
1430     {
1431         uno::Reference<ui::XUIConfigurationManager> xConfigManager = getUIConfigManager();
1432 
1433         CPPUNIT_ASSERT(xConfigManager->hasSettings(sToolBarName));
1434     }
1435 }
1436 
CPPUNIT_TEST_FIXTURE(Test,testTdf60700_images)1437 CPPUNIT_TEST_FIXTURE(Test, testTdf60700_images)
1438 {
1439     createSwDoc();
1440 
1441     auto getUIConfigManager = [this]() {
1442         css::uno::Reference<css::uno::XComponentContext> xContext
1443             = comphelper::getProcessComponentContext();
1444         uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
1445         CPPUNIT_ASSERT(xModel.is());
1446         uno::Reference<ui::XUIConfigurationManagerSupplier> xConfigSupplier(xModel, uno::UNO_QUERY);
1447         CPPUNIT_ASSERT(xConfigSupplier.is());
1448         uno::Reference<ui::XUIConfigurationManager> xConfigManager
1449             = xConfigSupplier->getUIConfigurationManager();
1450         return xConfigManager;
1451     };
1452 
1453     static constexpr sal_Int16 imageType
1454         = css::ui::ImageType::COLOR_NORMAL | css::ui::ImageType::SIZE_DEFAULT;
1455 
1456     // Create and persist a custom icon to the document
1457     {
1458         Image aImage(m_directories.getURLFromSrc(u"/sw/qa/extras/odfexport/data/libreoffice.png"));
1459         CPPUNIT_ASSERT(!!aImage);
1460 
1461         uno::Reference<graphic::XGraphic> xGraphic = Graphic(aImage.GetBitmap()).GetXGraphic();
1462         CPPUNIT_ASSERT(xGraphic.is());
1463 
1464         uno::Sequence<OUString> aImportURL{ u".uno:OpenFromWriter"_ustr };
1465         uno::Sequence<uno::Reference<graphic::XGraphic>> aImportGraph{ xGraphic };
1466 
1467         css::uno::Reference<css::ui::XImageManager> xImgMgr(getUIConfigManager()->getImageManager(),
1468                                                             uno::UNO_QUERY);
1469 
1470         xImgMgr->insertImages(imageType, aImportURL, aImportGraph);
1471         xImgMgr->store();
1472     }
1473 
1474     saveAndReload(mpFilter);
1475 
1476     // Verify that the custom icon is still present after save-and-reload
1477     {
1478         uno::Reference<ui::XUIConfigurationManager> xConfigManager = getUIConfigManager();
1479         css::uno::Reference<css::ui::XImageManager> xImgMgr(xConfigManager->getImageManager(),
1480                                                             uno::UNO_QUERY);
1481 
1482         CPPUNIT_ASSERT(xImgMgr->hasImage(imageType, u".uno:OpenFromWriter"_ustr));
1483     }
1484 }
1485 
CPPUNIT_TEST_FIXTURE(Test,testTdf60700_accelerators)1486 CPPUNIT_TEST_FIXTURE(Test, testTdf60700_accelerators)
1487 {
1488     createSwDoc();
1489 
1490     auto getUIConfigManager = [this]() {
1491         css::uno::Reference<css::uno::XComponentContext> xContext
1492             = comphelper::getProcessComponentContext();
1493         uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
1494         CPPUNIT_ASSERT(xModel.is());
1495         uno::Reference<ui::XUIConfigurationManagerSupplier> xConfigSupplier(xModel, uno::UNO_QUERY);
1496         CPPUNIT_ASSERT(xConfigSupplier.is());
1497         uno::Reference<ui::XUIConfigurationManager> xConfigManager
1498             = xConfigSupplier->getUIConfigurationManager();
1499         return xConfigManager;
1500     };
1501 
1502     awt::KeyEvent aCtrlU;
1503     aCtrlU.KeyCode = css::awt::Key::U;
1504     aCtrlU.Modifiers = css::awt::KeyModifier::MOD1;
1505 
1506     static constexpr OUString sCommand = u".uno:OpenFromWriter"_ustr;
1507 
1508     // Create and persist a custom keyboard shortcut to the document
1509     {
1510         css::uno::Reference<css::ui::XAcceleratorConfiguration> xAccel
1511             = getUIConfigManager()->getShortCutManager();
1512 
1513         xAccel->setKeyEvent(aCtrlU, sCommand);
1514 
1515         xAccel->store();
1516     }
1517 
1518     saveAndReload(mpFilter);
1519 
1520     // Verify that the custom keyboard shortcut is still present after save-and-reload
1521     {
1522         uno::Reference<ui::XUIConfigurationManager> xConfigManager = getUIConfigManager();
1523         css::uno::Reference<css::ui::XAcceleratorConfiguration> xAccel
1524             = getUIConfigManager()->getShortCutManager();
1525 
1526         CPPUNIT_ASSERT_EQUAL(sCommand, xAccel->getCommandByKeyEvent(aCtrlU));
1527     }
1528 }
1529 
CPPUNIT_TEST_FIXTURE(Test,testTdf60700_directories)1530 CPPUNIT_TEST_FIXTURE(Test, testTdf60700_directories)
1531 {
1532     createSwDoc();
1533     save(mpFilter);
1534 
1535     // There is no way to read the contents of Configurations2/ from a loaded document,
1536     // because only UIConfigurationManager has a reference to it and there is no method
1537     // to access that reference from outside the class. So, we inspect the zipfile
1538     // directly.
1539 
1540     uno::Sequence<uno::Any> aArgs{ uno::Any(maTempFile.GetURL()) };
1541     uno::Reference<container::XNameAccess> xNameAccess(
1542         m_xSFactory->createInstanceWithArguments(u"com.sun.star.packages.zip.ZipFileAccess"_ustr,
1543                                                  aArgs),
1544         uno::UNO_QUERY);
1545     const css::uno::Sequence<OUString> aNames(xNameAccess->getElementNames());
1546 
1547     int nMatches = 0;
1548     for (const OUString& sName : aNames)
1549     {
1550         OUString sRest;
1551         if (sName.startsWith("Configurations2/", &sRest) && !sRest.isEmpty())
1552         {
1553             ++nMatches;
1554         }
1555     }
1556 
1557     // There should be zero elements within Configurations2/ on a fresh document.
1558     CPPUNIT_ASSERT_EQUAL(0, nMatches);
1559 }
1560 
1561 
1562 } // end of anonymous namespace
1563 CPPUNIT_PLUGIN_IMPLEMENT();
1564 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1565