calc: on editing invalidation of view with different zoom is wrong
[LibreOffice.git] / vcl / qa / cppunit / skia / skia.cxx
blobf2990d3811fcb63041ff309c9d7416f469b001b3
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 <test/bootstrapfixture.hxx>
12 #include <tools/stream.hxx>
13 #include <basegfx/matrix/b2dhommatrix.hxx>
15 #include <vcl/graphicfilter.hxx>
16 #include <vcl/virdev.hxx>
17 #include <vcl/skia/SkiaHelper.hxx>
19 #include <skia/salbmp.hxx>
20 #include <skia/utils.hxx>
21 #include <bitmap/BitmapWriteAccess.hxx>
23 using namespace SkiaHelper;
25 // This tests backends that use Skia (i.e. intentionally not the svp one, which is the default.)
26 // Note that you still may need to actually set for Skia to be used (see vcl/README.vars).
27 // If Skia is not enabled, all tests will be silently skipped.
28 namespace
30 class SkiaTest : public test::BootstrapFixture
32 public:
33 SkiaTest()
34 : test::BootstrapFixture(true, false)
38 void testBitmapErase();
39 void testDrawShaders();
40 void testInterpretAs8Bit();
41 void testAlphaBlendWith();
42 void testBitmapCopyOnWrite();
43 void testMatrixQuality();
44 void testDelayedScale();
45 void testDelayedScaleAlphaImage();
46 void testDrawDelayedScaleImage();
47 void testChecksum();
48 void testTdf137329();
49 void testTdf140848();
50 void testTdf132367();
52 CPPUNIT_TEST_SUITE(SkiaTest);
53 CPPUNIT_TEST(testBitmapErase);
54 CPPUNIT_TEST(testDrawShaders);
55 CPPUNIT_TEST(testInterpretAs8Bit);
56 CPPUNIT_TEST(testAlphaBlendWith);
57 CPPUNIT_TEST(testBitmapCopyOnWrite);
58 CPPUNIT_TEST(testMatrixQuality);
59 CPPUNIT_TEST(testDelayedScale);
60 CPPUNIT_TEST(testDelayedScaleAlphaImage);
61 CPPUNIT_TEST(testDrawDelayedScaleImage);
62 CPPUNIT_TEST(testChecksum);
63 CPPUNIT_TEST(testTdf137329);
64 CPPUNIT_TEST(testTdf140848);
65 CPPUNIT_TEST(testTdf132367);
66 CPPUNIT_TEST_SUITE_END();
68 private:
69 #if 0
70 template <class BitmapT> // handle both Bitmap and BitmapEx
71 void savePNG(const OUString& sWhere, const BitmapT& rBmp)
73 SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
74 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
75 rFilter.compressAsPNG(BitmapEx(rBmp), aStream);
77 void savePNG(const OUString& sWhere, const ScopedVclPtr<VirtualDevice>& device)
79 SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
80 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
81 rFilter.compressAsPNG(device->GetBitmapEx(Point(), device->GetOutputSizePixel()), aStream);
83 #endif
86 void SkiaTest::testBitmapErase()
88 if (!SkiaHelper::isVCLSkiaEnabled())
89 return;
90 Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
91 SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
92 CPPUNIT_ASSERT(skiaBitmap);
93 // Uninitialized bitmap.
94 CPPUNIT_ASSERT(!skiaBitmap->unittestHasBuffer());
95 CPPUNIT_ASSERT(!skiaBitmap->unittestHasImage());
96 CPPUNIT_ASSERT(!skiaBitmap->unittestHasAlphaImage());
97 CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
98 // Test that Bitmap.Erase() just sets erase color and doesn't allocate pixels.
99 bitmap.Erase(COL_RED);
100 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
101 CPPUNIT_ASSERT(!skiaBitmap->unittestHasBuffer());
102 CPPUNIT_ASSERT(!skiaBitmap->unittestHasImage());
103 CPPUNIT_ASSERT(!skiaBitmap->unittestHasAlphaImage());
104 CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
105 // Reading a pixel will create pixel data.
106 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_RED), BitmapReadAccess(bitmap).GetColor(0, 0));
107 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
108 CPPUNIT_ASSERT(skiaBitmap->unittestHasBuffer());
109 CPPUNIT_ASSERT(!skiaBitmap->unittestHasImage());
110 CPPUNIT_ASSERT(!skiaBitmap->unittestHasAlphaImage());
111 CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
114 // Test that draw calls that internally result in SkShader calls work properly.
115 void SkiaTest::testDrawShaders()
117 if (!SkiaHelper::isVCLSkiaEnabled())
118 return;
119 ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
120 device->SetOutputSizePixel(Size(20, 20));
121 device->SetBackground(Wallpaper(COL_WHITE));
122 device->Erase();
123 Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
124 bitmap.Erase(COL_RED);
125 SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
126 CPPUNIT_ASSERT(skiaBitmap->PreferSkShader());
127 AlphaMask alpha(Size(10, 10));
128 alpha.Erase(64);
129 SkiaSalBitmap* skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
130 CPPUNIT_ASSERT(skiaAlpha->PreferSkShader());
132 device->DrawBitmap(Point(5, 5), bitmap);
133 //savePNG("/tmp/a1.png", device);
134 // Check that the area is painted, but nothing else.
135 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0)));
136 CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(5, 5)));
137 CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(14, 14)));
138 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(15, 15)));
139 device->Erase();
141 device->DrawBitmapEx(Point(5, 5), BitmapEx(bitmap, alpha));
142 //savePNG("/tmp/a2.png", device);
143 Color resultRed(COL_RED.GetRed() * 3 / 4 + 64, 64, 64); // 3/4 red, 1/4 white
144 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0)));
145 CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(5, 5)));
146 CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(14, 14)));
147 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(15, 15)));
148 device->Erase();
150 basegfx::B2DHomMatrix matrix;
151 matrix.scale(10, 10);
152 matrix.rotate(M_PI / 4);
153 device->DrawTransformedBitmapEx(matrix, BitmapEx(bitmap, alpha));
154 //savePNG("/tmp/a3.png", device);
155 CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(0, 1)));
156 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(1, 0)));
157 CPPUNIT_ASSERT_EQUAL(resultRed, device->GetPixel(Point(0, 10)));
158 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(10, 10)));
159 device->Erase();
161 // Test with scaling. Use everything 10x larger to reduce the impact of smoothscaling.
162 ScopedVclPtr<VirtualDevice> deviceLarge = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
163 deviceLarge->SetOutputSizePixel(Size(200, 200));
164 deviceLarge->SetBackground(Wallpaper(COL_WHITE));
165 deviceLarge->Erase();
166 Bitmap bitmapLarge(Size(100, 100), vcl::PixelFormat::N24_BPP);
167 bitmapLarge.Erase(COL_RED);
168 SkiaSalBitmap* skiaBitmapLarge
169 = dynamic_cast<SkiaSalBitmap*>(bitmapLarge.ImplGetSalBitmap().get());
170 CPPUNIT_ASSERT(skiaBitmapLarge->PreferSkShader());
171 AlphaMask alphaLarge(Size(100, 100));
172 alphaLarge.Erase(64);
174 BitmapWriteAccess access(bitmapLarge);
175 access.SetFillColor(COL_BLUE);
176 access.FillRect(tools::Rectangle(Point(20, 40), Size(10, 10)));
178 // Using alpha will still lead to shaders being used.
179 deviceLarge->DrawBitmapEx(Point(50, 50), Size(60, 60), Point(20, 20), Size(30, 30),
180 BitmapEx(bitmapLarge, alphaLarge));
181 //savePNG("/tmp/a4.png", deviceLarge);
182 Color resultBlue(64, 64, COL_BLUE.GetBlue() * 3 / 4 + 64); // 3/4 blue, 1/4 white
183 CPPUNIT_ASSERT_EQUAL(COL_WHITE, deviceLarge->GetPixel(Point(40, 40)));
184 CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(50, 50)));
185 CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(100, 100)));
186 CPPUNIT_ASSERT_EQUAL(COL_WHITE, deviceLarge->GetPixel(Point(110, 110)));
187 // Don't test colors near the edge between the colors, smoothscaling affects them.
188 const int diff = 3;
189 CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(50 + diff, 89 - diff)));
190 CPPUNIT_ASSERT_EQUAL(resultBlue, deviceLarge->GetPixel(Point(50 + diff, 90 + diff)));
191 CPPUNIT_ASSERT_EQUAL(resultBlue, deviceLarge->GetPixel(Point(69 - diff, 100 - diff)));
192 CPPUNIT_ASSERT_EQUAL(resultRed, deviceLarge->GetPixel(Point(70 + diff, 100 - diff)));
193 CPPUNIT_ASSERT_EQUAL(resultBlue, deviceLarge->GetPixel(Point(50 + diff, 100 - diff)));
194 device->Erase();
197 void SkiaTest::testInterpretAs8Bit()
199 if (!SkiaHelper::isVCLSkiaEnabled())
200 return;
201 Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
202 // Test with erase color.
203 bitmap.Erase(Color(33, 33, 33));
204 SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
205 CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
206 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, bitmap.getPixelFormat());
207 bitmap.Convert(BmpConversion::N8BitNoConversion);
208 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
209 CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
210 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, bitmap.getPixelFormat());
211 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(33), BitmapReadAccess(bitmap).GetPixelIndex(0, 0));
213 // Test with image.
214 bitmap = Bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
215 bitmap.Erase(Color(34, 34, 34));
216 BitmapReadAccess(bitmap).GetColor(0, 0); // Create pixel data, reset erase color.
217 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
218 skiaBitmap->GetSkImage();
219 CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
220 CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
221 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, bitmap.getPixelFormat());
222 bitmap.Convert(BmpConversion::N8BitNoConversion);
223 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
224 CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
225 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, bitmap.getPixelFormat());
226 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(34), BitmapReadAccess(bitmap).GetPixelIndex(0, 0));
229 void SkiaTest::testAlphaBlendWith()
231 if (!SkiaHelper::isVCLSkiaEnabled())
232 return;
233 AlphaMask alpha(Size(10, 10));
234 Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
235 // Test with erase colors set.
236 alpha.Erase(64);
237 SkiaSalBitmap* skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
238 CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
239 bitmap.Erase(Color(64, 64, 64));
240 SkiaSalBitmap* skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
241 CPPUNIT_ASSERT(skiaBitmap->unittestHasEraseColor());
242 alpha.BlendWith(bitmap);
243 skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
244 CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
245 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
246 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
247 AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 0));
249 // Test with images set.
250 alpha.Erase(64);
251 AlphaMask::ScopedReadAccess(alpha)->GetColor(0, 0); // Reading a pixel will create pixel data.
252 skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
253 skiaAlpha->GetSkImage();
254 CPPUNIT_ASSERT(!skiaAlpha->unittestHasEraseColor());
255 CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
256 bitmap.Erase(Color(64, 64, 64));
257 Bitmap::ScopedReadAccess(bitmap)->GetColor(0, 0); // Reading a pixel will create pixel data.
258 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
259 skiaBitmap->GetSkImage();
260 CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
261 CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
262 alpha.BlendWith(bitmap);
263 skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
264 CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
265 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
266 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
267 AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 0));
269 // Test with erase color for alpha and image for other bitmap.
270 alpha.Erase(64);
271 skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
272 CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
273 bitmap.Erase(Color(64, 64, 64));
274 Bitmap::ScopedReadAccess(bitmap)->GetColor(0, 0); // Reading a pixel will create pixel data.
275 skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
276 skiaBitmap->GetSkImage();
277 CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
278 CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
279 alpha.BlendWith(bitmap);
280 skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.ImplGetSalBitmap().get());
281 CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
282 CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
283 CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(112),
284 AlphaMask::ScopedReadAccess(alpha)->GetPixelIndex(0, 0));
287 void SkiaTest::testBitmapCopyOnWrite()
289 if (!SkiaHelper::isVCLSkiaEnabled())
290 return;
291 SkiaSalBitmap bitmap;
292 CPPUNIT_ASSERT(bitmap.Create(Size(10, 10), vcl::PixelFormat::N24_BPP, BitmapPalette()));
293 bitmap.GetSkImage();
294 bitmap.GetAlphaSkImage();
295 CPPUNIT_ASSERT(bitmap.unittestHasBuffer());
296 CPPUNIT_ASSERT(bitmap.unittestHasImage());
297 CPPUNIT_ASSERT(bitmap.unittestHasAlphaImage());
298 SkiaSalBitmap bitmap2;
299 CPPUNIT_ASSERT(bitmap2.Create(bitmap));
300 // Data should be shared.
301 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetBuffer(), bitmap2.unittestGetBuffer());
302 CPPUNIT_ASSERT(bitmap2.unittestHasImage());
303 CPPUNIT_ASSERT(bitmap2.unittestHasAlphaImage());
304 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), bitmap2.unittestGetImage());
305 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), bitmap2.unittestGetAlphaImage());
306 // Reading still should keep the data shared.
307 const SkImage* oldImage = bitmap.unittestGetImage();
308 const SkImage* oldAlphaImage = bitmap.unittestGetAlphaImage();
309 BitmapBuffer* buffer = bitmap.AcquireBuffer(BitmapAccessMode::Read);
310 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetBuffer(), bitmap2.unittestGetBuffer());
311 bitmap.ReleaseBuffer(buffer, BitmapAccessMode::Read);
312 // Images get possibly updated only after releasing the buffer.
313 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), bitmap2.unittestGetImage());
314 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), bitmap2.unittestGetAlphaImage());
315 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), oldImage);
316 CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), oldAlphaImage);
317 // Writing should unshare.
318 buffer = bitmap.AcquireBuffer(BitmapAccessMode::Write);
319 CPPUNIT_ASSERT(bitmap.unittestGetBuffer() != bitmap2.unittestGetBuffer());
320 bitmap.ReleaseBuffer(buffer, BitmapAccessMode::Write);
321 CPPUNIT_ASSERT(bitmap.unittestGetImage() != bitmap2.unittestGetImage());
322 CPPUNIT_ASSERT(bitmap.unittestGetAlphaImage() != bitmap2.unittestGetAlphaImage());
323 CPPUNIT_ASSERT(bitmap.unittestGetImage() != oldImage);
324 CPPUNIT_ASSERT(bitmap.unittestGetAlphaImage() != oldAlphaImage);
327 void SkiaTest::testMatrixQuality()
329 if (!SkiaHelper::isVCLSkiaEnabled())
330 return;
331 // Not changing the size (but possibly rotated/flipped) does not need high quality transformations.
332 CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix()));
333 CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(90)));
334 CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(180)));
335 CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(270)));
336 CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(1, -1)));
337 CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(0, -1)));
338 CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(2, 1)));
339 CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(89)));
342 void SkiaTest::testDelayedScale()
344 if (!SkiaHelper::isVCLSkiaEnabled())
345 return;
346 Bitmap bitmap1(Size(10, 10), vcl::PixelFormat::N24_BPP);
347 SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap1.ImplGetSalBitmap().get());
348 CPPUNIT_ASSERT(skiaBitmap1);
349 // Do scaling based on mBuffer.
350 (void)BitmapReadAccess(bitmap1); // allocates mBuffer
351 CPPUNIT_ASSERT(skiaBitmap1->unittestHasBuffer());
352 CPPUNIT_ASSERT(!skiaBitmap1->unittestHasImage());
353 CPPUNIT_ASSERT(bitmap1.Scale(2, 2, BmpScaleFlag::Default));
354 skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap1.ImplGetSalBitmap().get());
355 CPPUNIT_ASSERT(skiaBitmap1);
356 CPPUNIT_ASSERT(skiaBitmap1->unittestHasBuffer());
357 CPPUNIT_ASSERT(!skiaBitmap1->unittestHasImage());
358 CPPUNIT_ASSERT_EQUAL(Size(20, 20), bitmap1.GetSizePixel());
359 CPPUNIT_ASSERT_EQUAL(Size(20, 20), imageSize(skiaBitmap1->GetSkImage()));
360 BitmapBuffer* buffer1 = skiaBitmap1->AcquireBuffer(BitmapAccessMode::Read);
361 CPPUNIT_ASSERT(buffer1);
362 CPPUNIT_ASSERT_EQUAL(tools::Long(20), buffer1->mnWidth);
363 CPPUNIT_ASSERT_EQUAL(tools::Long(20), buffer1->mnHeight);
364 skiaBitmap1->ReleaseBuffer(buffer1, BitmapAccessMode::Read);
365 // Do scaling based on mImage.
366 SkiaSalBitmap skiaBitmap2(skiaBitmap1->GetSkImage());
367 CPPUNIT_ASSERT(!skiaBitmap2.unittestHasBuffer());
368 CPPUNIT_ASSERT(skiaBitmap2.unittestHasImage());
369 CPPUNIT_ASSERT(skiaBitmap2.Scale(2, 3, BmpScaleFlag::Default));
370 CPPUNIT_ASSERT(!skiaBitmap2.unittestHasBuffer());
371 CPPUNIT_ASSERT(skiaBitmap2.unittestHasImage());
372 CPPUNIT_ASSERT_EQUAL(Size(40, 60), skiaBitmap2.GetSize());
373 CPPUNIT_ASSERT_EQUAL(Size(40, 60), imageSize(skiaBitmap2.GetSkImage()));
374 BitmapBuffer* buffer2 = skiaBitmap2.AcquireBuffer(BitmapAccessMode::Read);
375 CPPUNIT_ASSERT(buffer2);
376 CPPUNIT_ASSERT_EQUAL(tools::Long(40), buffer2->mnWidth);
377 CPPUNIT_ASSERT_EQUAL(tools::Long(60), buffer2->mnHeight);
378 skiaBitmap2.ReleaseBuffer(buffer2, BitmapAccessMode::Read);
381 void SkiaTest::testDelayedScaleAlphaImage()
383 if (!SkiaHelper::isVCLSkiaEnabled())
384 return;
385 auto bitmapTmp = std::make_unique<SkiaSalBitmap>();
386 CPPUNIT_ASSERT(bitmapTmp->Create(Size(10, 10), vcl::PixelFormat::N24_BPP, BitmapPalette()));
387 bitmapTmp->Erase(COL_RED);
388 // Create a bitmap that has only an image, not a pixel buffer.
389 SkiaSalBitmap bitmap(bitmapTmp->GetSkImage());
390 bitmapTmp.release();
391 CPPUNIT_ASSERT(!bitmap.unittestHasBuffer());
392 CPPUNIT_ASSERT(bitmap.unittestHasImage());
393 CPPUNIT_ASSERT(!bitmap.unittestHasAlphaImage());
394 // Set up pending scale.
395 CPPUNIT_ASSERT(bitmap.Scale(2.0, 2.0, BmpScaleFlag::Fast));
396 CPPUNIT_ASSERT(bitmap.unittestHasPendingScale());
397 CPPUNIT_ASSERT(bitmap.InterpretAs8Bit());
398 // Ask for SkImage and make sure it's scaled up.
399 sk_sp<SkImage> image = bitmap.GetSkImage();
400 CPPUNIT_ASSERT_EQUAL(20, image->width());
401 // Ask again, this time it should be cached.
402 sk_sp<SkImage> image2 = bitmap.GetSkImage();
403 CPPUNIT_ASSERT_EQUAL(image.get(), image2.get());
404 // Add another scale.
405 CPPUNIT_ASSERT(bitmap.Scale(3.0, 3.0, BmpScaleFlag::Fast));
406 // Ask for alpha SkImage and make sure it's scaled up.
407 sk_sp<SkImage> alphaImage = bitmap.GetAlphaSkImage();
408 CPPUNIT_ASSERT_EQUAL(60, alphaImage->width());
409 // Ask again, this time it should be cached.
410 sk_sp<SkImage> alphaImage2 = bitmap.GetAlphaSkImage();
411 CPPUNIT_ASSERT_EQUAL(alphaImage.get(), alphaImage2.get());
412 // Ask again for non-alpha image, it should be scaled again.
413 sk_sp<SkImage> image3 = bitmap.GetSkImage();
414 CPPUNIT_ASSERT_EQUAL(60, image3->width());
415 CPPUNIT_ASSERT(image3.get() != image2.get());
416 CPPUNIT_ASSERT(image3.get() != image.get());
417 // Create pixel buffer from the image (it should convert from alpha image because the bitmap is 8bpp
418 // and the alpha image size matches).
419 SkiaSalBitmap bitmapCopy;
420 bitmapCopy.Create(bitmap);
421 CPPUNIT_ASSERT(!bitmap.unittestHasBuffer());
422 BitmapBuffer* buffer1 = bitmap.AcquireBuffer(BitmapAccessMode::Read);
423 CPPUNIT_ASSERT(bitmap.unittestHasBuffer());
424 bitmap.ReleaseBuffer(buffer1, BitmapAccessMode::Read);
425 CPPUNIT_ASSERT_EQUAL(Size(60, 60), bitmap.GetSize());
426 // Scale the copy before the buffer was created (this time it should convert from non-alpha image
427 // because of the different size).
428 CPPUNIT_ASSERT(!bitmapCopy.unittestHasBuffer());
429 CPPUNIT_ASSERT(bitmapCopy.Scale(4.0, 4.0, BmpScaleFlag::Fast));
430 BitmapBuffer* buffer2 = bitmapCopy.AcquireBuffer(BitmapAccessMode::Read);
431 CPPUNIT_ASSERT(bitmapCopy.unittestHasBuffer());
432 bitmapCopy.ReleaseBuffer(buffer2, BitmapAccessMode::Read);
433 CPPUNIT_ASSERT_EQUAL(Size(240, 240), bitmapCopy.GetSize());
436 void SkiaTest::testDrawDelayedScaleImage()
438 if (!SkiaHelper::isVCLSkiaEnabled())
439 return;
440 if (SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster)
441 return; // This test tests caching that's done only in raster mode.
442 ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
443 device->SetOutputSizePixel(Size(10, 10));
444 device->SetBackground(Wallpaper(COL_WHITE));
445 device->Erase();
446 Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
447 bitmap.Erase(COL_RED);
448 // Set a pixel to create pixel data.
449 BitmapWriteAccess(bitmap).SetPixel(0, 0, COL_BLUE);
450 SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
451 // Force creating of image.
452 sk_sp<SkImage> image1 = skiaBitmap1->GetSkImage();
453 CPPUNIT_ASSERT(skiaBitmap1->unittestHasImage());
454 CPPUNIT_ASSERT(bitmap.Scale(Size(5, 5)));
455 // Make sure delayed scaling has not changed the image.
456 SkiaSalBitmap* skiaBitmap2 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
457 CPPUNIT_ASSERT(skiaBitmap2->unittestHasImage());
458 sk_sp<SkImage> image2 = skiaBitmap2->GetSkImage(SkiaHelper::DirectImage::Yes);
459 CPPUNIT_ASSERT_EQUAL(image1, image2);
460 CPPUNIT_ASSERT_EQUAL(Size(5, 5), bitmap.GetSizePixel());
461 CPPUNIT_ASSERT_EQUAL(Size(10, 10), SkiaHelper::imageSize(image2));
462 // Draw the bitmap scaled to size 10x10 and check that the 10x10 image was used (and kept),
463 // even though technically the bitmap is 5x5.
464 device->DrawBitmap(Point(0, 0), Size(10, 10), bitmap);
465 SkiaSalBitmap* skiaBitmap3 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
466 CPPUNIT_ASSERT(skiaBitmap3->unittestHasImage());
467 sk_sp<SkImage> image3 = skiaBitmap3->GetSkImage(SkiaHelper::DirectImage::Yes);
468 CPPUNIT_ASSERT_EQUAL(image1, image3);
469 CPPUNIT_ASSERT_EQUAL(Size(5, 5), bitmap.GetSizePixel());
470 CPPUNIT_ASSERT_EQUAL(Size(10, 10), SkiaHelper::imageSize(image3));
473 void SkiaTest::testChecksum()
475 if (!SkiaHelper::isVCLSkiaEnabled())
476 return;
477 Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
478 bitmap.Erase(COL_RED);
479 BitmapChecksum checksum1 = bitmap.GetChecksum();
480 // Set a pixel to create pixel data, that should change checksum.
481 BitmapWriteAccess(bitmap).SetPixel(0, 0, COL_BLUE);
482 BitmapChecksum checksum2 = bitmap.GetChecksum();
483 CPPUNIT_ASSERT(checksum2 != checksum1);
484 SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
485 // Creating an image should not change the checksum.
486 sk_sp<SkImage> image1 = skiaBitmap1->GetSkImage();
487 BitmapChecksum checksum3 = bitmap.GetChecksum();
488 CPPUNIT_ASSERT_EQUAL(checksum2, checksum3);
489 // Delayed scaling should change checksum even if the scaling has not taken place.
490 bitmap.Scale(Size(20, 20));
491 BitmapChecksum checksum4 = bitmap.GetChecksum();
492 CPPUNIT_ASSERT(checksum4 != checksum3);
493 // Setting back to the original red content should have the original checksum.
494 // (This also makes sure this next step is not affected by the delayed scaling
495 // above possibly taking place now.)
496 bitmap = Bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
497 bitmap.Erase(COL_RED);
498 BitmapChecksum checksum5 = bitmap.GetChecksum();
499 CPPUNIT_ASSERT_EQUAL(checksum1, checksum5);
500 // The optimized changing of images to greyscale should change the checksum.
501 SkiaSalBitmap* skiaBitmap2 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
502 skiaBitmap2->unittestResetToImage();
503 BitmapChecksum checksum6 = skiaBitmap2->GetChecksum();
504 CPPUNIT_ASSERT_EQUAL(checksum5, checksum6);
505 CPPUNIT_ASSERT(skiaBitmap2->ConvertToGreyscale());
506 BitmapChecksum checksum7 = skiaBitmap2->GetChecksum();
507 CPPUNIT_ASSERT(checksum7 != checksum6);
510 void SkiaTest::testTdf137329()
512 if (!SkiaHelper::isVCLSkiaEnabled())
513 return;
514 // Draw a filled polygon in the entire device, with AA enabled.
515 // All pixels in the device should be black, even those at edges (i.e. not affected by AA).
516 ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
517 device->SetOutputSizePixel(Size(10, 10));
518 device->SetBackground(Wallpaper(COL_WHITE));
519 device->SetAntialiasing(AntialiasingFlags::Enable);
520 device->Erase();
521 device->SetLineColor();
522 device->SetFillColor(COL_BLACK);
523 device->DrawPolyPolygon(
524 basegfx::B2DPolyPolygon(basegfx::B2DPolygon{ { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } }));
525 // savePNG("/tmp/tdf137329.png", device);
526 CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0)));
527 CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 0)));
528 CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9)));
529 CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 9)));
530 CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(4, 4)));
533 void SkiaTest::testTdf140848()
535 if (!SkiaHelper::isVCLSkiaEnabled())
536 return;
537 ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
538 device->SetOutputSizePixel(Size(1300, 400));
539 device->SetBackground(Wallpaper(COL_BLACK));
540 device->SetAntialiasing(AntialiasingFlags::Enable);
541 device->Erase();
542 device->SetLineColor();
543 device->SetFillColor(COL_WHITE);
544 basegfx::B2DPolygon p1 = { { 952.73121259842514519, 102.4599685039370911 },
545 { 952.73121259842514519, 66.55445669291347599 },
546 { 1239.9753070866140661, 66.554456692913390725 },
547 { 1239.9753070866140661, 138.36548031496062094 },
548 { 952.73121259842514519, 138.36548031496070621 } };
549 basegfx::B2DPolygon p2 = { { 1168.1642834645670064, 210.17650393700790801 },
550 { 1168.1642834645670064, 66.554456692913404936 },
551 { 1239.9753070866140661, 66.554456692913390725 },
552 { 1239.9753070866142934, 353.79855118110236845 },
553 { 1168.1642834645670064, 353.79855118110236845 } };
554 device->DrawPolyPolygon(basegfx::B2DPolyPolygon(p1));
555 device->DrawPolyPolygon(basegfx::B2DPolyPolygon(p2));
556 //savePNG("/tmp/tdf140848.png", device);
557 // Rounding errors caused the overlapping part not to be drawn.
558 CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(1200, 100)));
561 void SkiaTest::testTdf132367()
563 if (!SkiaHelper::isVCLSkiaEnabled())
564 return;
565 ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT);
566 device->SetOutputSizePixel(Size(2, 2));
567 device->SetBackground(Wallpaper(COL_BLACK));
568 device->Erase();
569 device->DrawPixel(Point(1, 1), COL_WHITE);
570 // This will make the bitmap store data in SkImage.
571 Bitmap bitmap = device->GetBitmap(Point(0, 0), Size(2, 2));
572 // Scaling will only set up delayed scaling of the SkImage.
573 bitmap.Scale(Size(4, 4), BmpScaleFlag::NearestNeighbor);
574 // Now it will need to be converted to pixel buffer, check it's converted properly
575 // from the SkImage.
576 BitmapReadAccess access(bitmap);
577 CPPUNIT_ASSERT_EQUAL(tools::Long(4), access.Width());
578 CPPUNIT_ASSERT_EQUAL(tools::Long(4), access.Height());
579 CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access.GetColor(3, 3));
582 } // namespace
584 CPPUNIT_TEST_SUITE_REGISTRATION(SkiaTest);
586 CPPUNIT_PLUGIN_IMPLEMENT();
588 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */