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 <cppunit/TestAssert.h>
11 #include <cppunit/TestFixture.h>
12 #include <cppunit/extensions/HelperMacros.h>
13 #include <cppunit/plugin/TestPlugIn.h>
14 
15 #include <com/sun/star/beans/PropertyValue.hpp>
16 
17 #include <vcl/bitmapaccess.hxx>
18 #include <vcl/graph.hxx>
19 #include <vcl/graphicfilter.hxx>
20 #include <tools/stream.hxx>
21 #include <unotest/directories.hxx>
22 
23 using namespace css;
24 
25 namespace
26 {
27 class GraphicTest : public CppUnit::TestFixture
28 {
29     void testUnloadedGraphic();
30     void testUnloadedGraphicLoading();
31     void testUnloadedGraphicWmf();
32     void testUnloadedGraphicAlpha();
33     void testUnloadedGraphicSizeUnit();
34 
35     CPPUNIT_TEST_SUITE(GraphicTest);
36     CPPUNIT_TEST(testUnloadedGraphic);
37     CPPUNIT_TEST(testUnloadedGraphicLoading);
38     CPPUNIT_TEST(testUnloadedGraphicWmf);
39     CPPUNIT_TEST(testUnloadedGraphicAlpha);
40     CPPUNIT_TEST(testUnloadedGraphicSizeUnit);
41     CPPUNIT_TEST_SUITE_END();
42 };
43 
createBitmap(bool alpha=false)44 BitmapEx createBitmap(bool alpha = false)
45 {
46     Bitmap aBitmap(Size(120, 100), 24);
47     aBitmap.Erase(COL_LIGHTRED);
48 
49     aBitmap.SetPrefSize(Size(6000, 5000));
50     aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
51 
52     if (alpha)
53     {
54         sal_uInt8 uAlphaValue = 0x80;
55         AlphaMask aAlphaMask(Size(120, 100), &uAlphaValue);
56 
57         return BitmapEx(aBitmap, aAlphaMask);
58     }
59     else
60     {
61         return BitmapEx(aBitmap);
62     }
63 }
64 
createBitmapAndExportForType(SvStream & rStream,OUString const & sType,bool alpha)65 void createBitmapAndExportForType(SvStream& rStream, OUString const& sType, bool alpha)
66 {
67     BitmapEx aBitmapEx = createBitmap(alpha);
68 
69     uno::Sequence<beans::PropertyValue> aFilterData;
70     GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
71     sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName(sType);
72     rGraphicFilter.ExportGraphic(aBitmapEx, "none", rStream, nFilterFormat, &aFilterData);
73 
74     rStream.Seek(STREAM_SEEK_TO_BEGIN);
75 }
76 
makeUnloadedGraphic(OUString const & sType,bool alpha=false)77 Graphic makeUnloadedGraphic(OUString const& sType, bool alpha = false)
78 {
79     SvMemoryStream aStream;
80     GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
81     createBitmapAndExportForType(aStream, sType, alpha);
82     return rGraphicFilter.ImportUnloadedGraphic(aStream);
83 }
84 
85 char const DATA_DIRECTORY[] = "/vcl/qa/cppunit/data/";
86 
testUnloadedGraphic()87 void GraphicTest::testUnloadedGraphic()
88 {
89     // make unloaded test graphic
90     Graphic aGraphic = makeUnloadedGraphic("png");
91     Graphic aGraphic2 = aGraphic;
92 
93     // check available
94     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
95     CPPUNIT_ASSERT_EQUAL(false, aGraphic2.isAvailable());
96 
97     CPPUNIT_ASSERT_EQUAL(true, aGraphic2.makeAvailable());
98     CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
99     CPPUNIT_ASSERT_EQUAL(true, aGraphic2.isAvailable());
100 
101     // check GetSizePixel doesn't load graphic
102     aGraphic = makeUnloadedGraphic("png");
103     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
104     CPPUNIT_ASSERT_EQUAL(120L, aGraphic.GetSizePixel().Width());
105     CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Height());
106     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
107 
108     // check GetPrefSize doesn't load graphic
109     CPPUNIT_ASSERT_EQUAL(6000L, aGraphic.GetPrefSize().Width());
110     CPPUNIT_ASSERT_EQUAL(5000L, aGraphic.GetPrefSize().Height());
111     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
112 
113     // check GetSizeBytes loads graphic
114     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
115     CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
116     CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
117 }
118 
testUnloadedGraphicLoading()119 void GraphicTest::testUnloadedGraphicLoading()
120 {
121     const OUString aFormats[] = { "png", "gif", "jpg" };
122 
123     for (OUString const& sFormat : aFormats)
124     {
125         Graphic aGraphic = makeUnloadedGraphic(sFormat);
126 
127         // check available
128         CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
129         CPPUNIT_ASSERT_EQUAL(120L, aGraphic.GetSizePixel().Width());
130         CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Height());
131         CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
132         CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
133         CPPUNIT_ASSERT_EQUAL(true, aGraphic.isAvailable());
134         Bitmap aBitmap(aGraphic.GetBitmapEx().GetBitmap());
135 
136         {
137             Bitmap::ScopedReadAccess pReadAccess(aBitmap);
138             for (long y = 0; y < aGraphic.GetSizePixel().Height(); y++)
139             {
140                 for (long x = 0; x < aGraphic.GetSizePixel().Width(); x++)
141                 {
142                     if (pReadAccess->HasPalette())
143                     {
144                         Color aColor
145                             = pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(y, x));
146                         CPPUNIT_ASSERT_EQUAL(OUString("ff0000"), aColor.AsRGBHexString());
147                     }
148                     else
149                     {
150                         Color aColor = pReadAccess->GetPixel(y, x);
151                         if (sFormat != "jpg")
152                             CPPUNIT_ASSERT_EQUAL(OUString("ff0000"), aColor.AsRGBHexString());
153                     }
154                 }
155             }
156         }
157     }
158 }
159 
testUnloadedGraphicWmf()160 void GraphicTest::testUnloadedGraphicWmf()
161 {
162     // Create some in-memory WMF data, set its own preferred size to 99x99.
163     BitmapEx aBitmapEx = createBitmap();
164     SvMemoryStream aStream;
165     GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
166     sal_uInt16 nFilterFormat = rGraphicFilter.GetExportFormatNumberForShortName("wmf");
167     Graphic aGraphic(aBitmapEx);
168     aGraphic.SetPrefSize(Size(99, 99));
169     aGraphic.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
170     rGraphicFilter.ExportGraphic(aGraphic, "none", aStream, nFilterFormat);
171     aStream.Seek(STREAM_SEEK_TO_BEGIN);
172 
173     // Now lazy-load this WMF data, with a custom preferred size of 42x42.
174     Size aMtfSize100(42, 42);
175     aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
176     aGraphic.makeAvailable();
177 
178     // Without the accompanying fix in place, this test would have failed with:
179     // - Expected: 42x42
180     // - Actual  : 99x99
181     // i.e. the custom preferred size was lost after lazy-load.
182     CPPUNIT_ASSERT_EQUAL(Size(42, 42), aGraphic.GetPrefSize());
183 }
184 
testUnloadedGraphicAlpha()185 void GraphicTest::testUnloadedGraphicAlpha()
186 {
187     // make unloaded test graphic with alpha
188     Graphic aGraphic = makeUnloadedGraphic("png", true);
189 
190     CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAlpha());
191     CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsTransparent());
192     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
193 
194     // make unloaded test graphic without alpha
195     aGraphic = makeUnloadedGraphic("png", false);
196 
197     CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsAlpha());
198     CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsTransparent());
199     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
200 }
201 
testUnloadedGraphicSizeUnit()202 void GraphicTest::testUnloadedGraphicSizeUnit()
203 {
204     GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
205     test::Directories aDirectories;
206     OUString aURL = aDirectories.getURLFromSrc(DATA_DIRECTORY) + "inch-size.emf";
207     Size aMtfSize100(42, 42);
208     SvFileStream aStream(aURL, StreamMode::READ);
209     Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream, 0, &aMtfSize100);
210     aGraphic.makeAvailable();
211 
212     // Without the accompanying fix in place, this test would have failed with:
213     // - Expected: 400x363
214     // - Actual  : 42x42
215     // i.e. a mm100 size was used as a hint and the inch size was set for a non-matching unit.
216     CPPUNIT_ASSERT_EQUAL(Size(400, 363), aGraphic.GetPrefSize());
217 }
218 
219 } // namespace
220 
221 CPPUNIT_TEST_SUITE_REGISTRATION(GraphicTest);
222 
223 CPPUNIT_PLUGIN_IMPLEMENT();
224 
225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
226