1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <test/bootstrapfixture.hxx>
12 #include <vcl/print.hxx>
13 #include <vcl/virdev.hxx>
14 #include <vcl/window.hxx>
15 #include <vcl/bitmapaccess.hxx>
16 #include <vcl/gdimtf.hxx>
17 #include <vcl/metaact.hxx>
18 #include <bitmapwriteaccess.hxx>
19 #include <bufferdevice.hxx>
22 #include <basegfx/matrix/b2dhommatrix.hxx>
24 class VclOutdevTest
: public test::BootstrapFixture
28 : BootstrapFixture(true, false)
32 void testVirtualDevice();
33 void testUseAfterDispose();
34 void testPrinterBackgroundColor();
35 void testWindowBackgroundColor();
36 void testGetReadableFontColorPrinter();
37 void testGetReadableFontColorWindow();
38 void testDrawTransformedBitmapEx();
39 void testDrawTransformedBitmapExFlip();
43 CPPUNIT_TEST_SUITE(VclOutdevTest
);
45 CPPUNIT_TEST(testVirtualDevice
);
46 CPPUNIT_TEST(testUseAfterDispose
);
47 CPPUNIT_TEST(testPrinterBackgroundColor
);
48 CPPUNIT_TEST(testWindowBackgroundColor
);
49 CPPUNIT_TEST(testGetReadableFontColorPrinter
);
50 CPPUNIT_TEST(testGetReadableFontColorWindow
);
51 CPPUNIT_TEST(testDrawTransformedBitmapEx
);
52 CPPUNIT_TEST(testDrawTransformedBitmapExFlip
);
53 CPPUNIT_TEST(testRTL
);
54 CPPUNIT_TEST(testRTLGuard
);
55 CPPUNIT_TEST_SUITE_END();
58 void VclOutdevTest::testGetReadableFontColorPrinter()
60 ScopedVclPtrInstance
<Printer
> pPrinter
;
61 CPPUNIT_ASSERT_EQUAL(pPrinter
->GetReadableFontColor(COL_WHITE
, COL_WHITE
), COL_BLACK
);
64 void VclOutdevTest::testGetReadableFontColorWindow()
66 ScopedVclPtrInstance
<vcl::Window
> pWindow(nullptr, WB_APP
| WB_STDWORK
);
67 CPPUNIT_ASSERT_EQUAL(pWindow
->GetReadableFontColor(COL_WHITE
, COL_BLACK
), COL_WHITE
);
68 CPPUNIT_ASSERT_EQUAL(pWindow
->GetReadableFontColor(COL_WHITE
, COL_WHITE
), COL_BLACK
);
69 CPPUNIT_ASSERT_EQUAL(pWindow
->GetReadableFontColor(COL_BLACK
, COL_BLACK
), COL_WHITE
);
72 void VclOutdevTest::testPrinterBackgroundColor()
74 ScopedVclPtrInstance
<Printer
> pPrinter
;
75 CPPUNIT_ASSERT_EQUAL(pPrinter
->GetBackgroundColor(), COL_WHITE
);
78 void VclOutdevTest::testWindowBackgroundColor()
80 ScopedVclPtrInstance
<vcl::Window
> pWindow(nullptr, WB_APP
| WB_STDWORK
);
81 pWindow
->SetBackground(Wallpaper(COL_WHITE
));
82 CPPUNIT_ASSERT_EQUAL(pWindow
->GetBackgroundColor(), COL_WHITE
);
85 void VclOutdevTest::testVirtualDevice()
87 // TODO: This unit test is not executed for macOS unless bitmap scaling is implemented
89 ScopedVclPtrInstance
<VirtualDevice
> pVDev
;
90 pVDev
->SetOutputSizePixel(Size(32, 32));
91 pVDev
->SetBackground(Wallpaper(COL_WHITE
));
93 CPPUNIT_ASSERT_EQUAL(pVDev
->GetBackgroundColor(), COL_WHITE
);
96 pVDev
->DrawPixel(Point(1, 2), COL_BLUE
);
97 pVDev
->DrawPixel(Point(31, 30), COL_RED
);
99 Size aSize
= pVDev
->GetOutputSizePixel();
100 CPPUNIT_ASSERT_EQUAL(Size(32, 32), aSize
);
102 Bitmap aBmp
= pVDev
->GetBitmap(Point(), aSize
);
105 OUString
rFileName("/tmp/foo-unx.png");
107 vcl::PNGWriter
aWriter( aBmp
);
108 SvFileStream
sOutput( rFileName
, StreamMode::WRITE
);
109 aWriter
.Write( sOutput
);
112 SAL_WARN("vcl", "Error writing png to " << rFileName
);
116 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, pVDev
->GetPixel(Point(0, 0)));
117 #if !defined _WIN32 //TODO: various failures on Windows tinderboxes
118 CPPUNIT_ASSERT_EQUAL(COL_BLUE
, pVDev
->GetPixel(Point(1, 2)));
119 CPPUNIT_ASSERT_EQUAL(COL_RED
, pVDev
->GetPixel(Point(31, 30)));
121 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, pVDev
->GetPixel(Point(30, 31)));
123 // Gotcha: y and x swap for BitmapReadAccess: deep joy.
124 Bitmap::ScopedReadAccess
pAcc(aBmp
);
125 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, static_cast<Color
>(pAcc
->GetPixel(0, 0)));
126 #if !defined _WIN32 //TODO: various failures on Windows tinderboxes
127 CPPUNIT_ASSERT_EQUAL(COL_BLUE
, static_cast<Color
>(pAcc
->GetPixel(2, 1)));
128 CPPUNIT_ASSERT_EQUAL(COL_RED
, static_cast<Color
>(pAcc
->GetPixel(30, 31)));
130 CPPUNIT_ASSERT_EQUAL(COL_WHITE
, static_cast<Color
>(pAcc
->GetPixel(31, 30)));
133 VclPtr
<vcl::Window
> pWin
= VclPtr
<WorkWindow
>::Create( (vcl::Window
*)nullptr );
134 CPPUNIT_ASSERT( pWin
);
135 OutputDevice
*pOutDev
= pWin
.get();
140 void VclOutdevTest::testUseAfterDispose()
142 // Create a virtual device, enable map mode then dispose it.
143 ScopedVclPtrInstance
<VirtualDevice
> pVDev
;
145 pVDev
->EnableMapMode();
147 pVDev
->disposeOnce();
149 // Make sure that these don't crash after dispose.
150 pVDev
->GetInverseViewTransformation();
152 pVDev
->GetViewTransformation();
155 void VclOutdevTest::testDrawTransformedBitmapEx()
157 // Create a virtual device, and connect a metafile to it.
158 // Also create a 16x16 bitmap.
159 ScopedVclPtrInstance
<VirtualDevice
> pVDev
;
160 Bitmap
aBitmap(Size(16, 16), 24);
162 // Fill the top left quarter with black.
163 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
164 pWriteAccess
->Erase(COL_WHITE
);
165 for (int i
= 0; i
< 8; ++i
)
167 for (int j
= 0; j
< 8; ++j
)
169 pWriteAccess
->SetPixel(j
, i
, COL_BLACK
);
173 BitmapEx
aBitmapEx(aBitmap
);
174 basegfx::B2DHomMatrix aMatrix
;
176 // Rotate 90 degrees clockwise, so the black part goes to the top right.
177 aMatrix
.rotate(M_PI
/ 2);
179 aMtf
.Record(pVDev
.get());
181 // Draw the rotated bitmap on the vdev.
182 pVDev
->DrawTransformedBitmapEx(aMatrix
, aBitmapEx
);
183 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf
.GetActionSize());
184 MetaAction
* pAction
= aMtf
.GetAction(0);
185 CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE
, pAction
->GetType());
186 auto pBitmapAction
= static_cast<MetaBmpExScaleAction
*>(pAction
);
187 const BitmapEx
& rBitmapEx
= pBitmapAction
->GetBitmapEx();
188 Size aTransformedSize
= rBitmapEx
.GetSizePixel();
189 // Without the accompanying fix in place, this test would have failed with:
192 // I.e. the bitmap before scaling was already scaled down, just because it was rotated.
193 CPPUNIT_ASSERT_EQUAL(Size(16, 16), aTransformedSize
);
195 aBitmap
= rBitmapEx
.GetBitmap();
196 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
197 for (int i
= 0; i
< 16; ++i
)
199 for (int j
= 0; j
< 16; ++j
)
201 BitmapColor aColor
= pAccess
->GetPixel(j
, i
);
202 Color aExpected
= i
>= 8 && j
< 8 ? COL_BLACK
: COL_WHITE
;
203 std::stringstream ss
;
204 ss
<< "Color is expected to be ";
205 ss
<< ((aExpected
== COL_WHITE
) ? "white" : "black");
206 ss
<< ", is " << aColor
.AsRGBHexString();
207 ss
<< " (row " << j
<< ", col " << i
<< ")";
208 // Without the accompanying fix in place, this test would have failed with:
209 // - Expected: c[00000000]
210 // - Actual : c[ffffff00]
211 // - Color is expected to be black, is ffffff (row 0, col 8)
212 // i.e. the top right quarter of the image was not fully black, there was a white first
214 CPPUNIT_ASSERT_EQUAL_MESSAGE(ss
.str(), aExpected
, Color(aColor
));
219 void VclOutdevTest::testDrawTransformedBitmapExFlip()
221 // Create a virtual device, and connect a metafile to it.
222 // Also create a 16x16 bitmap.
223 ScopedVclPtrInstance
<VirtualDevice
> pVDev
;
224 Bitmap
aBitmap(Size(16, 16), 24);
226 // Fill the top left quarter with black.
227 BitmapScopedWriteAccess
pWriteAccess(aBitmap
);
228 pWriteAccess
->Erase(COL_WHITE
);
229 for (int i
= 0; i
< 8; ++i
)
231 for (int j
= 0; j
< 8; ++j
)
233 pWriteAccess
->SetPixel(j
, i
, COL_BLACK
);
237 BitmapEx
aBitmapEx(aBitmap
);
238 basegfx::B2DHomMatrix aMatrix
;
239 // Negative y scale: bitmap should be upside down, so the black part goes to the bottom left.
240 aMatrix
.scale(8, -8);
241 // Rotate 90 degrees clockwise, so the black part goes back to the top left.
242 aMatrix
.rotate(M_PI
/ 2);
244 aMtf
.Record(pVDev
.get());
246 // Draw the scaled and rotated bitmap on the vdev.
247 pVDev
->DrawTransformedBitmapEx(aMatrix
, aBitmapEx
);
248 CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aMtf
.GetActionSize());
249 MetaAction
* pAction
= aMtf
.GetAction(0);
250 CPPUNIT_ASSERT_EQUAL(MetaActionType::BMPEXSCALE
, pAction
->GetType());
251 auto pBitmapAction
= static_cast<MetaBmpExScaleAction
*>(pAction
);
252 const BitmapEx
& rBitmapEx
= pBitmapAction
->GetBitmapEx();
254 aBitmap
= rBitmapEx
.GetBitmap();
255 Bitmap::ScopedReadAccess
pAccess(aBitmap
);
258 BitmapColor aColor
= pAccess
->GetPixel(nY
, nX
);
259 std::stringstream ss
;
260 ss
<< "Color is expected to be black, is " << aColor
.AsRGBHexString();
261 ss
<< " (row " << nY
<< ", col " << nX
<< ")";
262 // Without the accompanying fix in place, this test would have failed with:
263 // - Expected: c[00000000]
264 // - Actual : c[ffffff00]
265 // - Color is expected to be black, is ffffff (row 2, col 2)
266 // i.e. the top left quarter of the image was not black, due to a missing flip.
267 CPPUNIT_ASSERT_EQUAL_MESSAGE(ss
.str(), COL_BLACK
, Color(aColor
));
270 void VclOutdevTest::testRTL()
272 ScopedVclPtrInstance
<vcl::Window
> pWindow(nullptr, WB_APP
| WB_STDWORK
);
273 pWindow
->EnableRTL();
274 vcl::RenderContext
& rRenderContext
= *pWindow
;
275 vcl::BufferDevice
pBuffer(pWindow
, rRenderContext
);
277 // Without the accompanying fix in place, this test would have failed, because the RTL status
278 // from pWindow was not propagated to pBuffer.
279 CPPUNIT_ASSERT(pBuffer
->IsRTLEnabled());
282 void VclOutdevTest::testRTLGuard()
284 ScopedVclPtrInstance
<vcl::Window
> pWindow(nullptr, WB_APP
| WB_STDWORK
);
285 pWindow
->EnableRTL();
286 pWindow
->RequestDoubleBuffering(true);
287 ImplFrameData
* pFrameData
= pWindow
->ImplGetWindowImpl()->mpFrameData
;
288 vcl::PaintBufferGuard
aGuard(pFrameData
, pWindow
);
289 // Without the accompanying fix in place, this test would have failed, because the RTL status
290 // from pWindow was not propagated to aGuard.
291 CPPUNIT_ASSERT(aGuard
.GetRenderContext()->IsRTLEnabled());
294 CPPUNIT_TEST_SUITE_REGISTRATION(VclOutdevTest
);
296 CPPUNIT_PLUGIN_IMPLEMENT();
298 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */