Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / qa / extras / layout / layout2.cxx
blob9cbae8ae114a36f4232f725e1729f65c2cad9b74
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <swmodeltestbase.hxx>
12 #include <com/sun/star/text/XTextFrame.hpp>
13 #include <com/sun/star/text/XTextTable.hpp>
14 #include <com/sun/star/linguistic2/XHyphenator.hpp>
15 #include <com/sun/star/view/XSelectionSupplier.hpp>
17 #include <comphelper/scopeguard.hxx>
18 #include <comphelper/sequence.hxx>
19 #include <unotools/syslocaleoptions.hxx>
20 #include <editeng/unolingu.hxx>
21 #include <o3tl/string_view.hxx>
23 #include <unotxdoc.hxx>
24 #include <rootfrm.hxx>
25 #include <txtfrm.hxx>
26 #include <wrtsh.hxx>
27 #include <IDocumentLayoutAccess.hxx>
28 #include <IDocumentRedlineAccess.hxx>
29 #include <frameformats.hxx>
30 #include <unotextrange.hxx>
31 #include <fmtanchr.hxx>
33 /// Test to assert layout / rendering result of Writer.
34 class SwLayoutWriter2 : public SwModelTestBase
36 public:
37 SwLayoutWriter2()
38 : SwModelTestBase("/sw/qa/extras/layout/data/")
42 protected:
43 void CheckRedlineCharAttributesHidden();
46 // this mainly tests that splitting portions across redlines in SwAttrIter works
47 void SwLayoutWriter2::CheckRedlineCharAttributesHidden()
49 discardDumpedLayout();
50 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
51 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/merged", "paraPropsNodeIndex", "9");
52 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
53 "type", "PortionType::Para");
54 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
55 "portion", "foobaz");
56 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/merged", "paraPropsNodeIndex", "10");
57 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
58 "type", "PortionType::Para");
59 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
60 "portion", "foobaz");
61 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/merged", "paraPropsNodeIndex", "11");
62 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
63 "type", "PortionType::Text");
64 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
65 "portion", "foo");
66 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
67 "type", "PortionType::Text");
68 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
69 "portion", "baz");
70 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/merged", "paraPropsNodeIndex", "12");
71 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
72 "type", "PortionType::Text");
73 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
74 "portion", "foo");
75 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
76 "type", "PortionType::Text");
77 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
78 "portion", "baz");
79 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/merged", "paraPropsNodeIndex", "13");
80 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
81 "type", "PortionType::Text");
82 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
83 "portion", "foo");
84 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
85 "type", "PortionType::Text");
86 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
87 "portion", "baz");
88 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/merged", "paraPropsNodeIndex", "14");
89 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
90 "type", "PortionType::Text");
91 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
92 "portion", "foo");
93 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
94 "type", "PortionType::Text");
95 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
96 "portion", "baz");
97 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/merged", "paraPropsNodeIndex", "15");
98 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
99 "type", "PortionType::Text");
100 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
101 "portion", "foo");
102 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
103 "type", "PortionType::Text");
104 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
105 "portion", "baz");
106 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/merged", "paraPropsNodeIndex", "16");
107 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
108 "type", "PortionType::Text");
109 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
110 "portion", "foo");
111 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
112 "type", "PortionType::Text");
113 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
114 "portion", "baz");
115 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/merged", "paraPropsNodeIndex", "17");
116 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
117 "type", "PortionType::Para");
118 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
119 "portion", "foobaz");
120 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/merged", "paraPropsNodeIndex", "18");
121 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
122 "type", "PortionType::Text");
123 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
124 "portion", "fo");
125 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
126 "type", "PortionType::Text");
127 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
128 "portion", "ob");
129 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
130 "type", "PortionType::Text");
131 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
132 "portion", "az");
133 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/merged", "paraPropsNodeIndex", "19");
134 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
135 "type", "PortionType::Para");
136 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwParaPortion[1]",
137 "portion", "foobaz");
140 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf148897)
142 createSwDoc("tdf148897.odt");
144 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
146 assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 1);
147 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
148 assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
149 assertXPath(pXmlDoc, "/root/page[2]/body/txt[3]/anchored/fly", 1);
150 assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 0);
151 assertXPath(pXmlDoc, "/root/page[3]/body/txt/anchored/fly", 0);
152 assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 1);
153 assertXPath(pXmlDoc, "/root/page[4]/body/txt[1]/anchored/fly", 1);
154 // fly portion exists, no overlapping text
155 assertXPath(pXmlDoc, "/root/page[4]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
156 "height", "5797");
157 assertXPath(pXmlDoc, "/root/page[5]/sorted_objs/fly", 0);
158 assertXPath(pXmlDoc, "/root/page", 5);
160 auto xModel = mxComponent.queryThrow<frame::XModel>();
161 uno::Reference<drawing::XShape> xShape(getShapeByName(u"Image3"));
162 uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(), uno::UNO_QUERY);
163 xCtrl->select(uno::Any(xShape));
165 dispatchCommand(mxComponent, ".uno:Delete", {});
167 discardDumpedLayout();
168 pXmlDoc = parseLayoutDump();
170 assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 0);
171 assertXPath(pXmlDoc, "/root/page[1]/body/txt/anchored/fly", 0);
172 assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
173 assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly", 1);
174 assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 1);
175 assertXPath(pXmlDoc, "/root/page[3]/body/txt[2]/anchored/fly", 1);
176 // fly portion exists, no overlapping text
177 assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
178 "height", "5797");
179 assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 0);
180 assertXPath(pXmlDoc, "/root/page[4]/body/txt/anchored/fly", 0);
181 assertXPath(pXmlDoc, "/root/page", 4);
183 dispatchCommand(mxComponent, ".uno:Undo", {});
185 discardDumpedLayout();
186 pXmlDoc = parseLayoutDump();
188 assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 1);
189 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
190 assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
191 assertXPath(pXmlDoc, "/root/page[2]/body/txt[3]/anchored/fly", 1);
192 assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 0);
193 assertXPath(pXmlDoc, "/root/page[3]/body/txt/anchored/fly", 0);
194 assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 1);
195 assertXPath(pXmlDoc, "/root/page[4]/body/txt[1]/anchored/fly", 1);
196 // fly portion exists, no overlapping text
197 assertXPath(pXmlDoc, "/root/page[4]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
198 "height", "5797");
199 assertXPath(pXmlDoc, "/root/page[5]/sorted_objs/fly", 0);
200 assertXPath(pXmlDoc, "/root/page", 5);
202 dispatchCommand(mxComponent, ".uno:Redo", {});
204 discardDumpedLayout();
205 pXmlDoc = parseLayoutDump();
207 assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 0);
208 assertXPath(pXmlDoc, "/root/page[1]/body/txt/anchored/fly", 0);
209 assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
210 assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly", 1);
211 assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 1);
212 assertXPath(pXmlDoc, "/root/page[3]/body/txt[2]/anchored/fly", 1);
213 // fly portion exists, no overlapping text
214 assertXPath(pXmlDoc, "/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
215 "height", "5797");
216 assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 0);
217 assertXPath(pXmlDoc, "/root/page[4]/body/txt/anchored/fly", 0);
218 assertXPath(pXmlDoc, "/root/page", 4);
221 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineCharAttributes)
223 createSwDoc("redline_charatr.fodt");
224 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
225 CPPUNIT_ASSERT(pTextDoc);
226 SwDoc* pDoc(pTextDoc->GetDocShell()->GetDoc());
227 SwRootFrame* pLayout(pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
228 CPPUNIT_ASSERT(pLayout->IsHideRedlines());
230 // verify after load
231 CheckRedlineCharAttributesHidden();
233 dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
234 CPPUNIT_ASSERT(!pLayout->IsHideRedlines());
235 // why is this needed explicitly?
236 pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();
237 discardDumpedLayout();
238 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
240 // show: nothing is merged
241 assertXPath(pXmlDoc, "//merged", 0);
242 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
243 "type", "PortionType::Text");
244 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
245 "portion", "foo");
246 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
247 "type", "PortionType::Text");
248 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
249 "portion", "bar");
250 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
251 "type", "PortionType::Text");
252 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
253 "portion", "baz");
254 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
255 "type", "PortionType::Text");
256 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
257 "portion", "foo");
258 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
259 "type", "PortionType::Text");
260 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
261 "portion", "bar");
262 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
263 "type", "PortionType::Text");
264 assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
265 "portion", "baz");
266 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
267 "type", "PortionType::Text");
268 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
269 "portion", "foo");
270 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
271 "type", "PortionType::Text");
272 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
273 "portion", "bar");
274 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
275 "type", "PortionType::Text");
276 assertXPath(pXmlDoc, "/root/page[1]/body/txt[3]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
277 "portion", "baz");
278 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
279 "type", "PortionType::Text");
280 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
281 "portion", "foo");
282 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
283 "type", "PortionType::Text");
284 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
285 "portion", "bar");
286 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
287 "type", "PortionType::Text");
288 assertXPath(pXmlDoc, "/root/page[1]/body/txt[4]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
289 "portion", "baz");
290 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
291 "type", "PortionType::Text");
292 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
293 "portion", "foo");
294 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
295 "type", "PortionType::Text");
296 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
297 "portion", "bar");
298 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
299 "type", "PortionType::Text");
300 assertXPath(pXmlDoc, "/root/page[1]/body/txt[5]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
301 "portion", "baz");
302 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
303 "type", "PortionType::Text");
304 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
305 "portion", "foo");
306 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
307 "type", "PortionType::Text");
308 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
309 "portion", "bar");
310 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
311 "type", "PortionType::Text");
312 assertXPath(pXmlDoc, "/root/page[1]/body/txt[6]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
313 "portion", "baz");
314 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
315 "type", "PortionType::Text");
316 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
317 "portion", "foo");
318 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
319 "type", "PortionType::Text");
320 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
321 "portion", "bar");
322 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
323 "type", "PortionType::Text");
324 assertXPath(pXmlDoc, "/root/page[1]/body/txt[7]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
325 "portion", "baz");
326 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
327 "type", "PortionType::Text");
328 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
329 "portion", "foo");
330 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
331 "type", "PortionType::Text");
332 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
333 "portion", "ba");
334 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
335 "type", "PortionType::Text");
336 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
337 "portion", "r");
338 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[4]",
339 "type", "PortionType::Text");
340 assertXPath(pXmlDoc, "/root/page[1]/body/txt[8]/SwParaPortion/SwLineLayout/SwLinePortion[4]",
341 "portion", "baz");
342 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
343 "type", "PortionType::Text");
344 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
345 "portion", "foo");
346 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
347 "type", "PortionType::Text");
348 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
349 "portion", "bar");
350 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
351 "type", "PortionType::Text");
352 assertXPath(pXmlDoc, "/root/page[1]/body/txt[9]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
353 "portion", "baz");
354 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
355 "type", "PortionType::Text");
356 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
357 "portion", "fo");
358 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
359 "type", "PortionType::Text");
360 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
361 "portion", "o");
362 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
363 "type", "PortionType::Text");
364 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
365 "portion", "bar");
366 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[4]",
367 "type", "PortionType::Text");
368 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[4]",
369 "portion", "b");
370 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[5]",
371 "type", "PortionType::Text");
372 assertXPath(pXmlDoc, "/root/page[1]/body/txt[10]/SwParaPortion/SwLineLayout/SwLinePortion[5]",
373 "portion", "az");
374 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
375 "type", "PortionType::Text");
376 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[1]",
377 "portion", "foo");
378 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
379 "type", "PortionType::Text");
380 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[2]",
381 "portion", "b");
382 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
383 "type", "PortionType::Text");
384 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[3]",
385 "portion", "a");
386 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[4]",
387 "type", "PortionType::Text");
388 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[4]",
389 "portion", "r");
390 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[5]",
391 "type", "PortionType::Text");
392 assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/SwParaPortion/SwLineLayout/SwLinePortion[5]",
393 "portion", "baz");
395 // verify after hide
396 dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
397 CPPUNIT_ASSERT(pLayout->IsHideRedlines());
398 // why is this needed explicitly?
399 pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();
400 CheckRedlineCharAttributesHidden();
403 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineShowHideFootnotePagination)
405 createSwDoc("redline_footnote_pagination.fodt");
406 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
407 CPPUNIT_ASSERT(pTextDoc);
408 SwDoc* pDoc(pTextDoc->GetDocShell()->GetDoc());
409 SwRootFrame* pLayout(pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
410 CPPUNIT_ASSERT(!pLayout->IsHideRedlines());
412 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
414 // check footnotes
415 assertXPath(pXmlDoc, "/root/page[1]/ftncont/ftn", 6);
416 assertXPath(pXmlDoc, "/root/page[2]/ftncont/ftn", 3);
417 // check that first page ends with the y line and second page starts with z
418 assertXPath(pXmlDoc, "/root/page[1]/body/txt[last()]/SwParaPortion/SwLineLayout[last()]",
419 "portion",
420 "yyyyyyyyy yyy yyyyyyyyyyyyyyyy yyyyyyy yyy yyyyy yyyyyyyyy yyy yyyyyyyyy ");
421 assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
422 "zzz. zzz zzzz zzzz* zzz zzz zzzzzzz zzz zzzz zzzzzzzzzzzzzz zzzzzzzzzzzz ");
424 // hide redlines - all still visible footnotes move to page 1
425 dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
427 discardDumpedLayout();
428 pXmlDoc = parseLayoutDump();
430 assertXPath(pXmlDoc, "/root/page[1]/ftncont/ftn", 2);
431 assertXPath(pXmlDoc, "/root/page[2]/ftncont/ftn", 0);
433 // show again - should now get the same result as on loading
434 dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
436 discardDumpedLayout();
437 pXmlDoc = parseLayoutDump();
439 // check footnotes
440 assertXPath(pXmlDoc, "/root/page[1]/ftncont/ftn", 6);
441 assertXPath(pXmlDoc, "/root/page[2]/ftncont/ftn", 3);
442 // check that first page ends with the y line and second page starts with z
443 assertXPath(pXmlDoc, "/root/page[1]/body/txt[last()]/SwParaPortion/SwLineLayout[last()]",
444 "portion",
445 "yyyyyyyyy yyy yyyyyyyyyyyyyyyy yyyyyyy yyy yyyyy yyyyyyyyy yyy yyyyyyyyy ");
446 assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
447 "zzz. zzz zzzz zzzz* zzz zzz zzzzzzz zzz zzzz zzzzzzzzzzzzzz zzzzzzzzzzzz ");
450 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testtdf138951)
452 // Open the bugdoc
453 createSwDoc("tdf138951.odt");
454 auto pDoc = getSwDoc();
456 // Get the only shape
457 uno::Reference<drawing::XShape> xShape(getShape(1), uno::UNO_QUERY);
458 CPPUNIT_ASSERT(xShape);
460 // Gather its formats: the shape and textbox
461 const SwFrameFormat* pTxFrm = SwTextBoxHelper::getOtherTextBoxFormat(xShape);
462 CPPUNIT_ASSERT(pTxFrm);
463 const SwFrameFormat* pShFrm = SwTextBoxHelper::getOtherTextBoxFormat(pTxFrm, RES_FLYFRMFMT);
464 CPPUNIT_ASSERT(pShFrm);
466 pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();
468 // Get the bound rectangle of the textframe
469 tools::Rectangle aTxtFrmRect(pTxFrm->FindRealSdrObject()->GetLogicRect());
471 // Get the bound rectangle of the shape
472 tools::Rectangle aShpRect(pShFrm->FindRealSdrObject()->GetLogicRect());
474 // Check the anchor the same and the textbox is inside the shape
475 const bool bIsAnchTheSame
476 = *pShFrm->GetAnchor().GetAnchorNode() == *pShFrm->GetAnchor().GetAnchorNode();
477 CPPUNIT_ASSERT_MESSAGE("The anchor is different for the textbox and shape!", bIsAnchTheSame);
478 CPPUNIT_ASSERT_MESSAGE("The textbox has fallen apart!", aShpRect.Contains(aTxtFrmRect));
479 // Without the fix the anchor differs, and the frame outside of the shape
482 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150717)
484 createSwDoc("tdf150717.odt");
485 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
486 // check bookmark colors defined in metadata
487 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[2]", "colors",
488 "#Bookmark1 Bookmark Start");
489 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[4]", "colors",
490 "#Bookmark2 Bookmark Start");
491 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[6]", "colors",
492 "#Bookmark2 Bookmark End#Bookmark1 Bookmark End");
493 // full text, if bookmarks are visible
494 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[1]", "portion",
495 "Lorem ");
496 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[3]", "portion",
497 "ipsum dolor et ");
498 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[5]", "portion",
499 "ames");
500 assertXPath(pXmlDoc, "/root/page/body/txt/SwParaPortion/SwLineLayout/child::*[7]", "portion",
501 ".");
504 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150790)
506 createSwDoc("tdf150790.fodt");
507 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
508 // point bookmark is shown as I-beam (only its text dump is |, as before on the screen)
509 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/SwBookmarkPortion",
510 "colors", "#Bookmark 1 Bookmark");
511 // single start bookmark
512 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/SwBookmarkPortion[1]",
513 "colors", "#Bookmark 2 Bookmark Start");
514 // single end bookmark
515 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/SwBookmarkPortion[3]",
516 "colors", "#Bookmark 3 Bookmark End");
517 // This was |, as before the point bookmark (neighboring end and start bookmarks)
518 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout/SwBookmarkPortion[2]",
519 "colors", "#Bookmark 2 Bookmark End#Bookmark 3 Bookmark Start");
522 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumberInNumbering)
524 createSwDoc("tdf42748.fodt");
525 SwDoc* pDoc = getSwDoc();
526 SwDocShell* pShell = pDoc->GetDocShell();
528 // Dump the rendering of the first page as an XML file.
529 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
530 MetafileXmlDump dumper;
532 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
533 CPPUNIT_ASSERT(pXmlDoc);
535 // Assert the tracked deletion of the number of joined list item and
536 // the tracked insertion of the number after a split list item as not black
537 // (and not COL_GREEN color of the tracked text movement, see testRedlineMoving) elements
538 assertXPath(
539 pXmlDoc,
540 "/metafile/push/push/push/textcolor[not(@color='#000000') and not(@color='#008000')]", 5);
542 // tdf#145068 numbering shows changes in the associated list item, not the next one
543 // This was 1 (black numbering of the first list item previously)
544 assertXPath(pXmlDoc, "/metafile/push/push/push/font[4][@color='#000000']", 0);
547 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumbering)
549 createSwDoc("tdf115523.fodt");
550 SwDoc* pDoc = getSwDoc();
551 SwDocShell* pShell = pDoc->GetDocShell();
553 // Dump the rendering of the first page as an XML file.
554 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
555 MetafileXmlDump dumper;
557 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
558 CPPUNIT_ASSERT(pXmlDoc);
560 // Show the correct and the original line numbering instead of counting
561 // the deleted list items in Show Changes mode, as part of the list
562 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "1.");
563 // This was "2." (deleted text node, now its text content is part of the first list item)
564 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "[2.] ");
565 // This was "3." (now it's the second list item)
566 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[5]/text", "2.[3.] ");
569 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumbering2)
571 createSwDoc("tdf115524.fodt");
572 SwDoc* pDoc = getSwDoc();
573 SwDocShell* pShell = pDoc->GetDocShell();
575 // Dump the rendering of the first page as an XML file.
576 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
577 MetafileXmlDump dumper;
579 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
580 CPPUNIT_ASSERT(pXmlDoc);
582 // Show the correct and the original line numbering in Show Changes mode
583 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "1.");
584 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "2.");
585 // FIXME: show as 3.[2.]
586 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[5]/text", "3.");
587 // This was "4." (not shown the original number)
588 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[7]/text", "4.[3.] ");
591 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf149710_RedlineNumberingEditing)
593 createSwDoc("tdf149710.fodt");
594 SwDoc* pDoc = getSwDoc();
595 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
596 CPPUNIT_ASSERT(pTextDoc);
598 // Show Changes
599 SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
600 SwRootFrame* pLayout(pWrtShell->GetLayout());
601 CPPUNIT_ASSERT(!pLayout->IsHideRedlines());
603 // delete the paragraph mark of the first list item with change tracking
604 dispatchCommand(mxComponent, ".uno:GoToEndOfLine", {});
605 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
606 dispatchCommand(mxComponent, ".uno:Delete", {});
608 // Dump the rendering of the first page as an XML file.
609 SwDocShell* pShell = pDoc->GetDocShell();
610 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
611 MetafileXmlDump dumper;
613 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
614 CPPUNIT_ASSERT(pXmlDoc);
616 // Show the correct and the original line numbering instead of counting
617 // the deleted list items in Show Changes mode, as part of the list
618 // This was "1."
619 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "[1.] ");
620 // This was "2." (deleted text node, now its text content is part of the first list item)
621 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "1.[2.] ");
622 // This was "3." (now it's the second list item)
623 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[5]/text", "2.[3.] ");
625 // remove the tracked deletion, and check the layout again
626 pWrtShell->Undo();
627 xMetaFile = pShell->GetPreviewMetaFile();
628 pXmlDoc = dumpAndParse(dumper, *xMetaFile);
629 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "1.");
630 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "2.");
631 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[5]/text", "3.");
634 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf149709_RedlineNumberingLevel)
636 createSwDoc("tdf149709.fodt");
637 SwDoc* pDoc = getSwDoc();
638 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
639 CPPUNIT_ASSERT(pTextDoc);
641 // Show Changes
642 SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
643 SwRootFrame* pLayout(pWrtShell->GetLayout());
644 CPPUNIT_ASSERT(!pLayout->IsHideRedlines());
646 // insert a new list item at start of the second list item "a)"
647 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
648 pWrtShell->Down(false, 1);
649 pWrtShell->SplitNode(false);
651 // Dump the rendering of the first page as an XML file.
652 SwDocShell* pShell = pDoc->GetDocShell();
653 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
654 MetafileXmlDump dumper;
656 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
657 CPPUNIT_ASSERT(pXmlDoc);
659 // Show the correct and the original line numbering instead of counting
660 // the deleted list items in Show Changes mode, as part of the list
661 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "1.");
662 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "a)");
663 // This was "b)[2.]"
664 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[4]/text", "b)[a)] ");
665 // This was "c)[3.]"
666 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[6]/text", "c)[b)] ");
667 // This was "4.[2.]" (after disabling Show Changes, and enabling again)
668 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[8]/text", "2.");
670 // remove the tracked deletion, and check the layout again
671 pWrtShell->Undo();
672 xMetaFile = pShell->GetPreviewMetaFile();
673 pXmlDoc = dumpAndParse(dumper, *xMetaFile);
674 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "1.");
675 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "a)");
676 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[5]/text", "b)");
677 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[7]/text", "2.");
679 // check Redo
680 pWrtShell->Redo();
681 xMetaFile = pShell->GetPreviewMetaFile();
682 pXmlDoc = dumpAndParse(dumper, *xMetaFile);
683 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", "1.");
684 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", "a)");
685 // TODO: show as b)[a)]
686 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[4]/text", "b)");
687 // FIXME: This must be "c)[b]"
688 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[6]/text", "c)[a)] ");
689 assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[8]/text", "2.");
692 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf149711_importDOCXMoveToParagraphMark)
694 createSwDoc("tdf149711.docx");
695 SwDoc* pDoc = getSwDoc();
696 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
697 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 6);
699 // reject tracked insertion (moveTo)
700 SwEditShell* const pEditShell(pDoc->GetEditShell());
701 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
702 pEditShell->RejectRedline(1);
704 discardDumpedLayout();
705 pXmlDoc = parseLayoutDump();
706 // This was 6 (not tracked paragraph mark of the moveTo list item)
707 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 5);
710 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf152872)
712 createSwDoc("hidden-para-separator.docx");
713 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
715 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 2);
716 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout", "portion", "C DE");
717 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion", 0); // 5 is empty and hidden
718 assertXPath(pXmlDoc, "/root/page/body/txt[2]/infos/bounds", "height", "0");
720 dispatchCommand(mxComponent, ".uno:ControlCodes", {});
722 discardDumpedLayout();
723 pXmlDoc = parseLayoutDump();
725 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 5);
726 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout", "portion", "C ");
727 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout", "portion", "D");
728 // 3 is an empty paragraph with RES_CHRATR_HIDDEN which results in 0-height
729 // frame; ideally it should only be hidden when control codes are hidden
730 // and be a full-height frame now, but that needs more work...
731 assertXPath(pXmlDoc, "/root/page/body/txt[3]/infos/bounds", "height", "0");
732 assertXPath(pXmlDoc, "/root/page/body/txt[4]/SwParaPortion/SwLineLayout", "portion", "E");
733 // 5 is an empty paragraph with RES_CHRATR_HIDDEN which results in 0-height
734 // frame; ideally it should only be hidden when control codes are hidden
735 // and be a full-height frame now, but that needs more work...
736 assertXPath(pXmlDoc, "/root/page/body/txt[5]/SwParaPortion", 0); // 5 is empty
737 assertXPath(pXmlDoc, "/root/page/body/txt[5]/infos/bounds", "height", "0");
739 dispatchCommand(mxComponent, ".uno:ControlCodes", {});
741 discardDumpedLayout();
742 pXmlDoc = parseLayoutDump();
744 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 2);
745 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout", "portion", "C DE");
746 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion", 0); // 5 is empty and hidden
747 assertXPath(pXmlDoc, "/root/page/body/txt[2]/infos/bounds", "height", "0");
750 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf151954)
752 createSwDoc("tdf151954.docx");
753 SwDoc* pDoc = getSwDoc();
754 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
755 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 2);
757 // accept tracked insertion (moveTo)
758 SwEditShell* const pEditShell(pDoc->GetEditShell());
759 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
760 pEditShell->AcceptRedline(0);
762 discardDumpedLayout();
763 pXmlDoc = parseLayoutDump();
764 // This was 1 (moveFrom was extended to the paragraph mark)
765 assertXPath(pXmlDoc, "/root/page[1]/body/txt", 2);
768 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf152952)
770 createSwDoc("Hyphenated-link.rtf");
771 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
772 // URL should not be hyphenated
773 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
774 " NNNNNNNNNN NNNNNNNNNNNNNNN ");
775 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[2]", "portion",
776 "https://example.com/xxxxxxx/testtesttesttest/hyphenate/testtesttest ");
779 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf152952_compat)
781 uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
782 if (!xHyphenator->hasLocale(lang::Locale("en", "US", OUString())))
783 return;
785 createSwDoc("Hyphenated-link.fodt");
786 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
787 // URL hyphenated for backward compatibility
788 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
789 " NNNNNNNNNN NNNNNNNNNNNNNNN https://example.com/xxxxxxx/testtesttesttest/hyphen");
790 assertXPath(pXmlDoc, "/root/page[1]/body/txt[1]/SwParaPortion/SwLineLayout[2]", "portion",
791 "ate/testtesttest ");
794 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumberInFootnote)
796 createSwDoc("tdf85610.fodt");
797 SwDoc* pDoc = getSwDoc();
798 SwDocShell* pShell = pDoc->GetDocShell();
800 // Dump the rendering of the first page as an XML file.
801 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
802 MetafileXmlDump dumper;
804 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
805 CPPUNIT_ASSERT(pXmlDoc);
807 // changed color of numbers of footnote 1 (deleted footnote) and footnote 2 (inserted footnote)
808 // decreased the black <font> elements by 2:
809 // This was 7
810 assertXPath(pXmlDoc, "/metafile/push/push/push/font[@color='#000000']", 5);
813 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineMoving)
815 createSwDoc("tdf42748.fodt");
816 SwDoc* pDoc = getSwDoc();
817 SwDocShell* pShell = pDoc->GetDocShell();
819 // create a 3-element list without change tracking
820 SwEditShell* const pEditShell(pDoc->GetEditShell());
821 pEditShell->RejectRedline(0);
822 pEditShell->AcceptRedline(0);
824 // move down first list item with track changes
825 dispatchCommand(mxComponent, ".uno:GoToStartOfDoc", {});
826 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
827 dispatchCommand(mxComponent, ".uno:MoveDown", {});
829 // Dump the rendering of the first page as an XML file.
830 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
831 MetafileXmlDump dumper;
832 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
833 CPPUNIT_ASSERT(pXmlDoc);
835 // text and numbering colors show moving of the list item
836 // tdf#145719: the moved text item "It" is not detected as text moving,
837 // because it consists of less than 6 characters after stripping its spaces
838 assertXPath(pXmlDoc, "/metafile/push/push/push/textcolor[@color='#008000']", 0);
839 assertXPath(pXmlDoc, "/metafile/push/push/push/font[@color='#008000']", 0);
842 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineMoving2)
844 createSwDoc("tdf42748.fodt");
845 SwDoc* pDoc = getSwDoc();
846 SwDocShell* pShell = pDoc->GetDocShell();
848 // create a 3-element list without change tracking
849 SwEditShell* const pEditShell(pDoc->GetEditShell());
850 pEditShell->RejectRedline(0);
851 pEditShell->AcceptRedline(0);
853 // extend the first item to "An ItemIt", because detection of move needs
854 // at least 6 characters with an inner space after stripping white spaces
855 // of the redline
856 dispatchCommand(mxComponent, ".uno:GoToStartOfDoc", {});
857 SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
858 pWrtShell->Insert("An Item");
860 // move down first list item with track changes
861 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
862 dispatchCommand(mxComponent, ".uno:MoveDown", {});
864 // Dump the rendering of the first page as an XML file.
865 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
866 MetafileXmlDump dumper;
867 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
868 CPPUNIT_ASSERT(pXmlDoc);
870 // text and numbering colors show moving of the list item
871 // These were 0 (other color, not COL_GREEN, color of the tracked text movement)
872 assertXPath(pXmlDoc, "/metafile/push/push/push/textcolor[@color='#008000']", 5);
873 assertXPath(pXmlDoc, "/metafile/push/push/push/font[@color='#008000']", 11);
876 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineMovingDOCX)
878 createSwDoc("tdf104797.docx");
879 SwDoc* pDoc = getSwDoc();
880 SwDocShell* pShell = pDoc->GetDocShell();
882 SwEditShell* const pEditShell(pDoc->GetEditShell());
883 // This was 2 (moveFrom and moveTo joined other redlines)
884 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(5), pEditShell->GetRedlineCount());
886 // Dump the rendering of the first page as an XML file.
887 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
888 MetafileXmlDump dumper;
889 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
890 CPPUNIT_ASSERT(pXmlDoc);
892 // text colors show moved text
893 // These were 0 (other color, not COL_GREEN, color of the tracked text movement)
894 assertXPath(pXmlDoc, "/metafile/push/push/push/textcolor[@color='#008000']", 6);
897 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTableCellInvalidate)
899 discardDumpedLayout();
900 if (mxComponent.is())
901 mxComponent->dispose();
903 OUString const url(createFileURL(u"table_cell_overlap.fodt"));
905 // note: must set Hidden property, so that SfxFrameViewWindow_Impl::Resize()
906 // does *not* forward initial VCL Window Resize and thereby triggers a
907 // layout which does not happen on soffice --convert-to pdf.
908 std::vector<beans::PropertyValue> aFilterOptions = {
909 { beans::PropertyValue("Hidden", -1, uno::Any(true), beans::PropertyState_DIRECT_VALUE) },
912 // inline the loading because currently properties can't be passed...
913 mxComponent = loadFromDesktop(url, "com.sun.star.text.TextDocument",
914 comphelper::containerToSequence(aFilterOptions));
915 save("writer_pdf_Export");
917 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
918 // somehow these 2 rows overlapped in the PDF unless CalcLayout() runs
919 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/infos/bounds", "top", "6969");
920 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/infos/bounds", "height", "231");
921 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/cell[1]/infos/bounds", "top",
922 "6969");
923 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/cell[1]/infos/bounds", "height",
924 "231");
925 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/cell[1]/txt[1]/infos/bounds",
926 "top", "6969");
927 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[1]/cell[1]/txt[1]/infos/bounds",
928 "height", "231");
929 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/infos/bounds", "top", "7200");
930 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/infos/bounds", "height", "231");
931 // this was 6969, causing the overlap
932 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/cell[1]/infos/bounds", "top",
933 "7200");
934 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/cell[1]/infos/bounds", "height",
935 "231");
936 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/cell[1]/txt[1]/infos/bounds",
937 "top", "7200");
938 assertXPath(pXmlDoc, "/root/page[1]/anchored/fly/tab[1]/row[2]/cell[1]/txt[1]/infos/bounds",
939 "height", "231");
942 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf145719)
944 createSwDoc("tdf145719.odt");
945 SwDoc* pDoc = getSwDoc();
946 SwDocShell* pShell = pDoc->GetDocShell();
948 // Dump the rendering of the first page as an XML file.
949 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
950 MetafileXmlDump dumper;
951 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
952 CPPUNIT_ASSERT(pXmlDoc);
954 // text colors show moved text
955 // This was 0 (other color, not COL_GREEN, color of the tracked text movement)
956 assertXPath(pXmlDoc, "/metafile/push/push/push/textcolor[@color='#008000']", 4);
959 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testChangedTableRows)
961 createSwDoc("changed_table_rows.fodt");
962 SwDoc* pDoc = getSwDoc();
963 SwDocShell* pShell = pDoc->GetDocShell();
965 // Dump the rendering of the first page as an XML file.
966 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
967 MetafileXmlDump dumper;
968 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
969 CPPUNIT_ASSERT(pXmlDoc);
971 // This was 0 (other color, not COL_AUTHOR_TABLE_DEL, color of the tracked row deletion)
972 assertXPath(pXmlDoc, "/metafile/push/push/push/push/push/fillcolor[@color='#fce6f4']", 1);
973 // This was 0 (other color, not COL_AUTHOR_TABLE_INS, color of the tracked row insertion)
974 assertXPath(pXmlDoc, "/metafile/push/push/push/push/push/fillcolor[@color='#e1f2fa']", 1);
975 // This was 3 (color of the cells of the last column, 2 of them disabled by change tracking )
976 assertXPath(pXmlDoc, "/metafile/push/push/push/push/push/fillcolor[@color='#3faf46']", 1);
979 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf155187_TableInTextChange)
981 createSwDoc("table_in_text_change.fodt");
982 SwDoc* pDoc = getSwDoc();
983 SwDocShell* pShell = pDoc->GetDocShell();
985 // Dump the rendering of the first page as an XML file.
986 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
987 MetafileXmlDump dumper;
988 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
989 CPPUNIT_ASSERT(pXmlDoc);
991 // This was 0 (other color, not COL_AUTHOR_TABLE_DEL, color of the tracked row deletion)
992 assertXPath(pXmlDoc, "/metafile/push/push/push/push/push/fillcolor[@color='#fce6f4']", 2);
993 // This was 0 (other color, not COL_AUTHOR_TABLE_INS, color of the tracked row insertion)
994 assertXPath(pXmlDoc, "/metafile/push/push/push/push/push/fillcolor[@color='#e1f2fa']", 2);
997 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf145225_RedlineMovingWithBadInsertion)
999 createSwDoc("tdf42748.fodt");
1000 SwDoc* pDoc = getSwDoc();
1001 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1002 CPPUNIT_ASSERT(pTextDoc);
1004 // create a 3-element list without change tracking
1005 // (because the fixed problem depends on the own changes)
1006 SwEditShell* const pEditShell(pDoc->GetEditShell());
1007 pEditShell->RejectRedline(0);
1008 pEditShell->AcceptRedline(0);
1009 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), pEditShell->GetRedlineCount());
1011 // Show Changes
1012 SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
1013 SwRootFrame* pLayout(pWrtShell->GetLayout());
1014 CPPUNIT_ASSERT(!pLayout->IsHideRedlines());
1016 // insert a tracked paragraph break in middle of the second list item, i.e. split it
1017 dispatchCommand(mxComponent, ".uno:GoToStartOfDoc", {});
1018 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
1019 // positionate the cursor in the middle of the second list item
1020 pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false);
1021 pWrtShell->SplitNode(false);
1022 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), pEditShell->GetRedlineCount());
1024 // move up the last list item over the paragraph split
1025 dispatchCommand(mxComponent, ".uno:GoToEndOfDoc", {});
1026 dispatchCommand(mxComponent, ".uno:MoveUp", {});
1027 dispatchCommand(mxComponent, ".uno:MoveUp", {});
1028 // This was 2 (the tracked paragraph break joined with the moved list item,
1029 // setting the not changed text of the second list item to tracked insertion)
1030 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(3), pEditShell->GetRedlineCount());
1033 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf146964_ReappearingMovedTextInHideChangesMode)
1035 createSwDoc("tdf54819.fodt");
1036 SwDoc* pDoc = getSwDoc();
1037 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
1038 CPPUNIT_ASSERT(pTextDoc);
1040 // enable Record Changes
1041 dispatchCommand(mxComponent, ".uno:TrackChanges", {});
1042 CPPUNIT_ASSERT_MESSAGE("redlining should be on",
1043 pDoc->getIDocumentRedlineAccess().IsRedlineOn());
1045 // set Hide Changes mode
1046 dispatchCommand(mxComponent, ".uno:ShowTrackedChanges", {});
1047 SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
1048 SwRootFrame* pLayout(pWrtShell->GetLayout());
1049 CPPUNIT_ASSERT(pLayout->IsHideRedlines());
1051 // delete and paste the deleted word again during Track Changes
1052 dispatchCommand(mxComponent, ".uno:WordRightSel", {});
1053 dispatchCommand(mxComponent, ".uno:Cut", {});
1054 dispatchCommand(mxComponent, ".uno:Paste", {});
1056 SwEditShell* const pEditShell(pDoc->GetEditShell());
1057 CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), pEditShell->GetRedlineCount());
1059 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1060 CPPUNIT_ASSERT(pXmlDoc);
1061 // This was "Lorem Lorem ipsum" (reappearing deletion in Hide Changes mode)
1062 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout/SwParaPortion",
1063 "portion", "Lorem ipsum");
1066 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf125300)
1068 createSwDoc("tdf125300.docx");
1069 SwDoc* pDoc = getSwDoc();
1070 SwDocShell* pShell = pDoc->GetDocShell();
1072 // Dump the rendering of the first page as an XML file.
1073 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1074 MetafileXmlDump dumper;
1076 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1077 CPPUNIT_ASSERT(pXmlDoc);
1079 // Keep line spacing before bottom cell border (it was 1892)
1080 sal_Int32 y1
1081 = getXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[1]/push[5]/polyline/point[1]", "y")
1082 .toInt32();
1083 sal_Int32 y2
1084 = getXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[1]/push[5]/polyline/point[2]", "y")
1085 .toInt32();
1086 CPPUNIT_ASSERT_DOUBLES_EQUAL(2092, y1, 7);
1087 CPPUNIT_ASSERT_EQUAL(y1, y2);
1090 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116830)
1092 createSwDoc("tdf116830.odt");
1093 SwDoc* pDoc = getSwDoc();
1094 SwDocShell* pShell = pDoc->GetDocShell();
1096 // Dump the rendering of the first page as an XML file.
1097 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1098 MetafileXmlDump dumper;
1099 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1100 CPPUNIT_ASSERT(pXmlDoc);
1102 // Assert that the yellow rectangle (cell background) is painted after the
1103 // polypolygon (background shape).
1104 // Background shape: 1.1.1.2
1105 // Cell background: 1.1.1.3
1106 assertXPath(
1107 pXmlDoc,
1108 "/metafile/push[1]/push[1]/push[1]/push[2]/push[1]/push[1]/fillcolor[@color='#729fcf']", 1);
1109 assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[1]/push[2]/push[1]/push[1]/polypolygon",
1112 // This failed: cell background was painted before the background shape.
1113 assertXPath(pXmlDoc,
1114 "/metafile/push[1]/push[1]/push[1]/push[3]/push[1]/fillcolor[@color='#ffff00']", 1);
1115 assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[1]/push[3]/push[1]/rect", 1);
1118 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf114163)
1120 createSwDoc("tdf114163.odt");
1121 SwDoc* pDoc = getSwDoc();
1122 SwDocShell* pShell = pDoc->GetDocShell();
1124 // Dump the rendering of the first page as an XML file.
1125 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1126 MetafileXmlDump dumper;
1127 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1128 CPPUNIT_ASSERT(pXmlDoc);
1130 assertXPathContent(pXmlDoc, "(//textarray)[12]/text", "Data3");
1131 // This failed, if the legend first label is not "Data3". The legend position is right.
1134 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf131707)
1136 createSwDoc("tdf131707_flyWrap.doc");
1137 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1139 assertXPath(pXmlDoc, "//body/tab/row[3]/cell[2]/txt/infos/bounds", "top", "2185");
1140 // the image should be inside of the cell boundary - so the same top or higher
1141 assertXPath(pXmlDoc, "//body/tab/row[3]/cell[2]/txt/anchored/fly/infos/bounds", "top", "2185");
1144 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf122225)
1146 createSwDoc("tdf122225.docx");
1147 SwDoc* pDoc = getSwDoc();
1148 SwDocShell* pShell = pDoc->GetDocShell();
1150 // Dump the rendering of the first page as an XML file.
1151 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1152 MetafileXmlDump dumper;
1153 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1154 CPPUNIT_ASSERT(pXmlDoc);
1156 // Bug 122225 - FILEOPEN DOCX Textbox of Column chart legend reduces and text of legend disappears
1157 const sal_Int32 nLegendLabelLines
1158 = getXPathContent(pXmlDoc, "count(//text[contains(text(),\"Advanced Diploma\")])")
1159 .toInt32();
1160 // This failed, if the legend label is not "Advanced Diploma".
1161 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nLegendLabelLines);
1163 // Bug 140623 - Fileopen DOCX: Text Orientation of X-Axis 0 instead of 45 degrees
1164 const sal_Int32 nThirdLabelLines
1165 = getXPathContent(pXmlDoc, "count(//text[contains(text(),\"Hispanic\")])").toInt32();
1166 // This failed, if the third X axis label broke to multiple lines.
1167 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nThirdLabelLines);
1170 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf125335)
1172 createSwDoc("tdf125335.odt");
1173 SwDoc* pDoc = getSwDoc();
1174 SwDocShell* pShell = pDoc->GetDocShell();
1176 // Dump the rendering of the first page as an XML file.
1177 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1178 MetafileXmlDump dumper;
1179 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1180 CPPUNIT_ASSERT(pXmlDoc);
1182 assertXPathContent(pXmlDoc, "(//textarray)[12]/text", "Data3");
1183 // This failed, if the legend first label is not "Data3". The legend position is bottom.
1186 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134247)
1188 createSwDoc("legend-itemorder-min.docx");
1189 SwDoc* pDoc = getSwDoc();
1190 SwDocShell* pShell = pDoc->GetDocShell();
1192 // Dump the rendering of the first page as an XML file.
1193 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1194 MetafileXmlDump dumper;
1195 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1196 CPPUNIT_ASSERT(pXmlDoc);
1198 assertXPathContent(pXmlDoc, "(//textarray)[14]/text", "1. adatsor");
1199 // This failed, if the legend first label is not "1. adatsor".
1202 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf75659)
1204 createSwDoc("tdf75659.docx");
1205 SwDoc* pDoc = getSwDoc();
1206 SwDocShell* pShell = pDoc->GetDocShell();
1208 // Dump the rendering of the first page as an XML file.
1209 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1210 MetafileXmlDump dumper;
1211 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1212 CPPUNIT_ASSERT(pXmlDoc);
1214 assertXPathContent(pXmlDoc, "(//textarray)[17]/text", "Series1");
1215 assertXPathContent(pXmlDoc, "(//textarray)[18]/text", "Series2");
1216 assertXPathContent(pXmlDoc, "(//textarray)[19]/text", "Series3");
1217 // These failed, if the legend names are empty strings.
1220 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf136816)
1222 createSwDoc("tdf136816.odt");
1223 SwDoc* pDoc = getSwDoc();
1224 SwDocShell* pShell = pDoc->GetDocShell();
1226 // Dump the rendering of the first page as an XML file.
1227 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1228 MetafileXmlDump dumper;
1229 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1230 CPPUNIT_ASSERT(pXmlDoc);
1232 // Check number of legend entries
1233 assertXPath(pXmlDoc, "//text[contains(text(),\"Column\")]", 2);
1236 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf126425)
1238 createSwDoc("long_legendentry.docx");
1239 SwDoc* pDoc = getSwDoc();
1240 SwDocShell* pShell = pDoc->GetDocShell();
1242 // Dump the rendering of the first page as an XML file.
1243 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1244 MetafileXmlDump dumper;
1245 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1246 CPPUNIT_ASSERT(pXmlDoc);
1247 // Without the accompanying fix in place, this test would have failed with:
1248 // - Expected: 14
1249 // - Actual : 12
1250 // i.e. the text of the chart legend lost.
1251 assertXPath(pXmlDoc, "//textarray", 14);
1254 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testUnusedOLEprops)
1256 createSwDoc("tdf138465min.docx");
1258 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1259 CPPUNIT_ASSERT(pXmlDoc);
1260 // Without the accompanying fix in place, this test would have failed with:
1261 // - Expected: >300
1262 // - Actual : 142
1263 // i.e. the formula squashed
1264 CPPUNIT_ASSERT_GREATEREQUAL(
1265 double(300),
1266 getXPath(pXmlDoc, "/root/page/body/txt[2]/anchored/fly/notxt/infos/bounds", "height")
1267 .toDouble());
1270 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf123268)
1272 createSwDoc("tdf123268.odt");
1273 SwDoc* pDoc = getSwDoc();
1274 SwDocShell* pShell = pDoc->GetDocShell();
1276 // Dump the rendering of the first page as an XML file.
1277 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1278 MetafileXmlDump dumper;
1279 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1280 CPPUNIT_ASSERT(pXmlDoc);
1281 // Without the accompanying fix in place, this test would have failed with:
1282 // - Expected: 53
1283 // - Actual : 0
1284 // i.e. the chart lost.
1285 assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/push[1]/push[3]/push[1]/push[1]/push[1]/push",
1286 53);
1289 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf133005)
1291 createSwDoc("tdf133005.odt");
1292 SwDoc* pDoc = getSwDoc();
1293 SwDocShell* pShell = pDoc->GetDocShell();
1295 // Dump the rendering of the first page as an XML file.
1296 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1297 MetafileXmlDump dumper;
1298 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1299 CPPUNIT_ASSERT(pXmlDoc);
1301 sal_Int32 nXChartWall = getXPath(pXmlDoc,
1302 "/metafile/push[1]/push[1]/push[1]/push[3]/push[1]/push[1]/"
1303 "push[1]/push[1]/polyline[1]/point[2]",
1304 "x")
1305 .toInt32();
1306 sal_Int32 nXColumn = getXPath(pXmlDoc,
1307 "/metafile/push[1]/push[1]/push[1]/push[3]/push[1]/push[1]/"
1308 "push[1]/push[41]/polypolygon/polygon/point[1]",
1309 "x")
1310 .toInt32();
1312 // This failed, if the value axis doesn't appear inside category.
1313 CPPUNIT_ASSERT_DOUBLES_EQUAL(nXChartWall, nXColumn, 5);
1316 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf115630)
1318 createSwDoc("tdf115630.docx");
1319 SwDoc* pDoc = getSwDoc();
1320 SwDocShell* pShell = pDoc->GetDocShell();
1322 // Dump the rendering of the first page as an XML file.
1323 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1324 MetafileXmlDump dumper;
1325 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1326 CPPUNIT_ASSERT(pXmlDoc);
1328 // Test wide of inner chart area.
1329 sal_Int32 nXRight
1330 = getXPath(pXmlDoc,
1331 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[3]/polyline[1]/point[1]",
1332 "x")
1333 .toInt32();
1334 sal_Int32 nXLeft
1335 = getXPath(pXmlDoc,
1336 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[3]/polyline[1]/point[2]",
1337 "x")
1338 .toInt32();
1339 CPPUNIT_ASSERT_DOUBLES_EQUAL(2895, nXRight - nXLeft, 50);
1342 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf108021)
1344 createSwDoc("tdf108021.odt");
1345 SwDoc* pDoc = getSwDoc();
1346 SwDocShell* pShell = pDoc->GetDocShell();
1348 // Dump the rendering of the first page as an XML file.
1349 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1350 MetafileXmlDump dumper;
1351 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1352 CPPUNIT_ASSERT(pXmlDoc);
1354 assertXPath(pXmlDoc, "//textarray[@length='22']", 8);
1355 // This failed, if the textarray length of the first axis label not 22.
1358 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf125334)
1360 createSwDoc("tdf125334.odt");
1361 SwDoc* pDoc = getSwDoc();
1362 SwDocShell* pShell = pDoc->GetDocShell();
1364 // Dump the rendering of the first page as an XML file.
1365 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1366 MetafileXmlDump dumper;
1367 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1368 CPPUNIT_ASSERT(pXmlDoc);
1370 assertXPath(pXmlDoc, "//textarray[@length='17']", 4);
1371 // This failed, if the textarray length of the category axis label not 17.
1374 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf122800)
1376 createSwDoc("tdf122800.odt");
1377 SwDoc* pDoc = getSwDoc();
1378 SwDocShell* pShell = pDoc->GetDocShell();
1380 // Dump the rendering of the first page as an XML file.
1381 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1382 MetafileXmlDump dumper;
1383 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1384 CPPUNIT_ASSERT(pXmlDoc);
1386 assertXPath(pXmlDoc, "//textarray[@length='22']", 9);
1387 // This failed, if the textarray length of the first axis label not 22.
1390 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTruncatedAxisLabel)
1392 createSwDoc("testTruncatedAxisLabel.odt");
1393 SwDoc* pDoc = getSwDoc();
1394 SwDocShell* pShell = pDoc->GetDocShell();
1396 // Dump the rendering of the first page as an XML file.
1397 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1398 MetafileXmlDump dumper;
1399 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1400 CPPUNIT_ASSERT(pXmlDoc);
1402 // test the X axis label visibility
1403 assertXPathContent(pXmlDoc, "(//textarray)[1]/text", "Long axis label truncated 1");
1405 // test the Y axis label visibility
1406 assertXPathContent(pXmlDoc, "(//textarray)[3]/text", "-5.00");
1409 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf128996)
1411 createSwDoc("tdf128996.docx");
1412 SwDoc* pDoc = getSwDoc();
1413 SwDocShell* pShell = pDoc->GetDocShell();
1415 // Dump the rendering of the first page as an XML file.
1416 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1417 MetafileXmlDump dumper;
1418 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1419 CPPUNIT_ASSERT(pXmlDoc);
1421 assertXPathContent(pXmlDoc, "(//textarray)[1]/text", "A very long category name 1");
1424 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf126244)
1426 createSwDoc("tdf126244.docx");
1427 SwDoc* pDoc = getSwDoc();
1428 SwDocShell* pShell = pDoc->GetDocShell();
1430 // Dump the rendering of the first page as an XML file.
1431 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1432 MetafileXmlDump dumper;
1433 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1434 CPPUNIT_ASSERT(pXmlDoc);
1435 // Test the first level of vertical category axis labels orientation. The first level orientation should be horizontal.
1436 assertXPath(pXmlDoc, "(//font)[1]", "orientation", "0");
1437 // Test the second level of vertical category axis labels orientation. The second level orientation should be vertical.
1438 sal_Int32 nRotation = getXPath(pXmlDoc, "(//font)[5]", "orientation").toInt32();
1439 CPPUNIT_ASSERT(nRotation >= 899);
1440 CPPUNIT_ASSERT(nRotation <= 900);
1441 // Test the third level of vertical category axis labels orientation. The third level orientation should be vertical.
1442 nRotation = getXPath(pXmlDoc, "(//font)[7]", "orientation").toInt32();
1443 CPPUNIT_ASSERT(nRotation >= 899);
1444 CPPUNIT_ASSERT(nRotation <= 900);
1447 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf127304)
1449 createSwDoc("tdf127304.odt");
1450 SwDoc* pDoc = getSwDoc();
1451 SwDocShell* pShell = pDoc->GetDocShell();
1453 // Dump the rendering of the first page as an XML file.
1454 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1455 MetafileXmlDump dumper;
1456 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1457 CPPUNIT_ASSERT(pXmlDoc);
1458 // Test the first level of horizontal category axis labels orientation. The first level orientation should be vertical.
1459 sal_Int32 nRotation = getXPath(pXmlDoc, "(//font)[1]", "orientation").toInt32();
1460 CPPUNIT_ASSERT(nRotation >= 899);
1461 CPPUNIT_ASSERT(nRotation <= 900);
1462 // Test the second level of horizontal category axis labels orientation. The second level orientation should be horizontal.
1463 assertXPath(pXmlDoc, "(//font)[5]", "orientation", "0");
1464 // Test the third level of horizontal category axis labels orientation. The third level orientation should be horizontal.
1465 assertXPath(pXmlDoc, "(//font)[7]", "orientation", "0");
1468 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testHorizontal_multilevel)
1470 createSwDoc("horizontal_multilevel.odt");
1471 SwDoc* pDoc = getSwDoc();
1472 SwDocShell* pShell = pDoc->GetDocShell();
1474 // Dump the rendering of the first page as an XML file.
1475 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1476 MetafileXmlDump dumper;
1477 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1478 CPPUNIT_ASSERT(pXmlDoc);
1479 // Test the Y position of horizontal category axis label.
1480 sal_Int32 nYposition = getXPath(pXmlDoc, "(//textarray)[7]", "y").toInt32();
1481 CPPUNIT_ASSERT_DOUBLES_EQUAL(11248, nYposition, 20);
1484 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf69648)
1486 createSwDoc("tdf69648.docx");
1487 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
1488 CPPUNIT_ASSERT(pXmlDoc);
1490 OString sShapeXPath[2] = {
1491 "/root/page/body/txt/anchored/SwAnchoredDrawObject/SdrObjGroup/SdrObjList/SdrObject[1]",
1492 "/root/page/body/txt/anchored/SwAnchoredDrawObject/SdrObjGroup/SdrObjList/SdrObject[2]"
1494 OString sFrameXPath[2] = { "/root/page/body/txt/anchored/fly[1]/infos/bounds",
1495 "/root/page/body/txt/anchored/fly[2]/infos/bounds" };
1497 for (int i = 0; i < 2; ++i)
1499 const auto sDrawRect = getXPath(pXmlDoc, sShapeXPath[i], "aOutRect");
1500 const auto nComaPos1 = sDrawRect.indexOf(',', 0);
1501 const auto nComaPos2 = sDrawRect.indexOf(',', nComaPos1 + 1);
1502 const auto nComaPos3 = sDrawRect.indexOf(',', nComaPos2 + 1);
1504 const auto nDraw1 = o3tl::toInt64(sDrawRect.subView(0, nComaPos1));
1505 const auto nDraw2 = o3tl::toInt64(sDrawRect.subView(nComaPos1 + 1, nComaPos2 - nComaPos1));
1506 const auto nDraw3 = o3tl::toInt64(sDrawRect.subView(nComaPos2 + 1, nComaPos3 - nComaPos2));
1507 const auto nDraw4 = o3tl::toInt64(
1508 sDrawRect.subView(nComaPos3 + 1, sDrawRect.getLength() - nComaPos3 - 1));
1509 const auto aChildShape = SwRect(nDraw1, nDraw2, nDraw3, nDraw4);
1511 const auto nFlyLeft = getXPath(pXmlDoc, sFrameXPath[i], "left").toInt64();
1512 const auto nFlyTop = getXPath(pXmlDoc, sFrameXPath[i], "top").toInt64();
1513 const auto nFlyWidth = getXPath(pXmlDoc, sFrameXPath[i], "width").toInt64();
1514 const auto nFlyHeight = getXPath(pXmlDoc, sFrameXPath[i], "height").toInt64();
1516 const auto aFrame = SwRect(nFlyLeft, nFlyTop, nFlyWidth, nFlyHeight);
1518 CPPUNIT_ASSERT_MESSAGE("Textbox must be inside the shape!", aChildShape.Contains(aFrame));
1522 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116256)
1524 // Open bugdoc
1525 createSwDoc("tdf116256.docx");
1526 CPPUNIT_ASSERT(mxComponent);
1528 // Get the textbox
1529 uno::Reference<beans::XPropertySet> xTextBox(getShape(2), uno::UNO_QUERY_THROW);
1531 // Ensure that is a real textbox, and follows the text flow
1532 CPPUNIT_ASSERT(xTextBox->getPropertyValue("TextBox").get<bool>());
1533 CPPUNIT_ASSERT(xTextBox->getPropertyValue("IsFollowingTextFlow").get<bool>());
1535 // Parse the layout
1536 auto pLayout = parseLayoutDump();
1537 // Get the position of the shape
1538 const auto nTextBoxShapeLeft = getXPath(pLayout,
1539 "/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/"
1540 "anchored/SwAnchoredDrawObject/bounds",
1541 "left")
1542 .toInt64();
1543 const auto nTextBoxShapeTop = getXPath(pLayout,
1544 "/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/"
1545 "anchored/SwAnchoredDrawObject/bounds",
1546 "top")
1547 .toInt64();
1548 // Get the position of the textframe too.
1549 const auto nTextBoxFrameLeft
1550 = getXPath(pLayout,
1551 "/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/anchored/fly/infos/bounds",
1552 "left")
1553 .toInt64();
1554 const auto nTextBoxFrameTop
1555 = getXPath(pLayout,
1556 "/root/page/body/txt/anchored/fly/tab/row[1]/cell/txt/anchored/fly/infos/bounds",
1557 "top")
1558 .toInt64();
1560 // Without the fix in place these were less than they supposed to.
1561 CPPUNIT_ASSERT_GREATEREQUAL(nTextBoxShapeLeft, nTextBoxFrameLeft);
1562 CPPUNIT_ASSERT_GREATEREQUAL(nTextBoxShapeTop, nTextBoxFrameTop);
1565 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138194)
1567 createSwDoc("xaxis-labelbreak.docx");
1568 SwDoc* pDoc = getSwDoc();
1569 SwDocShell* pShell = pDoc->GetDocShell();
1571 // Dump the rendering of the first page as an XML file.
1572 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1573 MetafileXmlDump dumper;
1574 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1575 CPPUNIT_ASSERT(pXmlDoc);
1576 // Without the accompanying fix in place, this test would have failed with:
1577 // - Expected: 8
1578 // - Actual : 7
1579 // i.e. the X axis label flowed out of chart area.
1580 assertXPath(pXmlDoc, "//textarray", 8);
1583 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf146272)
1585 createSwDoc("tdf146272.odt");
1587 uno::Reference<beans::XPropertySet> xPicture(getShape(2), uno::UNO_QUERY);
1588 uno::Reference<beans::XPropertySet> xDrawing(getShape(1), uno::UNO_QUERY);
1589 uno::Reference<beans::XPropertySet> xFrame(xDrawing->getPropertyValue("TextBoxContent"),
1590 uno::UNO_QUERY);
1592 CPPUNIT_ASSERT(xPicture);
1593 CPPUNIT_ASSERT(xDrawing);
1594 CPPUNIT_ASSERT(xFrame);
1596 const sal_uInt64 nPitureZorder = xPicture->getPropertyValue("ZOrder").get<sal_uInt64>();
1597 const sal_uInt64 nDrawingZorder = xDrawing->getPropertyValue("ZOrder").get<sal_uInt64>();
1598 const sal_uInt64 nFrameZorder = xFrame->getPropertyValue("ZOrder").get<sal_uInt64>();
1600 CPPUNIT_ASSERT_MESSAGE("Bad ZOrder!", nDrawingZorder < nFrameZorder);
1601 CPPUNIT_ASSERT_MESSAGE("Bad ZOrder!", nFrameZorder < nPitureZorder);
1604 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138773)
1606 createSwDoc("tdf138773.docx");
1607 SwDoc* pDoc = getSwDoc();
1608 SwDocShell* pShell = pDoc->GetDocShell();
1610 // Dump the rendering of the first page as an XML file.
1611 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1612 MetafileXmlDump dumper;
1613 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1614 CPPUNIT_ASSERT(pXmlDoc);
1616 const sal_Int32 nFirstLabelLines
1617 = getXPathContent(pXmlDoc, "count(//text[contains(text(),\"2000-01\")])").toInt32();
1619 // This failed, if the first X axis label broke to multiple lines.
1620 CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nFirstLabelLines);
1623 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf124796)
1625 createSwDoc("tdf124796.odt");
1626 SwDoc* pDoc = getSwDoc();
1627 SwDocShell* pShell = pDoc->GetDocShell();
1629 // Dump the rendering of the first page as an XML file.
1630 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1631 MetafileXmlDump dumper;
1632 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1633 CPPUNIT_ASSERT(pXmlDoc);
1635 // This failed, if the minimum value of Y axis is not -10.
1636 assertXPathContent(pXmlDoc, "(//textarray)[5]/text", "-10");
1638 // This failed, if the maximum value of Y axis is not 15.
1639 assertXPathContent(pXmlDoc, "(//textarray)[10]/text", "15");
1642 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf72727)
1644 createSwDoc("tdf72727.odt");
1645 SwDoc* pDoc = getSwDoc();
1646 SwDocShell* pShell = pDoc->GetDocShell();
1648 // Dump the rendering of the first page as an XML file.
1649 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1650 MetafileXmlDump dumper;
1651 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1652 CPPUNIT_ASSERT(pXmlDoc);
1654 // Without the fix in place, this test would have failed with
1655 // - Expected: 1
1656 // - Actual : Series1
1657 assertXPathContent(pXmlDoc, "(//textarray)[1]/text", "1");
1658 assertXPathContent(pXmlDoc, "(//textarray)[2]/text", "2");
1659 assertXPathContent(pXmlDoc, "(//textarray)[3]/text", "3");
1662 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf130969)
1664 createSwDoc("tdf130969.docx");
1665 SwDoc* pDoc = getSwDoc();
1666 SwDocShell* pShell = pDoc->GetDocShell();
1668 // Dump the rendering of the first page as an XML file.
1669 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1670 MetafileXmlDump dumper;
1671 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1672 CPPUNIT_ASSERT(pXmlDoc);
1674 // This failed, if the minimum value of Y axis is not 0.35781
1675 assertXPathContent(pXmlDoc, "(//textarray)[5]/text", "0.35781");
1678 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf40260)
1680 createSwDoc("tdf40260.odt");
1681 SwDoc* pDoc = getSwDoc();
1682 SwDocShell* pShell = pDoc->GetDocShell();
1684 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1685 MetafileXmlDump dumper;
1686 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1687 CPPUNIT_ASSERT(pXmlDoc);
1689 // Without the fix in place, this test would have failed with
1690 // - Expected: f(x) = 1.26510397865547E-06 x − 5.95245604996327E-12
1691 // - Actual : f(x) = 0 x − 0
1692 assertXPathContent(pXmlDoc, "(//textarray)[19]/text",
1693 "f(x) = 1.26510397865547E-06 x " + OUStringChar(u'\x2212')
1694 + " 5.95245604996327E-12");
1697 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf129054)
1699 createSwDoc("tdf129054.docx");
1700 SwDoc* pDoc = getSwDoc();
1701 SwDocShell* pShell = pDoc->GetDocShell();
1703 // Dump the rendering of the first page as an XML file.
1704 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1705 MetafileXmlDump dumper;
1706 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1707 CPPUNIT_ASSERT(pXmlDoc);
1709 // Test the size of diameter of Pie chart.
1710 sal_Int32 nYTop
1711 = getXPath(pXmlDoc,
1712 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[4]/polyline[1]/point[1]",
1713 "y")
1714 .toInt32();
1715 sal_Int32 nYBottom
1716 = getXPath(
1717 pXmlDoc,
1718 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[4]/polyline[1]/point[31]",
1719 "y")
1720 .toInt32();
1721 CPPUNIT_ASSERT_DOUBLES_EQUAL(4615, nYTop - nYBottom, 5);
1724 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf129173)
1726 createSwDoc("testAreaChartNumberFormat.docx");
1727 SwDoc* pDoc = getSwDoc();
1728 SwDocShell* pShell = pDoc->GetDocShell();
1730 // Dump the rendering of the first page as an XML file.
1731 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1732 MetafileXmlDump dumper;
1733 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1734 CPPUNIT_ASSERT(pXmlDoc);
1736 // Check the first data label of area chart.
1737 assertXPathContent(pXmlDoc, "(//textarray)[22]/text", "56");
1740 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134866)
1742 createSwDoc("tdf134866.docx");
1743 SwDoc* pDoc = getSwDoc();
1744 SwDocShell* pShell = pDoc->GetDocShell();
1746 // Dump the rendering of the first page as an XML file.
1747 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1748 MetafileXmlDump dumper;
1749 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1750 CPPUNIT_ASSERT(pXmlDoc);
1752 // Check the data label of pie chart.
1753 assertXPathContent(pXmlDoc, "(//textarray)[2]/text", "100%");
1756 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf137116)
1758 createSwDoc("tdf137116.docx");
1759 SwDoc* pDoc = getSwDoc();
1760 SwDocShell* pShell = pDoc->GetDocShell();
1762 // Dump the rendering of the first page as an XML file.
1763 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1764 MetafileXmlDump dumper;
1765 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1766 CPPUNIT_ASSERT(pXmlDoc);
1767 sal_Int32 nX2 = getXPath(pXmlDoc, "(//textarray)[2]", "x").toInt32(); // second data label
1768 sal_Int32 nX4 = getXPath(pXmlDoc, "(//textarray)[4]", "x").toInt32(); // fourth data label
1769 // Without the accompanying fix in place, this test would have failed with:
1770 // - Expected: 1229
1771 // - Actual : -225
1772 // - Delta : 100
1773 // i.e. the second data label appeared inside the pie slice.
1774 CPPUNIT_ASSERT_DOUBLES_EQUAL(1117, nX2 - nX4, 100);
1777 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf137154)
1779 createSwDoc("tdf137154.docx");
1780 SwDoc* pDoc = getSwDoc();
1781 SwDocShell* pShell = pDoc->GetDocShell();
1783 // Dump the rendering of the first page as an XML file.
1784 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1785 MetafileXmlDump dumper;
1786 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1787 CPPUNIT_ASSERT(pXmlDoc);
1788 sal_Int32 nX1 = getXPath(pXmlDoc, "(//textarray)[1]", "x").toInt32(); // first data label
1789 sal_Int32 nX4 = getXPath(pXmlDoc, "(//textarray)[4]", "x").toInt32(); // fourth data label
1790 // Without the accompanying fix in place, this test would have failed with:
1791 // - Expected: 10865
1792 // - Actual : 10252
1793 // - Delta : 50
1794 // i.e. the first data label appeared too close to the pie.
1795 CPPUNIT_ASSERT_DOUBLES_EQUAL(nX4, nX1, 50);
1798 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138777)
1800 createSwDoc("outside_long_data_label.docx");
1801 SwDoc* pDoc = getSwDoc();
1802 SwDocShell* pShell = pDoc->GetDocShell();
1804 // Dump the rendering of the first page as an XML file.
1805 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1806 MetafileXmlDump dumper;
1807 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1808 CPPUNIT_ASSERT(pXmlDoc);
1810 const sal_Int32 nFirstLabelLines
1811 = getXPathContent(pXmlDoc, "count(//text[contains(text(),\"really\")])").toInt32();
1813 // This failed, if the first data label didn't break to multiple lines.
1814 CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(1), nFirstLabelLines);
1817 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf130031)
1819 createSwDoc("tdf130031.docx");
1820 SwDoc* pDoc = getSwDoc();
1821 SwDocShell* pShell = pDoc->GetDocShell();
1823 // Dump the rendering of the first page as an XML file.
1824 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1825 MetafileXmlDump dumper;
1826 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1827 CPPUNIT_ASSERT(pXmlDoc);
1828 sal_Int32 nY = getXPath(pXmlDoc, "(//textarray)[11]", "y").toInt32();
1829 // Without the accompanying fix in place, this test would have failed with:
1830 // - Expected: 4653
1831 // - Actual : 2182
1832 // - Delta : 50
1833 // i.e. the data label appeared above the data point.
1834 CPPUNIT_ASSERT_DOUBLES_EQUAL(4653, nY, 50);
1837 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf130242)
1839 createSwDoc("tdf130242.odt");
1840 SwDoc* pDoc = getSwDoc();
1841 SwDocShell* pShell = pDoc->GetDocShell();
1843 // Dump the rendering of the first page as an XML file.
1844 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1845 MetafileXmlDump dumper;
1846 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1847 CPPUNIT_ASSERT(pXmlDoc);
1848 sal_Int32 nY = getXPath(pXmlDoc, "(//textarray)[11]", "y").toInt32();
1849 // Without the accompanying fix in place, this test would have failed with:
1850 // - Expected: 5758
1851 // - Actual : 3352
1852 // - Delta : 50
1853 // i.e. the data label appeared above the data point.
1854 CPPUNIT_ASSERT_DOUBLES_EQUAL(5758, nY, 50);
1856 nY = getXPath(pXmlDoc, "(//textarray)[13]", "y").toInt32();
1857 // Without the accompanying fix in place, this test would have failed with:
1858 // - Expected: 2335
1859 // - Actual : 2343
1860 // - Delta : 50
1861 // i.e. the data label appeared above the data point.
1862 CPPUNIT_ASSERT_DOUBLES_EQUAL(2335, nY, 50);
1865 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134121)
1867 createSwDoc("piechart_leaderline.odt");
1868 SwDoc* pDoc = getSwDoc();
1869 SwDocShell* pShell = pDoc->GetDocShell();
1871 // Dump the rendering of the first page as an XML file.
1872 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1873 MetafileXmlDump dumper;
1874 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1875 CPPUNIT_ASSERT(pXmlDoc);
1877 // Check the custom leader line on pie chart.
1878 assertXPath(pXmlDoc, "//polyline", 1);
1881 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf138018)
1883 createSwDoc("tdf138018.docx");
1884 SwDoc* pDoc = getSwDoc();
1885 SwDocShell* pShell = pDoc->GetDocShell();
1887 // Dump the rendering of the first page as an XML file.
1888 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1889 MetafileXmlDump dumper;
1890 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1891 CPPUNIT_ASSERT(pXmlDoc);
1892 // Without the accompanying fix in place, this test would have failed with:
1893 // - Expected: 2
1894 // - Actual : 3
1895 // i.e. the leader line was visible.
1896 assertXPath(pXmlDoc, "//polyline", 2);
1899 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf130380)
1901 createSwDoc("tdf130380.docx");
1902 SwDoc* pDoc = getSwDoc();
1903 SwDocShell* pShell = pDoc->GetDocShell();
1905 // Dump the rendering of the first page as an XML file.
1906 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1907 MetafileXmlDump dumper;
1908 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1909 CPPUNIT_ASSERT(pXmlDoc);
1910 sal_Int32 nY = getXPath(pXmlDoc,
1911 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[1]/polypolygon/"
1912 "polygon/point[1]",
1913 "y")
1914 .toInt32();
1915 // Without the accompanying fix in place, this test would have failed with:
1916 // - Expected: 6727
1917 // - Actual : 4411
1918 // - Delta : 50
1919 // i.e. the area chart shrank.
1920 CPPUNIT_ASSERT_DOUBLES_EQUAL(6727, nY, 50);
1923 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf129095)
1925 createSwDoc("tdf129095.docx");
1926 SwDoc* pDoc = getSwDoc();
1927 SwDocShell* pShell = pDoc->GetDocShell();
1929 // Dump the rendering of the first page as an XML file.
1930 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1931 MetafileXmlDump dumper;
1932 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1933 CPPUNIT_ASSERT(pXmlDoc);
1935 // check the inner chart area (relative size) visibility with testing the X axis label
1936 assertXPathContent(pXmlDoc, "//textarray/text", "Category 1");
1939 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf132956)
1941 createSwDoc("tdf132956.docx");
1942 SwDoc* pDoc = getSwDoc();
1943 SwDocShell* pShell = pDoc->GetDocShell();
1945 // Dump the rendering of the first page as an XML file.
1946 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1947 MetafileXmlDump dumper;
1948 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1949 CPPUNIT_ASSERT(pXmlDoc);
1951 // check the inner chart area (default size) visibility with testing the X axis label
1952 assertXPathContent(pXmlDoc, "//textarray/text", "Category 1");
1955 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf137819)
1957 // Open the bugdoc and check if it went wrong
1958 createSwDoc("tdf137819.fodt");
1959 SwDoc* pDoc = getSwDoc();
1960 CPPUNIT_ASSERT(pDoc);
1962 // Change the anchor if the textbox to As_char
1963 uno::Reference<beans::XPropertySet> xShapePropSet(getShape(1), uno::UNO_QUERY);
1964 xShapePropSet->setPropertyValue(
1965 "AnchorType", uno::Any(text::TextContentAnchorType::TextContentAnchorType_AS_CHARACTER));
1967 // Make the layout xml dump after the change
1968 auto pXml = parseLayoutDump();
1969 auto sTextRightSidePosition
1970 = getXPath(pXml, "/root/page/body/txt[6]/anchored/fly/infos/bounds", "right");
1971 auto sShapeRightSidePosition
1972 = getXPath(pXml, "/root/page/body/txt[6]/anchored/SwAnchoredDrawObject/bounds", "right");
1973 // Before the textframe did not follow the shape, now it supposed to
1974 // so the right side of the shape must be greater than the right side of
1975 // textframe:
1976 CPPUNIT_ASSERT(sTextRightSidePosition.toInt32() < sShapeRightSidePosition.toInt32());
1979 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf122014)
1981 createSwDoc("tdf122014.docx");
1982 SwDoc* pDoc = getSwDoc();
1983 SwDocShell* pShell = pDoc->GetDocShell();
1985 // Dump the rendering of the first page as an XML file.
1986 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
1987 MetafileXmlDump dumper;
1988 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
1989 CPPUNIT_ASSERT(pXmlDoc);
1991 // This failed, if the chart title is aligned to left.
1992 sal_Int32 nX1 = getXPath(pXmlDoc, "(//textarray)[13]", "x").toInt32();
1993 sal_Int32 nX2 = getXPath(pXmlDoc, "(//textarray)[14]", "x").toInt32();
1994 CPPUNIT_ASSERT_GREATER(nX1 + 100, nX2);
1997 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134659)
1999 createSwDoc("tdf134659.docx");
2000 SwDoc* pDoc = getSwDoc();
2001 SwDocShell* pShell = pDoc->GetDocShell();
2003 // Dump the rendering of the first page as an XML file.
2004 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2005 MetafileXmlDump dumper;
2006 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2007 CPPUNIT_ASSERT(pXmlDoc);
2009 // This failed, if the axis label is aligned to left.
2010 sal_Int32 nX1 = getXPath(pXmlDoc, "(//textarray)[1]", "x").toInt32();
2011 sal_Int32 nX2 = getXPath(pXmlDoc, "(//textarray)[2]", "x").toInt32();
2012 CPPUNIT_ASSERT_GREATER(nX1 + 250, nX2);
2015 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134235)
2017 createSwDoc("tdf134235.docx");
2018 SwDoc* pDoc = getSwDoc();
2019 SwDocShell* pShell = pDoc->GetDocShell();
2021 // Dump the rendering of the first page as an XML file.
2022 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2023 MetafileXmlDump dumper;
2024 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2025 CPPUNIT_ASSERT(pXmlDoc);
2026 // Without the accompanying fix in place, this test would have failed with:
2027 // - Expected: 14
2028 // - Actual : 13
2029 // i.e. the chart title flowed out of chart area.
2030 assertXPath(pXmlDoc, "//textarray", 14);
2033 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134676)
2035 createSwDoc("tdf134676.docx");
2036 SwDoc* pDoc = getSwDoc();
2037 SwDocShell* pShell = pDoc->GetDocShell();
2039 // Dump the rendering of the first page as an XML file.
2040 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2041 MetafileXmlDump dumper;
2042 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2043 CPPUNIT_ASSERT(pXmlDoc);
2044 // Without the accompanying fix in place, this test would have failed with:
2045 // - Expected: 14
2046 // - Actual : 13
2047 // i.e. the X axis title didn't break to multiple lines.
2048 assertXPath(pXmlDoc, "//textarray", 14);
2051 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134146)
2053 createSwDoc("tdf134146.docx");
2054 SwDoc* pDoc = getSwDoc();
2055 SwDocShell* pShell = pDoc->GetDocShell();
2057 // Dump the rendering of the first page as an XML file.
2058 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2059 MetafileXmlDump dumper;
2060 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2061 CPPUNIT_ASSERT(pXmlDoc);
2063 const sal_Int32 nTitleLines
2064 = getXPathContent(pXmlDoc, "count(//text[contains(text(),\"Horizontal\")])").toInt32();
2066 // Without the accompanying fix in place, this test would have failed.
2067 // i.e. the Y axis title didn't break to multiple lines.
2068 CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(1), nTitleLines);
2071 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf136061)
2073 createSwDoc("tdf136061.docx");
2074 SwDoc* pDoc = getSwDoc();
2075 SwDocShell* pShell = pDoc->GetDocShell();
2077 // Dump the rendering of the first page as an XML file.
2078 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2079 MetafileXmlDump dumper;
2080 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2081 CPPUNIT_ASSERT(pXmlDoc);
2082 // This failed, if the custom text of data label is missing.
2083 assertXPathContent(pXmlDoc, "(//textarray)[16]/text", "Customlabel");
2086 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116925)
2088 createSwDoc("tdf116925.docx");
2089 SwDoc* pDoc = getSwDoc();
2090 SwDocShell* pShell = pDoc->GetDocShell();
2092 // Dump the rendering of the first page as an XML file.
2093 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2094 MetafileXmlDump dumper;
2095 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2096 CPPUNIT_ASSERT(pXmlDoc);
2098 assertXPathContent(pXmlDoc,
2099 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[3]/textarray/text",
2100 "hello");
2101 // This failed, text color was #000000.
2102 assertXPath(
2103 pXmlDoc,
2104 "/metafile/push[1]/push[1]/push[1]/push[4]/push[1]/push[3]/textcolor[@color='#ffffff']", 1);
2107 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf117028)
2109 createSwDoc("tdf117028.docx");
2110 SwDoc* pDoc = getSwDoc();
2111 SwDocShell* pShell = pDoc->GetDocShell();
2113 // Dump the rendering of the first page as an XML file.
2114 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2115 MetafileXmlDump dumper;
2116 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2117 CPPUNIT_ASSERT(pXmlDoc);
2119 // The only polypolygon in the rendering result was the white background we
2120 // want to avoid.
2121 assertXPath(pXmlDoc, "//polypolygon", 0);
2123 // Make sure the text is still rendered.
2124 assertXPathContent(pXmlDoc, "//textarray/text", "Hello");
2127 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf106390)
2129 createSwDoc("tdf106390.odt");
2130 SwDoc* pDoc = getSwDoc();
2131 SwDocShell* pShell = pDoc->GetDocShell();
2133 // Dump the rendering of the first page as an XML file.
2134 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2135 MetafileXmlDump dumper;
2136 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2137 CPPUNIT_ASSERT(pXmlDoc);
2138 sal_Int32 nBottom = getXPath(pXmlDoc, "//sectrectclipregion", "bottom").toInt32();
2140 // No end point of line segments shall go below the bottom of the clipping area.
2141 const OString sXPath = "//polyline/point[@y>" + OString::number(nBottom) + "]";
2143 assertXPath(pXmlDoc, sXPath, 0);
2146 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTableExtrusion1)
2148 createSwDoc("table-extrusion1.odt");
2149 SwDoc* pDoc = getSwDoc();
2150 SwDocShell* pShell = pDoc->GetDocShell();
2152 // Dump the rendering of the first page as an XML file.
2153 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2154 MetafileXmlDump dumper;
2155 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2156 CPPUNIT_ASSERT(pXmlDoc);
2157 sal_Int32 nRight = getXPath(pXmlDoc, "//sectrectclipregion", "right").toInt32();
2158 sal_Int32 nLeft = static_cast<sal_Int32>(nRight * 0.95);
2160 // Expect table borders in right page margin.
2161 const OString sXPath = "//polyline/point[@x>" + OString::number(nLeft) + " and @x<"
2162 + OString::number(nRight) + "]";
2164 assertXPath(pXmlDoc, sXPath, 4);
2167 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTableExtrusion2)
2169 createSwDoc("table-extrusion2.odt");
2170 SwDoc* pDoc = getSwDoc();
2171 SwDocShell* pShell = pDoc->GetDocShell();
2173 // Dump the rendering of the first page as an XML file.
2174 std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
2175 MetafileXmlDump dumper;
2176 xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
2177 CPPUNIT_ASSERT(pXmlDoc);
2178 // End point position of the outer table.
2179 sal_Int32 nX = getXPath(pXmlDoc, "(//polyline[1]/point)[2]", "x").toInt32();
2181 // Do not allow inner table extrude outer table.
2182 const OString sXPath = "//polyline/point[@x>" + OString::number(nX) + "]";
2184 assertXPath(pXmlDoc, sXPath, 0);
2187 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf116848)
2189 createSwDoc("tdf116848.odt");
2190 SwDoc* pDoc = getSwDoc();
2191 // This resulted in a layout loop.
2192 pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout();
2195 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf117245)
2197 createSwDoc("tdf117245.odt");
2198 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2199 // This was 2, TabOverMargin did not use a single line when there was
2200 // enough space for the text.
2201 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout", 1);
2203 // This was 2, same problem elsewhere due to code duplication.
2204 assertXPath(pXmlDoc, "/root/page/body/txt[2]/SwParaPortion/SwLineLayout", 1);
2207 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf118672)
2209 createSwDoc("tdf118672.odt");
2210 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2212 // Check if we have hyphenation support, otherwise can't test SwHyphPortion.
2213 uno::Reference<linguistic2::XHyphenator> xHyphenator = LinguMgr::GetHyphenator();
2214 if (!xHyphenator->hasLocale(lang::Locale("en", "US", OUString())))
2215 return;
2217 // This ended as "fol*1 2 3 4 5 6 7 8 9", i.e. "10con-" was moved to the next line.
2218 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]", "portion",
2219 "He heard quiet steps behind him. That didn't bode well. Who could be fol*1 2 "
2220 "3 4 5 6 7 8 9 10con");
2221 assertXPath(pXmlDoc, "/root/page/body/txt[1]/SwParaPortion/SwLineLayout[2]", "portion",
2222 "setetur");
2225 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150200)
2227 createSwDoc("tdf150200.odt");
2228 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2229 // dash
2230 OUString sFirstLine
2231 = parseDump("/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]/@portion");
2232 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"-(dash)"));
2233 CPPUNIT_ASSERT_EQUAL(sal_Int32(93), sFirstLine.getLength());
2234 // en-dash
2235 sFirstLine = parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout[1]/@portion");
2236 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"–(en-dash)"));
2237 CPPUNIT_ASSERT_EQUAL(sal_Int32(88), sFirstLine.getLength());
2238 // em-dash
2239 sFirstLine = parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout[1]/@portion");
2240 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"—(em-dash)"));
2241 CPPUNIT_ASSERT_EQUAL(sal_Int32(77), sFirstLine.getLength());
2242 // figure dash
2243 sFirstLine = parseDump("/root/page/body/txt[4]/SwParaPortion/SwLineLayout[1]/@portion");
2244 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"‒(figure dash)"));
2245 CPPUNIT_ASSERT_EQUAL(sal_Int32(87), sFirstLine.getLength());
2248 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150200_DOCX)
2250 createSwDoc("tdf150200.docx");
2251 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2252 // dash
2253 OUString sFirstLine
2254 = parseDump("/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]/@portion");
2255 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"-(dash)"));
2256 CPPUNIT_ASSERT_EQUAL(sal_Int32(93), sFirstLine.getLength());
2257 // en-dash
2258 sFirstLine = parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout[1]/@portion");
2259 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"–(en-dash)"));
2260 CPPUNIT_ASSERT_EQUAL(sal_Int32(88), sFirstLine.getLength());
2261 // em-dash
2262 sFirstLine = parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout[1]/@portion");
2263 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"—(em-dash)"));
2264 CPPUNIT_ASSERT_EQUAL(sal_Int32(77), sFirstLine.getLength());
2265 // figure dash
2266 sFirstLine = parseDump("/root/page/body/txt[4]/SwParaPortion/SwLineLayout[1]/@portion");
2267 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"‒(figure dash)"));
2268 CPPUNIT_ASSERT_EQUAL(sal_Int32(87), sFirstLine.getLength());
2271 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150438)
2273 createSwDoc("tdf150438.odt");
2274 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2275 // left double quotation mark
2276 OUString sFirstLine
2277 = parseDump("/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]/@portion");
2278 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"“Lorem ipsum"));
2279 CPPUNIT_ASSERT_EQUAL(sal_Int32(92), sFirstLine.getLength());
2280 // right double quotation mark
2281 sFirstLine = parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout[1]/@portion");
2282 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"”Nunc viverra imperdiet enim."));
2283 CPPUNIT_ASSERT_EQUAL(sal_Int32(97), sFirstLine.getLength());
2284 // left single quotation mark
2285 sFirstLine = parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout[1]/@portion");
2286 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"‘Aenean nec lorem."));
2287 CPPUNIT_ASSERT_EQUAL(sal_Int32(85), sFirstLine.getLength());
2288 // right single quotation mark or apostrophe
2289 sFirstLine = parseDump("/root/page/body/txt[4]/SwParaPortion/SwLineLayout[1]/@portion");
2290 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"’Aenean nec lorem."));
2291 CPPUNIT_ASSERT_EQUAL(sal_Int32(85), sFirstLine.getLength());
2294 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150438_DOCX)
2296 createSwDoc("tdf150438.docx");
2297 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2298 // left double quotation mark
2299 OUString sFirstLine
2300 = parseDump("/root/page/body/txt[1]/SwParaPortion/SwLineLayout[1]/@portion");
2301 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"“Lorem ipsum"));
2302 CPPUNIT_ASSERT_EQUAL(sal_Int32(92), sFirstLine.getLength());
2303 // right double quotation mark
2304 sFirstLine = parseDump("/root/page/body/txt[2]/SwParaPortion/SwLineLayout[1]/@portion");
2305 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"”Nunc viverra imperdiet enim."));
2306 CPPUNIT_ASSERT_EQUAL(sal_Int32(97), sFirstLine.getLength());
2307 // left single quotation mark
2308 sFirstLine = parseDump("/root/page/body/txt[3]/SwParaPortion/SwLineLayout[1]/@portion");
2309 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"‘Aenean nec lorem."));
2310 CPPUNIT_ASSERT_EQUAL(sal_Int32(85), sFirstLine.getLength());
2311 // right single quotation mark or apostrophe
2312 sFirstLine = parseDump("/root/page/body/txt[4]/SwParaPortion/SwLineLayout[1]/@portion");
2313 CPPUNIT_ASSERT_EQUAL(true, sFirstLine.startsWith(u"’Aenean nec lorem."));
2314 CPPUNIT_ASSERT_EQUAL(sal_Int32(85), sFirstLine.getLength());
2317 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf117923)
2319 createSwDoc("tdf117923.doc");
2320 // Ensure that all text portions are calculated before testing.
2321 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
2322 CPPUNIT_ASSERT(pTextDoc);
2323 SwViewShell* pViewShell
2324 = pTextDoc->GetDocShell()->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
2325 CPPUNIT_ASSERT(pViewShell);
2326 pViewShell->Reformat();
2328 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2330 // Check that we actually test the line we need
2331 assertXPathContent(pXmlDoc, "/root/page/body/tab/row/cell/txt[3]", "GHI GHI GHI GHI");
2332 assertXPath(pXmlDoc,
2333 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion",
2334 "type", "PortionType::Number");
2335 assertXPath(pXmlDoc,
2336 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion",
2337 "expand", "2.");
2338 // The numbering height was 960.
2339 assertXPath(
2340 pXmlDoc,
2341 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion/SwFont",
2342 "height", "220");
2345 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf127606)
2347 createSwDoc("tdf117923.docx");
2348 // Ensure that all text portions are calculated before testing.
2349 SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
2350 CPPUNIT_ASSERT(pTextDoc);
2351 SwViewShell* pViewShell
2352 = pTextDoc->GetDocShell()->GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell();
2353 CPPUNIT_ASSERT(pViewShell);
2354 pViewShell->Reformat();
2356 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2358 // Check that we actually test the line we need
2359 assertXPathContent(pXmlDoc, "/root/page/body/tab/row/cell/txt[3]", "GHI GHI GHI GHI");
2360 assertXPath(pXmlDoc,
2361 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion",
2362 "type", "PortionType::Number");
2363 assertXPath(pXmlDoc,
2364 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion",
2365 "expand", "2.");
2366 // The numbering height was 960 in DOC format.
2367 assertXPath(
2368 pXmlDoc,
2369 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion/SwFont",
2370 "height", "220");
2372 // tdf#127606: now it's possible to change formatting of numbering
2373 // increase font size (220 -> 260)
2374 dispatchCommand(mxComponent, ".uno:SelectAll", {});
2375 dispatchCommand(mxComponent, ".uno:Grow", {});
2376 pViewShell->Reformat();
2377 discardDumpedLayout();
2378 pXmlDoc = parseLayoutDump();
2379 assertXPath(
2380 pXmlDoc,
2381 "/root/page/body/tab/row/cell/txt[3]/SwParaPortion/SwLineLayout/SwFieldPortion/SwFont",
2382 "height", "260");
2385 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf127118)
2387 createSwDoc("tdf127118.docx");
2388 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2389 // This was Horizontal: merged cell split between pages didn't keep vertical writing direction
2390 assertXPath(pXmlDoc, "/root/page[2]/body/tab/row[1]/cell[1]/txt[1]", "WritingMode", "VertBTLR");
2393 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf141220)
2395 createSwDoc("tdf141220.docx");
2397 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2398 sal_Int32 nShapeTop
2399 = getXPath(pXmlDoc, "//anchored/SwAnchoredDrawObject/bounds", "top").toInt32();
2400 sal_Int32 nTextBoxTop = getXPath(pXmlDoc, "//anchored/fly/infos/bounds", "top").toInt32();
2401 // Make sure the textbox stays inside the shape.
2402 CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(15), nTextBoxTop - nShapeTop);
2405 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, TestTextBoxChangeViaUNO)
2407 createSwDoc("TextBoxFrame.odt");
2408 // this file has a shape and a frame inside. Try to set up
2409 // the frame for the shape as textbox. Before this was not
2410 // implemented. This will be necessary for proper WPG import.
2412 CPPUNIT_ASSERT_EQUAL_MESSAGE("There must be a shape and a frame!", 2, getShapes());
2414 CPPUNIT_ASSERT_EQUAL_MESSAGE("This must be a custom shape!",
2415 OUString("com.sun.star.drawing.CustomShape"),
2416 getShape(1)->getShapeType());
2417 CPPUNIT_ASSERT_EQUAL_MESSAGE("This must be a frame shape!", OUString("FrameShape"),
2418 getShape(2)->getShapeType());
2420 CPPUNIT_ASSERT_MESSAGE("This is not supposed to be a textbox!",
2421 !uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
2422 ->getPropertyValue("TextBox")
2423 .get<bool>());
2424 // Without the fix it will crash at this line:
2425 CPPUNIT_ASSERT_MESSAGE("This is not supposed to be a textbox!",
2426 !uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
2427 ->getPropertyValue("TextBoxContent")
2428 .hasValue());
2430 // So now set the frame as textbox for the shape!
2431 uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
2432 ->setPropertyValue("TextBoxContent", uno::Any(uno::Reference<text::XTextFrame>(
2433 getShape(2), uno::UNO_QUERY_THROW)));
2435 CPPUNIT_ASSERT_MESSAGE("This is supposed to be a textbox!",
2436 uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
2437 ->getPropertyValue("TextBox")
2438 .get<bool>());
2440 CPPUNIT_ASSERT_MESSAGE("This is supposed to be a textbox!",
2441 uno::Reference<beans::XPropertySet>(getShape(1), uno::UNO_QUERY_THROW)
2442 ->getPropertyValue("TextBoxContent")
2443 .hasValue());
2446 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf121509)
2448 createSwDoc("Tdf121509.odt");
2449 auto pDoc = getSwDoc();
2450 CPPUNIT_ASSERT(pDoc);
2452 // Get all shape/frame formats
2453 auto vFrameFormats = pDoc->GetSpzFrameFormats();
2454 // Get the textbox
2455 auto xTextFrame = SwTextBoxHelper::getUnoTextFrame(getShape(1));
2456 // Get The triangle
2457 auto pTriangleShapeFormat = vFrameFormats->GetFormat(2);
2458 CPPUNIT_ASSERT(xTextFrame);
2459 CPPUNIT_ASSERT(pTriangleShapeFormat);
2461 // Get the position inside the textbox
2462 auto xTextContentStart = xTextFrame->getText()->getStart();
2463 SwUnoInternalPaM aCursor(*pDoc);
2464 CPPUNIT_ASSERT(sw::XTextRangeToSwPaM(aCursor, xTextContentStart));
2466 // Put the triangle into the textbox
2467 SwFormatAnchor aNewAnch(pTriangleShapeFormat->GetAnchor());
2468 aNewAnch.SetAnchor(aCursor.Start());
2469 CPPUNIT_ASSERT(pTriangleShapeFormat->SetFormatAttr(aNewAnch));
2471 // Reload (docx)
2472 // FIXME: if we use 'reload' here, it fails with
2473 // Assertion `!m_pFirst && !m_pLast && "There are still indices registered"' failed.
2474 save("Office Open XML Text");
2476 // The second part: check if the reloaded doc has flys inside a fly
2477 uno::Reference<lang::XComponent> xComponent
2478 = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument");
2479 uno::Reference<text::XTextDocument> xTextDoc(xComponent, uno::UNO_QUERY);
2480 auto pTextDoc = dynamic_cast<SwXTextDocument*>(xTextDoc.get());
2481 CPPUNIT_ASSERT(pTextDoc);
2482 auto pSecondDoc = pTextDoc->GetDocShell()->GetDoc();
2483 auto pSecondFormats = pSecondDoc->GetSpzFrameFormats();
2485 bool bFlyInFlyFound = false;
2486 for (auto secondformat : *pSecondFormats)
2488 const SwNode* pNd = secondformat->GetAnchor().GetAnchorNode();
2489 if (pNd->FindFlyStartNode())
2491 // So there is a fly inside another -> problem.
2492 bFlyInFlyFound = true;
2493 break;
2496 // Drop the tempfile
2497 maTempFile.CloseStream();
2499 // With the fix this cannot be true, if it is, that means Word unable to read the file..
2500 CPPUNIT_ASSERT_MESSAGE("Corrupt exported docx file!", !bFlyInFlyFound);
2503 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf134685)
2505 createSwDoc("tdf134685.docx");
2506 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2507 sal_Int32 nWidth
2508 = getXPath(pXmlDoc, "/root/page/body/tab/row[6]/cell[1]/infos/bounds", "width").toInt32();
2509 // This was 2223: the content was only partially visible according to the lost cell width
2510 CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(14000), nWidth);
2513 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf109077)
2515 createSwDoc("tdf109077.docx");
2516 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2517 sal_Int32 nShapeTop
2518 = getXPath(pXmlDoc, "//anchored/SwAnchoredDrawObject/bounds", "top").toInt32();
2519 sal_Int32 nTextBoxTop = getXPath(pXmlDoc, "//anchored/fly/infos/bounds", "top").toInt32();
2520 // This was 281: the top of the shape and its textbox should match, though
2521 // tolerate differences <= 1px (about 15 twips).
2522 CPPUNIT_ASSERT_LESS(static_cast<sal_Int32>(15), nTextBoxTop - nShapeTop);
2525 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testUserFieldTypeLanguage)
2527 // Set the system locale to German, the document will be English.
2528 SvtSysLocaleOptions aOptions;
2529 OUString sLocaleConfigString = aOptions.GetLanguageTag().getBcp47();
2530 aOptions.SetLocaleConfigString("de-DE");
2531 aOptions.Commit();
2532 comphelper::ScopeGuard g1([&aOptions, &sLocaleConfigString] {
2533 aOptions.SetLocaleConfigString(sLocaleConfigString);
2534 aOptions.Commit();
2537 createSwDoc("user-field-type-language.fodt");
2538 SwDoc* pDoc = getSwDoc();
2539 SwViewShell* pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
2540 pViewShell->UpdateFields();
2541 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2542 // This was "123,456.00", via a buggy 1234.56 -> 1234,56 -> 123456 ->
2543 // 123,456.00 transform chain.
2544 assertXPath(
2545 pXmlDoc,
2546 "/root/page/body/txt/SwParaPortion/SwLineLayout/SwFieldPortion[@type='PortionType::Field']",
2547 "expand", "1,234.56");
2549 discardDumpedLayout();
2550 // Now change the system locale to English (before this was failing, 1234,56 -> 0.00)
2551 aOptions.SetLocaleConfigString("en-GB");
2552 aOptions.Commit();
2553 comphelper::ScopeGuard g2([&aOptions, &sLocaleConfigString] {
2554 aOptions.SetLocaleConfigString(sLocaleConfigString);
2555 aOptions.Commit();
2557 pViewShell->UpdateFields();
2558 pXmlDoc = parseLayoutDump();
2559 // We expect, that the field value is not changed. Otherwise there is a problem:
2560 assertXPath(
2561 pXmlDoc,
2562 "/root/page/body/txt/SwParaPortion/SwLineLayout/SwFieldPortion[@type='PortionType::Field']",
2563 "expand", "1,234.56");
2564 discardDumpedLayout();
2565 // Now change the system locale to German
2566 aOptions.SetLocaleConfigString("de-DE");
2567 aOptions.Commit();
2568 comphelper::ScopeGuard g3([&aOptions, &sLocaleConfigString] {
2569 aOptions.SetLocaleConfigString(sLocaleConfigString);
2570 aOptions.Commit();
2572 pViewShell->UpdateFields();
2573 pXmlDoc = parseLayoutDump();
2574 // We expect, that the field value is not changed. Otherwise there is a problem:
2575 assertXPath(
2576 pXmlDoc,
2577 "/root/page/body/txt/SwParaPortion/SwLineLayout/SwFieldPortion[@type='PortionType::Field']",
2578 "expand", "1,234.56");
2581 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf124261)
2583 #if !defined(_WIN32) && !defined(MACOSX)
2584 // Make sure that pressing a key in a btlr cell frame causes an immediate, correct repaint.
2585 createSwDoc("tdf124261.docx");
2586 SwDoc* pDoc = getSwDoc();
2587 SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
2588 SwFrame* pPageFrame = pLayout->GetLower();
2589 CPPUNIT_ASSERT(pPageFrame->IsPageFrame());
2591 SwFrame* pBodyFrame = pPageFrame->GetLower();
2592 CPPUNIT_ASSERT(pBodyFrame->IsBodyFrame());
2594 SwFrame* pTabFrame = pBodyFrame->GetLower();
2595 CPPUNIT_ASSERT(pTabFrame->IsTabFrame());
2597 SwFrame* pRowFrame = pTabFrame->GetLower();
2598 CPPUNIT_ASSERT(pRowFrame->IsRowFrame());
2600 SwFrame* pCellFrame = pRowFrame->GetLower();
2601 CPPUNIT_ASSERT(pCellFrame->IsCellFrame());
2603 SwFrame* pFrame = pCellFrame->GetLower();
2604 CPPUNIT_ASSERT(pFrame->IsTextFrame());
2606 // Make sure that the text frame's area and the paint rectangle match.
2607 // Without the accompanying fix in place, this test would have failed with 'Expected: 1721;
2608 // Actual: 1547', i.e. an area other than the text frame was invalidated for a single-line
2609 // paragraph.
2610 SwTextFrame* pTextFrame = static_cast<SwTextFrame*>(pFrame);
2611 SwRect aRect = pTextFrame->GetPaintSwRect();
2612 CPPUNIT_ASSERT_EQUAL(pTextFrame->getFrameArea().Top(), aRect.Top());
2613 #endif
2616 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf135991)
2618 createSwDoc("tdf135991.odt");
2619 auto pDump = parseLayoutDump();
2620 // There used to be negative values that made the column frames invisible.
2621 assertXPath(pDump, "//bounds[@top<0]", 0);
2624 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf150642)
2626 createSwDoc("tdf150642.odt");
2627 auto pDump = parseLayoutDump();
2628 // There used to be negative values that made the cell frame invisible.
2629 assertXPath(pDump, "//bounds[@left<0]", 0);
2630 assertXPath(pDump, "//bounds[@right<0]", 0);
2633 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf152085)
2635 createSwDoc("tdf152085-section-tblr.odt");
2636 auto pDump = parseLayoutDump();
2637 sal_Int32 nSectionHeight
2638 = getXPath(pDump, "//section/infos/bounds", "bottom").toInt32(); // was 8391
2639 sal_Int32 nColumnHeight
2640 = getXPath(pDump, "(//column/infos/bounds)[2]", "bottom").toInt32(); // was 16216
2641 CPPUNIT_ASSERT_MESSAGE("The column in a TBRL page should be shorter than the section.",
2642 nColumnHeight <= nSectionHeight);
2645 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf152031)
2647 createSwDoc("tdf152031-stair.odt");
2649 // reproduce the bug by shrinking the table width.
2650 uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
2651 uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
2652 uno::UNO_QUERY);
2653 uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
2654 // Shrink table width from 5" to 4"
2655 sal_Int32 nWidth = getProperty<sal_Int32>(xTable, "Width") * 4 / 5;
2657 uno::Reference<beans::XPropertySet> xSet(xTable, uno::UNO_QUERY);
2658 xSet->setPropertyValue("Width", uno::Any(nWidth));
2660 auto pDump = parseLayoutDump();
2661 // There was a stair effect after change the table size.
2662 sal_Int32 nLeft_Row1 = getXPath(pDump, "(//row/infos/bounds)[1]", "left").toInt32();
2663 sal_Int32 nLeft_Row2 = getXPath(pDump, "(//row/infos/bounds)[2]", "left").toInt32();
2664 CPPUNIT_ASSERT_EQUAL_MESSAGE("left values of SwRowFrames should be consistent.", nLeft_Row1,
2665 nLeft_Row2);
2668 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf153136)
2670 createSwDoc("tdf153136.docx");
2671 xmlDocUniquePtr pXmlDoc = parseLayoutDump();
2673 const sal_Int32 small = 300; // Small-height lines are around 276 twip
2674 const sal_Int32 large = 1000; // Large-height lines are 1104 twip or more
2676 // Page 1: standalone paragraphs
2678 // U+0009 CHARACTER TABULATION: height is ignored
2679 sal_Int32 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[1]", "height").toInt32();
2680 CPPUNIT_ASSERT_LESS(small, height);
2682 // U+0020 SPACE: height is ignored
2683 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[2]", "height").toInt32();
2684 CPPUNIT_ASSERT_LESS(small, height);
2686 // U+00A0 NO-BREAK SPACE: height is considered
2687 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[3]", "height").toInt32();
2688 CPPUNIT_ASSERT_GREATER(large, height);
2690 // U+1680 OGHAM SPACE MARK: height is considered; not tested, because Liberation Serif lacks it
2692 // U+2000 EN QUAD: height is considered
2693 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[4]", "height").toInt32();
2694 CPPUNIT_ASSERT_GREATER(large, height);
2696 // U+2001 EM QUAD: height is considered
2697 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[5]", "height").toInt32();
2698 CPPUNIT_ASSERT_GREATER(large, height);
2700 // U+2002 EN SPACE: height is ignored
2701 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[6]", "height").toInt32();
2702 CPPUNIT_ASSERT_LESS(small, height);
2704 // U+2003 EM SPACE: height is ignored
2705 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[7]", "height").toInt32();
2706 CPPUNIT_ASSERT_LESS(small, height);
2708 // U+2004 THREE-PER-EM SPACE: height is considered
2709 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[8]", "height").toInt32();
2710 CPPUNIT_ASSERT_GREATER(large, height);
2712 // U+2005 FOUR-PER-EM SPACE: height is ignored
2713 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[9]", "height").toInt32();
2714 CPPUNIT_ASSERT_LESS(small, height);
2716 // U+2006 SIX-PER-EM SPACE: height is considered
2717 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[10]", "height").toInt32();
2718 CPPUNIT_ASSERT_GREATER(large, height);
2720 // U+2007 FIGURE SPACE: height is considered
2721 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[11]", "height").toInt32();
2722 CPPUNIT_ASSERT_GREATER(large, height);
2724 // U+2008 PUNCTUATION SPACE: height is considered
2725 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[12]", "height").toInt32();
2726 CPPUNIT_ASSERT_GREATER(large, height);
2728 // U+2009 THIN SPACE: height is considered
2729 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[13]", "height").toInt32();
2730 CPPUNIT_ASSERT_GREATER(large, height);
2732 // U+200A HAIR SPACE: height is considered
2733 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[14]", "height").toInt32();
2734 CPPUNIT_ASSERT_GREATER(large, height);
2736 // U+202F NARROW NO-BREAK SPACE: height is considered
2737 height = getXPath(pXmlDoc, "(/root/page[1]//SwLineLayout)[15]", "height").toInt32();
2738 CPPUNIT_ASSERT_GREATER(large, height);
2740 // U+205F MEDIUM MATHEMATICAL SPACE: height is considered; not tested, because Liberation Serif lacks it
2741 // U+3000 IDEOGRAPHIC SPACE: height is ignored; not tested, because Liberation Serif lacks it
2743 // Page 2: table rows (no paragraph-level size DF)
2745 // U+0020 SPACE: height is ignored
2746 height = getXPath(pXmlDoc, "(/root/page[2]//row)[1]/infos/bounds", "height").toInt32();
2747 CPPUNIT_ASSERT_LESS(small, height);
2749 // U+00A0 NO-BREAK SPACE: height is considered (1104 or so)
2750 height = getXPath(pXmlDoc, "(/root/page[2]//row)[2]/infos/bounds", "height").toInt32();
2751 CPPUNIT_ASSERT_GREATER(large, height);
2753 // U+1680 OGHAM SPACE MARK: height is considered; not tested, because Liberation Serif lacks it
2755 // U+2000 EN QUAD: height is considered
2756 height = getXPath(pXmlDoc, "(/root/page[2]//row)[3]/infos/bounds", "height").toInt32();
2757 CPPUNIT_ASSERT_GREATER(large, height);
2759 // U+2001 EM QUAD: height is considered
2760 height = getXPath(pXmlDoc, "(/root/page[2]//row)[4]/infos/bounds", "height").toInt32();
2761 CPPUNIT_ASSERT_GREATER(large, height);
2763 // U+2002 EN SPACE: height is ignored
2764 height = getXPath(pXmlDoc, "(/root/page[2]//row)[5]/infos/bounds", "height").toInt32();
2765 CPPUNIT_ASSERT_LESS(small, height);
2767 // U+2003 EM SPACE: height is ignored
2768 height = getXPath(pXmlDoc, "(/root/page[2]//row)[6]/infos/bounds", "height").toInt32();
2769 CPPUNIT_ASSERT_LESS(small, height);
2771 // U+2004 THREE-PER-EM SPACE: height is considered
2772 height = getXPath(pXmlDoc, "(/root/page[2]//row)[7]/infos/bounds", "height").toInt32();
2773 CPPUNIT_ASSERT_GREATER(large, height);
2775 // U+2005 FOUR-PER-EM SPACE: height is ignored
2776 height = getXPath(pXmlDoc, "(/root/page[2]//row)[8]/infos/bounds", "height").toInt32();
2777 CPPUNIT_ASSERT_LESS(small, height);
2779 // U+2006 SIX-PER-EM SPACE: height is considered
2780 height = getXPath(pXmlDoc, "(/root/page[2]//row)[9]/infos/bounds", "height").toInt32();
2781 CPPUNIT_ASSERT_GREATER(large, height);
2783 // U+2007 FIGURE SPACE: height is considered
2784 height = getXPath(pXmlDoc, "(/root/page[2]//row)[10]/infos/bounds", "height").toInt32();
2785 CPPUNIT_ASSERT_GREATER(large, height);
2787 // U+2008 PUNCTUATION SPACE: height is considered
2788 height = getXPath(pXmlDoc, "(/root/page[2]//row)[11]/infos/bounds", "height").toInt32();
2789 CPPUNIT_ASSERT_GREATER(large, height);
2791 // U+2009 THIN SPACE: height is considered
2792 height = getXPath(pXmlDoc, "(/root/page[2]//row)[12]/infos/bounds", "height").toInt32();
2793 CPPUNIT_ASSERT_GREATER(large, height);
2795 // U+200A HAIR SPACE: height is considered
2796 height = getXPath(pXmlDoc, "(/root/page[2]//row)[13]/infos/bounds", "height").toInt32();
2797 CPPUNIT_ASSERT_GREATER(large, height);
2799 // U+202F NARROW NO-BREAK SPACE: height is considered
2800 height = getXPath(pXmlDoc, "(/root/page[2]//row)[14]/infos/bounds", "height").toInt32();
2801 CPPUNIT_ASSERT_GREATER(large, height);
2803 // U+205F MEDIUM MATHEMATICAL SPACE: height is considered; not tested, because Liberation Serif lacks it
2804 // U+3000 IDEOGRAPHIC SPACE: height is ignored; not tested, because Liberation Serif lacks it
2806 // TODO: page 3, with table having paragraphs with paragraph-level size DF;
2807 // all rows should have large height
2809 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[1]/infos/bounds", "height").toInt32();
2810 // CPPUNIT_ASSERT_GREATER(large, height);
2811 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[2]/infos/bounds", "height").toInt32();
2812 // CPPUNIT_ASSERT_GREATER(large, height);
2813 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[3]/infos/bounds", "height").toInt32();
2814 // CPPUNIT_ASSERT_GREATER(large, height);
2815 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[4]/infos/bounds", "height").toInt32();
2816 // CPPUNIT_ASSERT_GREATER(large, height);
2817 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[5]/infos/bounds", "height").toInt32();
2818 // CPPUNIT_ASSERT_GREATER(large, height);
2819 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[6]/infos/bounds", "height").toInt32();
2820 // CPPUNIT_ASSERT_GREATER(large, height);
2821 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[7]/infos/bounds", "height").toInt32();
2822 // CPPUNIT_ASSERT_GREATER(large, height);
2823 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[8]/infos/bounds", "height").toInt32();
2824 // CPPUNIT_ASSERT_GREATER(large, height);
2825 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[9]/infos/bounds", "height").toInt32();
2826 // CPPUNIT_ASSERT_GREATER(large, height);
2827 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[10]/infos/bounds", "height").toInt32();
2828 // CPPUNIT_ASSERT_GREATER(large, height);
2829 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[11]/infos/bounds", "height").toInt32();
2830 // CPPUNIT_ASSERT_GREATER(large, height);
2831 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[12]/infos/bounds", "height").toInt32();
2832 // CPPUNIT_ASSERT_GREATER(large, height);
2833 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[13]/infos/bounds", "height").toInt32();
2834 // CPPUNIT_ASSERT_GREATER(large, height);
2835 // height = getXPath(pXmlDoc, "(/root/page[3]//row)[14]/infos/bounds", "height").toInt32();
2836 // CPPUNIT_ASSERT_GREATER(large, height);
2839 CPPUNIT_PLUGIN_IMPLEMENT();
2841 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */