Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <swmodeltestbase.hxx>
11 :
12 : #include <com/sun/star/awt/XBitmap.hpp>
13 : #include <com/sun/star/graphic/XGraphic.hpp>
14 : #include <officecfg/Office/Common.hxx>
15 : #include <comphelper/processfactory.hxx>
16 : #include <unotxdoc.hxx>
17 : #include <docsh.hxx>
18 : #include <doc.hxx>
19 : #include <ndgrf.hxx>
20 : #include <drawdoc.hxx>
21 : #include <unotools/fltrcfg.hxx>
22 :
23 16 : class Test : public SwModelTestBase
24 : {
25 : public:
26 8 : Test() : SwModelTestBase() {}
27 :
28 : void testSwappedOutImageExport();
29 : void testLinkedGraphicRT();
30 : void testImageWithSpecialID();
31 : void testGraphicShape();
32 : void testCharHighlight();
33 : void testCharHighlightBody();
34 : void testMSCharBackgroundEditing();
35 : void testCharBackgroundToHighlighting();
36 : #if !defined(WNT)
37 : void testSkipImages();
38 : #endif
39 :
40 2 : CPPUNIT_TEST_SUITE(Test);
41 1 : CPPUNIT_TEST(testSwappedOutImageExport);
42 1 : CPPUNIT_TEST(testLinkedGraphicRT);
43 1 : CPPUNIT_TEST(testImageWithSpecialID);
44 1 : CPPUNIT_TEST(testGraphicShape);
45 1 : CPPUNIT_TEST(testCharHighlight);
46 1 : CPPUNIT_TEST(testMSCharBackgroundEditing);
47 1 : CPPUNIT_TEST(testCharBackgroundToHighlighting);
48 : #if !defined(WNT)
49 1 : CPPUNIT_TEST(testSkipImages);
50 : #endif
51 5 : CPPUNIT_TEST_SUITE_END();
52 : };
53 :
54 1 : void Test::testSwappedOutImageExport()
55 : {
56 : const char* aFilterNames[] = {
57 : "writer8",
58 : "Rich Text Format",
59 : "MS Word 97",
60 : "Office Open XML Text",
61 1 : };
62 :
63 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
64 : {
65 : // Check whether the export code swaps in the image which was swapped out before by auto mechanism
66 :
67 : // Set cache size to a very small value to make sure one of the images is swapped out
68 4 : std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
69 4 : officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(static_cast<sal_Int32>(1), batch);
70 4 : batch->commit();
71 :
72 4 : if (mxComponent.is())
73 3 : mxComponent->dispose();
74 4 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/document_with_two_images.odt"), "com.sun.star.text.TextDocument");
75 :
76 : // Export the document and import again for a check
77 8 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
78 :
79 8 : utl::MediaDescriptor aMediaDescriptor;
80 4 : aMediaDescriptor["FilterName"] <<= OUString::createFromAscii(aFilterNames[nFilter]);
81 :
82 8 : utl::TempFile aTempFile;
83 4 : aTempFile.EnableKillingFile();
84 4 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
85 8 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
86 4 : xComponent->dispose();
87 4 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
88 :
89 : // Check whether graphic exported well after it was swapped out
90 8 : uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
91 8 : uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
92 :
93 8 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
94 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
95 :
96 : // First image
97 8 : uno::Reference<drawing::XShape> xImage(xDraws->getByIndex(0), uno::UNO_QUERY);
98 8 : uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
99 : // Check URL
100 : {
101 4 : OUString sURL;
102 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
103 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
104 : }
105 : // Check size
106 : {
107 4 : uno::Reference<graphic::XGraphic> xGraphic;
108 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
109 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
110 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
111 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
112 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
113 : }
114 :
115 : // Second Image
116 4 : xImage.set(xDraws->getByIndex(1), uno::UNO_QUERY);
117 4 : XPropSet.set( xImage, uno::UNO_QUERY_THROW );
118 : // Check URL
119 : {
120 4 : OUString sURL;
121 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
122 8 : CPPUNIT_ASSERT_MESSAGE(
123 8 : sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
124 : }
125 : // Check size
126 : {
127 4 : uno::Reference<graphic::XGraphic> xGraphic;
128 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
129 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
130 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
131 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width );
132 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height );
133 : }
134 4 : }
135 1 : }
136 :
137 1 : void Test::testLinkedGraphicRT()
138 : {
139 : const std::vector<OUString> aFilterNames = {
140 : "writer8",
141 : // "Rich Text Format", Note: picture is there, but SwGrfNode is not found?
142 : "MS Word 97",
143 : "Office Open XML Text",
144 1 : };
145 :
146 4 : for( size_t nFilter = 0; nFilter < aFilterNames.size(); ++nFilter )
147 : {
148 3 : if (mxComponent.is())
149 2 : mxComponent->dispose();
150 3 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/document_with_linked_graphic.odt"), "com.sun.star.text.TextDocument");
151 :
152 : const OString sFailedMessage = OString("Failed on filter: ")
153 3 : + OUStringToOString(aFilterNames[nFilter], RTL_TEXTENCODING_ASCII_US);
154 :
155 :
156 : // Export the document and import again for a check
157 6 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
158 :
159 6 : utl::MediaDescriptor aMediaDescriptor;
160 3 : aMediaDescriptor["FilterName"] <<= aFilterNames[nFilter];
161 :
162 6 : utl::TempFile aTempFile;
163 3 : aTempFile.EnableKillingFile();
164 3 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
165 6 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
166 3 : xComponent->dispose();
167 3 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
168 :
169 3 : SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
170 3 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
171 3 : SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
172 3 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pDoc);
173 3 : SwNodes& aNodes = pDoc->GetNodes();
174 :
175 : // Find the image
176 3 : bool bImageFound = false;
177 45 : for( sal_uLong nIndex = 0; nIndex < aNodes.Count(); ++nIndex)
178 : {
179 42 : if( aNodes[nIndex]->IsGrfNode() )
180 : {
181 3 : SwGrfNode* pGrfNode = aNodes[nIndex]->GetGrfNode();
182 3 : CPPUNIT_ASSERT(pGrfNode);
183 : // RT via DOCX makes linked graphic embedded?!
184 3 : if( aFilterNames[nFilter] != "Office Open XML Text" )
185 : {
186 2 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), pGrfNode->IsGrfLink());
187 : }
188 3 : const GraphicObject& rGraphicObj = pGrfNode->GetGrfObj(true);
189 3 : CPPUNIT_ASSERT_MESSAGE( sFailedMessage.getStr(), !rGraphicObj.IsSwappedOut());
190 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), GRAPHIC_BITMAP, rGraphicObj.GetType());
191 3 : CPPUNIT_ASSERT_EQUAL_MESSAGE( sFailedMessage.getStr(), static_cast<sal_uLong>(864900), rGraphicObj.GetSizeBytes());
192 3 : bImageFound = true;
193 : }
194 : }
195 3 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), bImageFound);
196 4 : }
197 1 : }
198 :
199 1 : void Test::testImageWithSpecialID()
200 : {
201 : // Check how LO handles when the imported graphic's ID is different from that one
202 : // which is generated by LO.
203 :
204 : const char* aFilterNames[] = {
205 : "writer8",
206 : "Rich Text Format",
207 : "MS Word 97",
208 : "Office Open XML Text",
209 1 : };
210 :
211 : // Trigger swap out mechanism to test swapped state factor too.
212 1 : std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
213 1 : officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(static_cast<sal_Int32>(1), batch);
214 1 : batch->commit();
215 :
216 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
217 : {
218 4 : if (mxComponent.is())
219 3 : mxComponent->dispose();
220 4 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/images_with_special_IDs.odt"), "com.sun.star.text.TextDocument");
221 :
222 : // Export the document and import again for a check
223 4 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
224 :
225 8 : utl::MediaDescriptor aMediaDescriptor;
226 4 : aMediaDescriptor["FilterName"] <<= OUString::createFromAscii(aFilterNames[nFilter]);
227 :
228 8 : utl::TempFile aTempFile;
229 4 : aTempFile.EnableKillingFile();
230 4 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
231 8 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
232 4 : xComponent->dispose();
233 4 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
234 :
235 : // Check whether graphic exported well
236 8 : uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
237 8 : uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
238 :
239 8 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
240 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
241 :
242 8 : uno::Reference<drawing::XShape> xImage = getShape(1);
243 8 : uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
244 : // Check URL
245 : {
246 4 : OUString sURL;
247 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
248 4 : CPPUNIT_ASSERT(sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
249 : }
250 : // Check size
251 : {
252 4 : uno::Reference<graphic::XGraphic> xGraphic;
253 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
254 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
255 4 : CPPUNIT_ASSERT(xBitmap.is());
256 4 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(610), xBitmap->getSize().Width );
257 8 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(381), xBitmap->getSize().Height );
258 : }
259 : // Second Image
260 4 : xImage = getShape(2);
261 4 : XPropSet.set( xImage, uno::UNO_QUERY_THROW );
262 : // Check URL
263 : {
264 4 : OUString sURL;
265 4 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
266 4 : CPPUNIT_ASSERT(sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
267 : }
268 : // Check size
269 : {
270 4 : uno::Reference<graphic::XGraphic> xGraphic;
271 4 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
272 8 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
273 4 : CPPUNIT_ASSERT(xBitmap.is());
274 4 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(900), xBitmap->getSize().Width );
275 8 : CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(600), xBitmap->getSize().Height );
276 : }
277 5 : }
278 1 : }
279 :
280 1 : void Test::testGraphicShape()
281 : {
282 : // There are two kind of images in Writer: 1) Writer specific handled by SwGrfNode and
283 : // 2) graphic shape handled by SdrGrafObj (e.g. after copy&paste from Impress).
284 :
285 : const char* aFilterNames[] = {
286 : "writer8",
287 : "Rich Text Format",
288 : "MS Word 97",
289 : "Office Open XML Text",
290 1 : };
291 :
292 : // Trigger swap out mechanism to test swapped state factor too.
293 1 : std::shared_ptr< comphelper::ConfigurationChanges > batch(comphelper::ConfigurationChanges::create());
294 1 : officecfg::Office::Common::Cache::GraphicManager::TotalCacheSize::set(static_cast<sal_Int32>(1), batch);
295 1 : batch->commit();
296 :
297 2 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
298 : {
299 2 : if (mxComponent.is())
300 1 : mxComponent->dispose();
301 2 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/graphic_shape.odt"), "com.sun.star.text.TextDocument");
302 :
303 : // Export the document and import again for a check
304 2 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
305 :
306 3 : utl::MediaDescriptor aMediaDescriptor;
307 2 : aMediaDescriptor["FilterName"] <<= OUString::createFromAscii(aFilterNames[nFilter]);
308 :
309 3 : utl::TempFile aTempFile;
310 2 : aTempFile.EnableKillingFile();
311 2 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
312 3 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
313 2 : xComponent->dispose();
314 2 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
315 :
316 : // Check whether graphic exported well
317 3 : uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
318 3 : uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
319 :
320 3 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
321 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(2), xDraws->getCount());
322 :
323 3 : uno::Reference<drawing::XShape> xImage = getShape(1);
324 3 : uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
325 : // First image is embedded
326 : // Check URL
327 : {
328 2 : OUString sURL;
329 2 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
330 2 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL != "vnd.sun.star.GraphicObject:00000000000000000000000000000000");
331 : }
332 : // Check size
333 : {
334 2 : uno::Reference<graphic::XGraphic> xGraphic;
335 2 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
336 4 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
337 2 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
338 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
339 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
340 : }
341 :
342 : // MS filters make this kind of linked images broken !?
343 2 : if( OUString::createFromAscii(aFilterNames[nFilter]) != "writer8" )
344 2 : return;
345 :
346 : // Second image is a linked one
347 1 : xImage = getShape(2);
348 1 : XPropSet.set( xImage, uno::UNO_QUERY_THROW );
349 : // Check URL
350 : {
351 1 : OUString sURL;
352 1 : XPropSet->getPropertyValue("GraphicURL") >>= sURL;
353 1 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL.endsWith("linked_graphic.jpg"));
354 : }
355 : // Check size
356 : {
357 1 : uno::Reference<graphic::XGraphic> xGraphic;
358 1 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
359 2 : uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
360 1 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
361 1 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(620), xBitmap->getSize().Width );
362 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(465), xBitmap->getSize().Height );
363 : }
364 1 : }
365 : }
366 :
367 2 : void Test::testCharHighlightBody()
368 : {
369 : // MS Word has two kind of character backgrounds called character shading and highlighting
370 : // MS filters handle these attributes separately, but ODF export merges them into one background attribute
371 :
372 : const char* aFilterNames[] = {
373 : "writer8",
374 : "Rich Text Format",
375 : "MS Word 97",
376 : "Office Open XML Text",
377 2 : };
378 :
379 10 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
380 : {
381 8 : if (mxComponent.is())
382 7 : mxComponent->dispose();
383 16 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/char_highlight.docx"),
384 8 : "com.sun.star.text.TextDocument");
385 :
386 8 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
387 :
388 : // Export the document and import again for a check
389 16 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
390 :
391 16 : utl::MediaDescriptor aMediaDescriptor;
392 8 : aMediaDescriptor["FilterName"] <<= OUString::createFromAscii(aFilterNames[nFilter]);
393 :
394 16 : utl::TempFile aTempFile;
395 8 : aTempFile.EnableKillingFile();
396 8 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
397 16 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
398 8 : xComponent->dispose();
399 8 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
400 :
401 16 : const uno::Reference< text::XTextRange > xPara = getParagraph(1);
402 : // Both highlight and background
403 8 : const sal_Int32 nBackColor(0x4F81BD);
404 136 : for( int nRun = 1; nRun <= 16; ++nRun )
405 : {
406 128 : const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,nRun), uno::UNO_QUERY);
407 128 : sal_Int32 nHighlightColor = 0;
408 128 : switch( nRun )
409 : {
410 8 : case 1: nHighlightColor = 0x000000; break; //black
411 8 : case 2: nHighlightColor = 0x0000ff; break; //blue
412 8 : case 3: nHighlightColor = 0x00ffff; break; //cyan
413 8 : case 4: nHighlightColor = 0x00ff00; break; //green
414 8 : case 5: nHighlightColor = 0xff00ff; break; //magenta
415 8 : case 6: nHighlightColor = 0xff0000; break; //red
416 8 : case 7: nHighlightColor = 0xffff00; break; //yellow
417 8 : case 8: nHighlightColor = 0xffffff; break; //white
418 8 : case 9: nHighlightColor = 0x000080; break;//dark blue
419 8 : case 10: nHighlightColor = 0x008080; break; //dark cyan
420 8 : case 11: nHighlightColor = 0x008000; break; //dark green
421 8 : case 12: nHighlightColor = 0x800080; break; //dark magenta
422 8 : case 13: nHighlightColor = 0x800000; break; //dark red
423 8 : case 14: nHighlightColor = 0x808000; break; //dark yellow
424 8 : case 15: nHighlightColor = 0x808080; break; //dark gray
425 8 : case 16: nHighlightColor = 0xC0C0C0; break; //light gray
426 : }
427 :
428 128 : if( strcmp(aFilterNames[nFilter], "writer8") == 0 )
429 : {
430 32 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharHighlight"));
431 32 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nHighlightColor, getProperty<sal_Int32>(xRun,"CharBackColor"));
432 : }
433 : else // MS filters
434 : {
435 96 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nHighlightColor, getProperty<sal_Int32>(xRun,"CharHighlight"));
436 96 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nBackColor, getProperty<sal_Int32>(xRun,"CharBackColor"));
437 : }
438 128 : }
439 :
440 : // Only highlight
441 : {
442 8 : const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,18), uno::UNO_QUERY);
443 8 : if( strcmp(aFilterNames[nFilter], "writer8") == 0 )
444 : {
445 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharHighlight"));
446 2 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0xff0000), getProperty<sal_Int32>(xRun,"CharBackColor"));
447 : }
448 : else
449 : {
450 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0xff0000), getProperty<sal_Int32>(xRun,"CharHighlight"));
451 6 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharBackColor"));
452 8 : }
453 : }
454 :
455 : // Only background
456 : {
457 8 : const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,19), uno::UNO_QUERY);
458 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharHighlight"));
459 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0x0000ff), getProperty<sal_Int32>(xRun,"CharBackColor"));
460 : }
461 8 : }
462 2 : }
463 :
464 1 : void Test::testCharHighlight()
465 : {
466 1 : SvtFilterOptions& rOpt = SvtFilterOptions::Get();
467 1 : rOpt.SetCharBackground2Shading();
468 :
469 1 : testCharHighlightBody();
470 :
471 1 : rOpt.SetCharBackground2Highlighting();
472 :
473 1 : testCharHighlightBody();
474 1 : }
475 :
476 1 : void Test::testMSCharBackgroundEditing()
477 : {
478 : // Simulate the editing process of imported MSO character background attributes
479 : // and check how export behaves.
480 :
481 : const char* aFilterNames[] = {
482 : "writer8",
483 : "Rich Text Format",
484 : "MS Word 97",
485 : "Office Open XML Text",
486 1 : };
487 :
488 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
489 : {
490 4 : if (mxComponent.is())
491 3 : mxComponent->dispose();
492 :
493 8 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/char_background_editing.docx"),
494 4 : "com.sun.star.text.TextDocument");
495 :
496 4 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
497 :
498 : // Check whether import was done on the right way
499 8 : uno::Reference< text::XTextRange > xPara = getParagraph(1);
500 : {
501 4 : uno::Reference<beans::XPropertySet> xRun(getRun(xPara,1), uno::UNO_QUERY);
502 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharHighlight"));
503 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0xff0000), getProperty<sal_Int32>(xRun,"CharBackColor"));
504 :
505 4 : xRun.set(getRun(xPara,2), uno::UNO_QUERY);
506 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0x0000ff), getProperty<sal_Int32>(xRun,"CharHighlight"));
507 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharBackColor"));
508 :
509 4 : xRun.set(getRun(xPara,3), uno::UNO_QUERY);
510 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0x0000ff), getProperty<sal_Int32>(xRun,"CharHighlight"));
511 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(0xff0000), getProperty<sal_Int32>(xRun,"CharBackColor"));
512 :
513 4 : xRun.set(getRun(xPara,4), uno::UNO_QUERY);
514 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharHighlight"));
515 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharBackColor"));
516 : }
517 :
518 : // Simulate editing
519 20 : for( int i = 1; i <= 4; ++i )
520 : {
521 16 : uno::Reference<beans::XPropertySet> xRun(getRun(xPara,i), uno::UNO_QUERY);
522 : // Change background
523 16 : sal_Int32 nBackColor = 0;
524 16 : switch( i )
525 : {
526 4 : case 1: nBackColor = 0x000000; break; //black
527 4 : case 2: nBackColor = 0x00ffff; break; //cyan
528 4 : case 3: nBackColor = 0x00ff00; break; //green
529 4 : case 4: nBackColor = 0xff00ff; break; //magenta
530 : }
531 16 : xRun->setPropertyValue("CharBackColor", uno::makeAny(static_cast<sal_Int32>(nBackColor)));
532 : // Remove highlighting
533 16 : xRun->setPropertyValue("CharHighlight", uno::makeAny(static_cast<sal_Int32>(COL_TRANSPARENT)));
534 : // Remove shading marker
535 16 : uno::Sequence<beans::PropertyValue> aGrabBag = getProperty<uno::Sequence<beans::PropertyValue> >(xRun,"CharInteropGrabBag");
536 80 : for (int j = 0; j < aGrabBag.getLength(); ++j)
537 : {
538 64 : beans::PropertyValue& rProp = aGrabBag[j];
539 64 : if (rProp.Name == "CharShadingMarker")
540 : {
541 8 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), true, rProp.Value.get<bool>());
542 8 : rProp.Value = uno::makeAny(false);
543 : }
544 : }
545 16 : xRun->setPropertyValue("CharInteropGrabBag", uno::makeAny(aGrabBag));
546 16 : }
547 :
548 4 : SvtFilterOptions& rOpt = SvtFilterOptions::Get();
549 4 : rOpt.SetCharBackground2Highlighting();
550 :
551 : // Export the document and import again for a check
552 4 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
553 :
554 8 : utl::MediaDescriptor aMediaDescriptor;
555 4 : aMediaDescriptor["FilterName"] <<= OUString::createFromAscii(aFilterNames[nFilter]);
556 :
557 8 : utl::TempFile aTempFile;
558 4 : aTempFile.EnableKillingFile();
559 4 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
560 8 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
561 4 : xComponent->dispose();
562 4 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
563 :
564 : // Check whether background was exported as highlighting
565 4 : xPara.set(getParagraph(1));
566 20 : for( int i = 1; i <= 4; ++i )
567 : {
568 16 : sal_Int32 nBackColor = 0;
569 16 : switch( i )
570 : {
571 4 : case 1: nBackColor = 0x000000; break; //black
572 4 : case 2: nBackColor = 0x00ffff; break; //cyan
573 4 : case 3: nBackColor = 0x00ff00; break; //green
574 4 : case 4: nBackColor = 0xff00ff; break; //magenta
575 : }
576 16 : const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,i), uno::UNO_QUERY);
577 16 : if( strcmp(aFilterNames[nFilter], "writer8") == 0 )
578 : {
579 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharHighlight"));
580 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(nBackColor), getProperty<sal_Int32>(xRun,"CharBackColor"));
581 : }
582 : else
583 : {
584 12 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(nBackColor), getProperty<sal_Int32>(xRun,"CharHighlight"));
585 12 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun,"CharBackColor"));
586 : }
587 16 : }
588 8 : }
589 1 : }
590 :
591 1 : void Test::testCharBackgroundToHighlighting()
592 : {
593 : // MSO highlighting has less kind of values so let's see how LO character background is converted
594 : // to these values
595 :
596 : const char* aFilterNames[] = {
597 : "Rich Text Format",
598 : "MS Word 97",
599 : "Office Open XML Text",
600 1 : };
601 :
602 4 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
603 : {
604 3 : if (mxComponent.is())
605 2 : mxComponent->dispose();
606 6 : mxComponent = loadFromDesktop(getURLFromSrc("/sw/qa/extras/globalfilter/data/char_background.odt"),
607 3 : "com.sun.star.text.TextDocument");
608 :
609 3 : const OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter];
610 :
611 :
612 3 : SvtFilterOptions& rOpt = SvtFilterOptions::Get();
613 3 : rOpt.SetCharBackground2Highlighting();
614 :
615 : // Export the document and import again for a check
616 6 : uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY);
617 :
618 6 : utl::MediaDescriptor aMediaDescriptor;
619 3 : aMediaDescriptor["FilterName"] <<= OUString::createFromAscii(aFilterNames[nFilter]);
620 :
621 6 : utl::TempFile aTempFile;
622 3 : aTempFile.EnableKillingFile();
623 3 : xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
624 6 : uno::Reference< lang::XComponent > xComponent(xStorable, uno::UNO_QUERY);
625 3 : xComponent->dispose();
626 3 : mxComponent = loadFromDesktop(aTempFile.GetURL(), "com.sun.star.text.TextDocument");
627 :
628 : // Check highlight color
629 6 : const uno::Reference< text::XTextRange > xPara = getParagraph(1);
630 63 : for( int nRun = 1; nRun <= 20; ++nRun )
631 : {
632 60 : const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,nRun), uno::UNO_QUERY);
633 60 : sal_Int32 nHighlightColor = 0;
634 60 : switch( nRun )
635 : {
636 3 : case 1: nHighlightColor = 0x000000; break; //black
637 3 : case 2: nHighlightColor = 0xffff00; break; //yellow
638 3 : case 3: nHighlightColor = 0xff00ff; break; //magenta
639 3 : case 4: nHighlightColor = 0x00ffff; break; //cyan
640 3 : case 5: nHighlightColor = 0xffff00; break; //yellow
641 3 : case 6: nHighlightColor = 0xff0000; break; //red
642 3 : case 7: nHighlightColor = 0x0000ff; break; //blue
643 3 : case 8: nHighlightColor = 0x00ff00; break; //green
644 3 : case 9: nHighlightColor = 0x008000; break; //dark green
645 3 : case 10: nHighlightColor = 0x800080; break; //dark magenta
646 3 : case 11: nHighlightColor = 0x000080; break; //dark blue
647 3 : case 12: nHighlightColor = 0x000000; break; //black
648 3 : case 13: nHighlightColor = 0x808000; break; //dark yellow
649 3 : case 14: nHighlightColor = 0x808080; break; //dark gray
650 3 : case 15: nHighlightColor = 0x000000; break; //white
651 3 : case 16: nHighlightColor = 0xff0000; break; //red
652 3 : case 17: nHighlightColor = 0xC0C0C0; break; //light gray
653 3 : case 18: nHighlightColor = 0x800000; break; //dark red
654 3 : case 19: nHighlightColor = 0x008080; break; //dark cyan
655 3 : case 20: nHighlightColor = 0xffffff; break; //white
656 : }
657 60 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nHighlightColor, getProperty<sal_Int32>(xRun,"CharHighlight"));
658 60 : }
659 3 : }
660 1 : }
661 :
662 : #if !defined(WNT)
663 1 : void Test::testSkipImages()
664 : {
665 : // Check how LO skips image loading (but not texts of textboxes and custom shapes)
666 : // during DOC and DOCX import, using the "SkipImages" FilterOptions.
667 :
668 : const char* aFilterNames[][2] = {
669 : { "/sw/qa/extras/globalfilter/data/skipimages.doc", NULL },
670 : { "/sw/qa/extras/globalfilter/data/skipimages.doc", "SkipImages" },
671 : { "/sw/qa/extras/globalfilter/data/skipimages.docx", NULL },
672 : { "/sw/qa/extras/globalfilter/data/skipimages.docx", "SkipImages" }
673 1 : };
674 :
675 5 : for( size_t nFilter = 0; nFilter < SAL_N_ELEMENTS(aFilterNames); ++nFilter )
676 : {
677 4 : bool bSkipImages = aFilterNames[nFilter][1] != NULL;
678 4 : OString sFailedMessage = OString("Failed on filter: ") + aFilterNames[nFilter][0];
679 :
680 4 : if (mxComponent.is())
681 3 : mxComponent->dispose();
682 :
683 4 : if (bSkipImages)
684 : {
685 : // FilterOptions parameter
686 2 : uno::Sequence<beans::PropertyValue> args(1);
687 2 : args[0].Name = "FilterOptions";
688 2 : args[0].Handle = -1;
689 2 : args[0].Value <<= OUString::createFromAscii(aFilterNames[nFilter][1]);
690 2 : args[0].State = beans::PropertyState_DIRECT_VALUE;
691 2 : mxComponent = loadFromDesktop(getURLFromSrc(aFilterNames[nFilter][0]), "com.sun.star.text.TextDocument", args);
692 2 : sFailedMessage = sFailedMessage + " - " + aFilterNames[nFilter][1];
693 : } else
694 2 : mxComponent = loadFromDesktop(getURLFromSrc(aFilterNames[nFilter][0]), "com.sun.star.text.TextDocument");
695 :
696 : // Check shapes (images, textboxes, custom shapes)
697 8 : uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
698 8 : uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
699 8 : uno::Reference<drawing::XShape> xShape;
700 8 : uno::Reference<graphic::XGraphic> xGraphic;
701 8 : uno::Reference< beans::XPropertySet > XPropSet;
702 8 : uno::Reference<awt::XBitmap> xBitmap;
703 :
704 4 : bool bHasTextboxText = false;
705 4 : bool bHasCustomShapeText = false;
706 4 : sal_Int32 nImageCount = 0;
707 :
708 26 : for (int i = 1; i<= xDraws->getCount(); i++)
709 : {
710 22 : xShape = getShape(i);
711 22 : XPropSet.set( xShape, uno::UNO_QUERY_THROW );
712 : try
713 : {
714 22 : XPropSet->getPropertyValue("Graphic") >>= xGraphic;
715 9 : xBitmap.set(xGraphic, uno::UNO_QUERY);
716 9 : if (xBitmap.is())
717 6 : nImageCount++;
718 : }
719 13 : catch (beans::UnknownPropertyException &)
720 : { /* ignore */ }
721 :
722 22 : uno::Reference<text::XTextRange> xText(xShape, uno::UNO_QUERY);
723 22 : if (xText.is())
724 : {
725 13 : OUString shapeText = xText->getString();
726 13 : if (shapeText.startsWith("Lorem ipsum"))
727 4 : bHasTextboxText = true;
728 9 : else if (shapeText.startsWith("Nam pretium"))
729 4 : bHasCustomShapeText = true;
730 : }
731 22 : }
732 :
733 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), bHasTextboxText);
734 4 : CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), bHasCustomShapeText);
735 4 : CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(bSkipImages ? 0 : 3), nImageCount );
736 4 : }
737 1 : }
738 : #endif
739 :
740 1 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
741 :
742 4 : CPPUNIT_PLUGIN_IMPLEMENT();
743 :
744 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|