nss: upgrade to release 3.73
[LibreOffice.git] / vcl / qa / cppunit / GraphicTest.cxx
blob50ff4a133f8663896a798a3c9b0c1255c8bfa1cd
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 <sal/config.h>
11 #include <config_oox.h>
12 #include <cppunit/TestAssert.h>
13 #include <cppunit/TestFixture.h>
14 #include <cppunit/extensions/HelperMacros.h>
15 #include <cppunit/plugin/TestPlugIn.h>
17 #include <com/sun/star/beans/PropertyValue.hpp>
19 #include <vcl/bitmapaccess.hxx>
20 #include <vcl/graph.hxx>
21 #include <vcl/graphicfilter.hxx>
22 #include <tools/stream.hxx>
23 #include <unotest/directories.hxx>
24 #include <comphelper/DirectoryHelper.hxx>
25 #include <comphelper/hash.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
28 #include <impgraph.hxx>
30 #if USE_TLS_NSS
31 #include <nss.h>
32 #endif
34 using namespace css;
36 namespace
38 class GraphicTest : public CppUnit::TestFixture
40 public:
41 ~GraphicTest();
43 private:
44 void testUnloadedGraphic();
45 void testUnloadedGraphicLoading();
46 void testUnloadedGraphicWmf();
47 void testUnloadedGraphicAlpha();
48 void testUnloadedGraphicSizeUnit();
49 void testSwapping();
50 void testSwappingVectorGraphic();
51 void testSwappingPageNumber();
53 CPPUNIT_TEST_SUITE(GraphicTest);
54 CPPUNIT_TEST(testUnloadedGraphic);
55 CPPUNIT_TEST(testUnloadedGraphicLoading);
56 CPPUNIT_TEST(testUnloadedGraphicWmf);
57 CPPUNIT_TEST(testUnloadedGraphicAlpha);
58 CPPUNIT_TEST(testUnloadedGraphicSizeUnit);
59 CPPUNIT_TEST(testSwapping);
60 CPPUNIT_TEST(testSwappingVectorGraphic);
61 CPPUNIT_TEST(testSwappingPageNumber);
62 CPPUNIT_TEST_SUITE_END();
65 GraphicTest::~GraphicTest()
67 #if USE_TLS_NSS
68 NSS_Shutdown();
69 #endif
72 BitmapEx createBitmap(bool alpha = false)
74 Bitmap aBitmap(Size(120, 100), 24);
75 aBitmap.Erase(COL_LIGHTRED);
77 aBitmap.SetPrefSize(Size(6000, 5000));
78 aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
80 if (alpha)
82 sal_uInt8 uAlphaValue = 0x80;
83 AlphaMask aAlphaMask(Size(120, 100), &uAlphaValue);
85 return BitmapEx(aBitmap, aAlphaMask);
87 else
89 return BitmapEx(aBitmap);
93 void createBitmapAndExportForType(SvStream& rStream, std::u16string_view sType, bool alpha)
95 BitmapEx aBitmapEx = createBitmap(alpha);
97 uno::Sequence<beans::PropertyValue> aFilterData;
98 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
99 sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(sType);
100 rGraphicFilter.ExportGraphic(aBitmapEx, "none", rStream, nFilterFormat, &aFilterData);
102 rStream.Seek(STREAM_SEEK_TO_BEGIN);
105 Graphic makeUnloadedGraphic(std::u16string_view sType, bool alpha = false)
107 SvMemoryStream aStream;
108 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
109 createBitmapAndExportForType(aStream, sType, alpha);
110 return rGraphicFilter.ImportUnloadedGraphic(aStream);
113 std::string toHexString(const std::vector<unsigned char>& a)
115 std::stringstream aStrm;
116 for (auto& i : a)
118 aStrm << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(i);
121 return aStrm.str();
124 std::unique_ptr<SvStream> createStream(OUString const& rSwapFileURL)
126 std::unique_ptr<SvStream> xStream;
130 xStream = ::utl::UcbStreamHelper::CreateStream(
131 rSwapFileURL, StreamMode::READWRITE | StreamMode::SHARE_DENYWRITE);
133 catch (const css::uno::Exception&)
137 return xStream;
140 std::vector<unsigned char> calculateHash(std::unique_ptr<SvStream>& rStream)
142 comphelper::Hash aHashEngine(comphelper::HashType::SHA1);
143 const sal_uInt32 nSize(rStream->remainingSize());
144 std::vector<sal_uInt8> aData(nSize);
145 aHashEngine.update(aData.data(), nSize);
146 return aHashEngine.finalize();
149 bool checkBitmap(Graphic& rGraphic)
151 bool bResult = true;
153 Bitmap aBitmap(rGraphic.GetBitmapEx().GetBitmap());
155 Bitmap::ScopedReadAccess pReadAccess(aBitmap);
156 for (tools::Long y = 0; y < rGraphic.GetSizePixel().Height(); y++)
158 for (tools::Long x = 0; x < rGraphic.GetSizePixel().Width(); x++)
160 if (pReadAccess->HasPalette())
162 sal_uInt32 nIndex = pReadAccess->GetPixelIndex(y, x);
163 Color aColor = pReadAccess->GetPaletteColor(nIndex);
164 bResult &= (aColor == Color(0xff, 0x00, 0x00));
166 else
168 Color aColor = pReadAccess->GetPixel(y, x);
169 bResult &= (aColor == Color(0xff, 0x00, 0x00));
175 return bResult;
178 char const DATA_DIRECTORY[] = "/vcl/qa/cppunit/data/";
179 char const PDFEXPORT_DATA_DIRECTORY[] = "/vcl/qa/cppunit/pdfexport/data/";
181 void GraphicTest::testUnloadedGraphic()
183 // make unloaded test graphic
184 Graphic aGraphic = makeUnloadedGraphic(u"png");
185 Graphic aGraphic2 = aGraphic;
187 // check available
188 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
189 CPPUNIT_ASSERT_EQUAL(false, aGraphic2.isAvailable());
191 CPPUNIT_ASSERT_EQUAL(true, aGraphic2.makeAvailable());
192 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
193 CPPUNIT_ASSERT_EQUAL(true, aGraphic2.isAvailable());
195 // check GetSizePixel doesn't load graphic
196 aGraphic = makeUnloadedGraphic(u"png");
197 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
198 CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
199 CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
200 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
202 // check GetPrefSize doesn't load graphic
203 CPPUNIT_ASSERT_EQUAL(tools::Long(6000), aGraphic.GetPrefSize().Width());
204 CPPUNIT_ASSERT_EQUAL(tools::Long(5000), aGraphic.GetPrefSize().Height());
205 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
207 // check GetSizeBytes loads graphic
208 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
209 CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
210 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
212 //check Type
213 aGraphic = makeUnloadedGraphic(u"png");
214 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
215 CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
216 CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
217 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
218 CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
221 void GraphicTest::testUnloadedGraphicLoading()
223 const OUString aFormats[] = { "png", "gif", "jpg" };
225 for (OUString const& sFormat : aFormats)
227 Graphic aGraphic = makeUnloadedGraphic(sFormat);
229 // check available
230 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
231 CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
232 CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
233 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
234 CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
235 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
237 if (sFormat != "jpg")
238 CPPUNIT_ASSERT_EQUAL(true, checkBitmap(aGraphic));
242 void GraphicTest::testUnloadedGraphicWmf()
244 // Create some in-memory WMF data, set its own preferred size to 99x99.
245 BitmapEx aBitmapEx = createBitmap();
246 SvMemoryStream aStream;
247 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
248 sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(u"wmf");
249 Graphic aGraphic(aBitmapEx);
250 aGraphic.SetPrefSize(Size(99, 99));
251 aGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
252 rGraphicFilter.ExportGraphic(aGraphic, "none", aStream, nFilterFormat);
253 aStream.Seek(STREAM_SEEK_TO_BEGIN);
255 // Now lazy-load this WMF data, with a custom preferred size of 42x42.
256 Size aMtfSize100(42, 42);
257 aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
258 aGraphic.makeAvailable();
260 // Without the accompanying fix in place, this test would have failed with:
261 // - Expected: 42x42
262 // - Actual : 99x99
263 // i.e. the custom preferred size was lost after lazy-load.
264 CPPUNIT_ASSERT_EQUAL(Size(42, 42), aGraphic.GetPrefSize());
267 void GraphicTest::testUnloadedGraphicAlpha()
269 // make unloaded test graphic with alpha
270 Graphic aGraphic = makeUnloadedGraphic(u"png", true);
272 CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAlpha());
273 CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsTransparent());
274 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
276 // make unloaded test graphic without alpha
277 aGraphic = makeUnloadedGraphic(u"png", false);
279 CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsAlpha());
280 CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsTransparent());
281 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
284 void GraphicTest::testUnloadedGraphicSizeUnit()
286 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
287 test::Directories aDirectories;
288 OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "inch-size.emf";
289 Size aMtfSize100(42, 42);
290 SvFileStream aStream(aURL, StreamMode::READ);
291 Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
292 aGraphic.makeAvailable();
294 // Without the accompanying fix in place, this test would have failed with:
295 // - Expected: 400x363
296 // - Actual : 42x42
297 // i.e. a mm100 size was used as a hint and the inch size was set for a non-matching unit.
298 CPPUNIT_ASSERT_EQUAL(Size(400, 363), aGraphic.GetPrefSize());
301 void GraphicTest::testSwapping()
303 // Prepare Graphic from a PNG image first
304 Graphic aGraphic = makeUnloadedGraphic(u"png");
306 CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
307 CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
308 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
310 CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
311 CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
313 BitmapChecksum aChecksumBeforeSwapping = aGraphic.GetChecksum();
315 CPPUNIT_ASSERT_EQUAL(sal_uInt32(319), aGraphic.GetGfxLink().GetDataSize());
317 // We loaded the Graphic and made it available
318 CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
319 // Get the declared byte size of the graphic
320 sal_uLong rByteSize = aGraphic.GetSizeBytes();
321 OUString rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
322 CPPUNIT_ASSERT_EQUAL(true, rSwapFileURL.isEmpty());
324 // Swapping out
325 CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
326 CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
327 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
329 // Byte size doesn't change when we swapped out
330 CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
332 // Let's check the swap file
333 rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
334 CPPUNIT_ASSERT_EQUAL(true, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
336 { // Check the swap file content
337 std::unique_ptr<SvStream> xStream = createStream(rSwapFileURL);
338 CPPUNIT_ASSERT_EQUAL(true, bool(xStream));
340 // Check size of the stream
341 CPPUNIT_ASSERT_EQUAL(sal_uInt64(449), xStream->remainingSize());
343 std::vector<unsigned char> aHash = calculateHash(xStream);
344 CPPUNIT_ASSERT_EQUAL(std::string("878281e583487b29ae09078e8040c01791c7649a"),
345 toHexString(aHash));
348 // Let's swap in
349 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
350 CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
351 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
352 CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
354 CPPUNIT_ASSERT_EQUAL(aChecksumBeforeSwapping, aGraphic.GetChecksum());
356 // File shouldn't be available anymore
357 CPPUNIT_ASSERT_EQUAL(false, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
359 // Check the bitmap
360 CPPUNIT_ASSERT_EQUAL(tools::Long(120), aGraphic.GetSizePixel().Width());
361 CPPUNIT_ASSERT_EQUAL(tools::Long(100), aGraphic.GetSizePixel().Height());
362 CPPUNIT_ASSERT_EQUAL(true, checkBitmap(aGraphic));
363 CPPUNIT_ASSERT_EQUAL(true, checkBitmap(aGraphic));
366 void GraphicTest::testSwappingVectorGraphic()
368 test::Directories aDirectories;
369 OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "SimpleExample.svg";
370 SvFileStream aStream(aURL, StreamMode::READ);
371 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
372 Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
374 CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
375 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
377 // Load the vector graphic
378 CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
379 CPPUNIT_ASSERT_EQUAL(sal_uInt32(223),
380 aGraphic.getVectorGraphicData()->getVectorGraphicDataArrayLength());
381 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
382 CPPUNIT_ASSERT_EQUAL(sal_uInt32(223), aGraphic.GetGfxLink().GetDataSize());
383 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
385 BitmapChecksum aBitmapChecksumBeforeSwapping = aGraphic.GetBitmapEx().GetChecksum();
387 CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
389 // Get the declared byte size of the graphic
390 sal_uLong rByteSize = aGraphic.GetSizeBytes();
391 CPPUNIT_ASSERT_EQUAL(sal_uLong(223), rByteSize);
392 OUString rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
393 CPPUNIT_ASSERT_EQUAL(true, rSwapFileURL.isEmpty());
395 // Swapping out
396 CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
397 CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
398 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
400 // Byte size doesn't change when we swapped out
401 // TODO: In case we don't trigger GetBitmapEx (above) the size is 0
402 CPPUNIT_ASSERT_EQUAL(rByteSize, aGraphic.GetSizeBytes());
404 // Let's check the swap file
405 rSwapFileURL = aGraphic.ImplGetImpGraphic()->getSwapFileURL();
406 CPPUNIT_ASSERT_EQUAL(true, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
408 { // Check the swap file content
409 std::unique_ptr<SvStream> xStream = createStream(rSwapFileURL);
410 CPPUNIT_ASSERT_EQUAL(true, bool(xStream));
412 // Check size of the stream
413 CPPUNIT_ASSERT_EQUAL(sal_uInt64(353), xStream->remainingSize());
415 std::vector<unsigned char> aHash = calculateHash(xStream);
416 CPPUNIT_ASSERT_EQUAL(std::string("6ae83fc9c06ca253ada0b156d6e4700a4a028c34"),
417 toHexString(aHash));
420 // Let's swap in
421 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
422 CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
423 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
424 CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
426 CPPUNIT_ASSERT_EQUAL(aBitmapChecksumBeforeSwapping, aGraphic.GetBitmapEx().GetChecksum());
428 // File shouldn't be available anymore
429 CPPUNIT_ASSERT_EQUAL(false, comphelper::DirectoryHelper::fileExists(rSwapFileURL));
432 void GraphicTest::testSwappingPageNumber()
434 test::Directories aDirectories;
435 OUString aURL = aDirectories.getURLFromSrc(PDFEXPORT_DATA_DIRECTORY) + "SimpleMultiPagePDF.pdf";
436 SvFileStream aStream(aURL, StreamMode::READ);
437 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
438 Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
440 CPPUNIT_ASSERT_EQUAL(GraphicType::Bitmap, aGraphic.GetType());
441 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
443 // Load the vector graphic
444 CPPUNIT_ASSERT_EQUAL(true, bool(aGraphic.getVectorGraphicData()));
445 // Set the page index
446 aGraphic.getVectorGraphicData()->setPageIndex(1);
448 CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf,
449 aGraphic.getVectorGraphicData()->getVectorGraphicDataType());
450 CPPUNIT_ASSERT_EQUAL(sal_uInt32(17693),
451 aGraphic.getVectorGraphicData()->getVectorGraphicDataArrayLength());
452 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
453 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getVectorGraphicData()->getPageIndex());
455 CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
457 // Swapping out
458 CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->swapOut());
459 CPPUNIT_ASSERT_EQUAL(true, aGraphic.ImplGetImpGraphic()->isSwappedOut());
460 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
462 // Let's swap in
463 CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
464 CPPUNIT_ASSERT_EQUAL(true, aGraphic.makeAvailable());
465 CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
466 CPPUNIT_ASSERT_EQUAL(false, aGraphic.ImplGetImpGraphic()->isSwappedOut());
468 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aGraphic.getVectorGraphicData()->getPageIndex());
471 } // namespace
473 CPPUNIT_TEST_SUITE_REGISTRATION(GraphicTest);
475 CPPUNIT_PLUGIN_IMPLEMENT();
477 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */