/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// This tests backends that use Skia (i.e. intentionally not the svp one, which is the default.) // Note that you still may need to actually set for Skia to be used (see vcl/README.vars). // If Skia is not enabled, all tests will be silently skipped. namespace
{ class SkiaTest : public test::BootstrapFixture
{ public:
SkiaTest()
: test::BootstrapFixture(true, false)
{
}
// Test with images set.
alpha.Erase(64);
BitmapScopedReadAccess(alpha)->GetColor(0, 0); // Reading a pixel will create pixel data.
skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.GetBitmap().ImplGetSalBitmap().get());
skiaAlpha->GetSkImage();
CPPUNIT_ASSERT(!skiaAlpha->unittestHasEraseColor());
CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
bitmap.Erase(64);
BitmapScopedReadAccess(bitmap)->GetColor(0, 0); // Reading a pixel will create pixel data.
skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.GetBitmap().ImplGetSalBitmap().get());
skiaBitmap->GetSkImage();
CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
alpha.BlendWith(bitmap);
skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.GetBitmap().ImplGetSalBitmap().get());
CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(255 - 112),
BitmapScopedReadAccess(alpha)->GetPixelIndex(0, 0));
// Test with erase color for alpha and image for other bitmap.
alpha.Erase(64);
skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.GetBitmap().ImplGetSalBitmap().get());
CPPUNIT_ASSERT(skiaAlpha->unittestHasEraseColor());
bitmap.Erase(64);
BitmapScopedReadAccess(bitmap)->GetColor(0, 0); // Reading a pixel will create pixel data.
skiaBitmap = dynamic_cast<SkiaSalBitmap*>(bitmap.GetBitmap().ImplGetSalBitmap().get());
skiaBitmap->GetSkImage();
CPPUNIT_ASSERT(!skiaBitmap->unittestHasEraseColor());
CPPUNIT_ASSERT(skiaBitmap->unittestHasImage());
alpha.BlendWith(bitmap);
skiaAlpha = dynamic_cast<SkiaSalBitmap*>(alpha.GetBitmap().ImplGetSalBitmap().get());
CPPUNIT_ASSERT(skiaAlpha->unittestHasImage());
CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, alpha.getPixelFormat());
CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt8>(255 - 112),
BitmapScopedReadAccess(alpha)->GetPixelIndex(0, 0));
}
void SkiaTest::testBitmapCopyOnWrite()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return;
SkiaSalBitmap bitmap;
CPPUNIT_ASSERT(bitmap.Create(Size(10, 10), vcl::PixelFormat::N24_BPP, BitmapPalette()));
bitmap.GetSkImage();
bitmap.GetAlphaSkImage();
CPPUNIT_ASSERT(bitmap.unittestHasBuffer());
CPPUNIT_ASSERT(bitmap.unittestHasImage());
CPPUNIT_ASSERT(bitmap.unittestHasAlphaImage());
SkiaSalBitmap bitmap2;
CPPUNIT_ASSERT(bitmap2.Create(bitmap)); // Data should be shared.
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetBuffer(), bitmap2.unittestGetBuffer());
CPPUNIT_ASSERT(bitmap2.unittestHasImage());
CPPUNIT_ASSERT(bitmap2.unittestHasAlphaImage());
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), bitmap2.unittestGetImage());
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), bitmap2.unittestGetAlphaImage()); // Reading still should keep the data shared. const SkImage* oldImage = bitmap.unittestGetImage(); const SkImage* oldAlphaImage = bitmap.unittestGetAlphaImage();
BitmapBuffer* buffer = bitmap.AcquireBuffer(BitmapAccessMode::Read);
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetBuffer(), bitmap2.unittestGetBuffer());
bitmap.ReleaseBuffer(buffer, BitmapAccessMode::Read); // Images get possibly updated only after releasing the buffer.
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), bitmap2.unittestGetImage());
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), bitmap2.unittestGetAlphaImage());
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetImage(), oldImage);
CPPUNIT_ASSERT_EQUAL(bitmap.unittestGetAlphaImage(), oldAlphaImage); // Writing should unshare.
buffer = bitmap.AcquireBuffer(BitmapAccessMode::Write);
CPPUNIT_ASSERT(bitmap.unittestGetBuffer() != bitmap2.unittestGetBuffer());
bitmap.ReleaseBuffer(buffer, BitmapAccessMode::Write);
CPPUNIT_ASSERT(bitmap.unittestGetImage() != bitmap2.unittestGetImage());
CPPUNIT_ASSERT(bitmap.unittestGetAlphaImage() != bitmap2.unittestGetAlphaImage());
CPPUNIT_ASSERT(bitmap.unittestGetImage() != oldImage);
CPPUNIT_ASSERT(bitmap.unittestGetAlphaImage() != oldAlphaImage);
}
void SkiaTest::testMatrixQuality()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return; // Not changing the size (but possibly rotated/flipped) does not need high quality transformations.
CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix()));
CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(90)));
CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(180)));
CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(270)));
CPPUNIT_ASSERT(!SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(1, -1)));
CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(0, -1)));
CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::Scale(2, 1)));
CPPUNIT_ASSERT(SkiaTests::matrixNeedsHighQuality(SkMatrix::RotateDeg(89)));
}
void SkiaTest::testDelayedScaleAlphaImage()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return; auto bitmapTmp = std::make_unique<SkiaSalBitmap>();
CPPUNIT_ASSERT(bitmapTmp->Create(Size(10, 10), vcl::PixelFormat::N24_BPP, BitmapPalette()));
bitmapTmp->Erase(COL_RED); // Create a bitmap that has only an image, not a pixel buffer.
SkiaSalBitmap bitmap(bitmapTmp->GetSkImage());
bitmapTmp.release();
CPPUNIT_ASSERT(!bitmap.unittestHasBuffer());
CPPUNIT_ASSERT(bitmap.unittestHasImage());
CPPUNIT_ASSERT(!bitmap.unittestHasAlphaImage()); // Set up pending scale.
CPPUNIT_ASSERT(bitmap.Scale(2.0, 2.0, BmpScaleFlag::Fast));
CPPUNIT_ASSERT(bitmap.unittestHasPendingScale());
CPPUNIT_ASSERT(bitmap.InterpretAs8Bit()); // Ask for SkImage and make sure it's scaled up.
sk_sp<SkImage> image = bitmap.GetSkImage();
CPPUNIT_ASSERT_EQUAL(20, image->width()); // Ask again, this time it should be cached.
sk_sp<SkImage> image2 = bitmap.GetSkImage();
CPPUNIT_ASSERT_EQUAL(image.get(), image2.get()); // Add another scale.
CPPUNIT_ASSERT(bitmap.Scale(3.0, 3.0, BmpScaleFlag::Fast)); // Ask for alpha SkImage and make sure it's scaled up.
sk_sp<SkImage> alphaImage = bitmap.GetAlphaSkImage();
CPPUNIT_ASSERT_EQUAL(60, alphaImage->width()); // Ask again, this time it should be cached.
sk_sp<SkImage> alphaImage2 = bitmap.GetAlphaSkImage();
CPPUNIT_ASSERT_EQUAL(alphaImage.get(), alphaImage2.get()); // Ask again for non-alpha image, it should be scaled again.
sk_sp<SkImage> image3 = bitmap.GetSkImage();
CPPUNIT_ASSERT_EQUAL(60, image3->width());
CPPUNIT_ASSERT(image3.get() != image2.get());
CPPUNIT_ASSERT(image3.get() != image.get()); // Create pixel buffer from the image (it should convert from alpha image because the bitmap is 8bpp // and the alpha image size matches).
SkiaSalBitmap bitmapCopy;
bitmapCopy.Create(bitmap);
CPPUNIT_ASSERT(!bitmap.unittestHasBuffer());
BitmapBuffer* buffer1 = bitmap.AcquireBuffer(BitmapAccessMode::Read);
CPPUNIT_ASSERT(bitmap.unittestHasBuffer());
bitmap.ReleaseBuffer(buffer1, BitmapAccessMode::Read);
CPPUNIT_ASSERT_EQUAL(Size(60, 60), bitmap.GetSize()); // Scale the copy before the buffer was created (this time it should convert from non-alpha image // because of the different size).
CPPUNIT_ASSERT(!bitmapCopy.unittestHasBuffer());
CPPUNIT_ASSERT(bitmapCopy.Scale(4.0, 4.0, BmpScaleFlag::Fast));
BitmapBuffer* buffer2 = bitmapCopy.AcquireBuffer(BitmapAccessMode::Read);
CPPUNIT_ASSERT(bitmapCopy.unittestHasBuffer());
bitmapCopy.ReleaseBuffer(buffer2, BitmapAccessMode::Read);
CPPUNIT_ASSERT_EQUAL(Size(240, 240), bitmapCopy.GetSize());
}
void SkiaTest::testDrawDelayedScaleImage()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return; if (SkiaHelper::renderMethodToUse() != SkiaHelper::RenderRaster) return; // This test tests caching that's done only in raster mode.
ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
device->SetOutputSizePixel(Size(10, 10));
device->SetBackground(Wallpaper(COL_WHITE));
device->Erase();
Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
bitmap.Erase(COL_RED); // Set a pixel to create pixel data.
BitmapWriteAccess(bitmap).SetPixel(0, 0, COL_BLUE);
SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get()); // Force creating of image.
sk_sp<SkImage> image1 = skiaBitmap1->GetSkImage();
CPPUNIT_ASSERT(skiaBitmap1->unittestHasImage());
CPPUNIT_ASSERT(bitmap.Scale(Size(5, 5))); // Make sure delayed scaling has not changed the image.
SkiaSalBitmap* skiaBitmap2 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
CPPUNIT_ASSERT(skiaBitmap2->unittestHasImage());
sk_sp<SkImage> image2 = skiaBitmap2->GetSkImage(SkiaHelper::DirectImage::Yes);
CPPUNIT_ASSERT_EQUAL(image1, image2);
CPPUNIT_ASSERT_EQUAL(Size(5, 5), bitmap.GetSizePixel());
CPPUNIT_ASSERT_EQUAL(Size(10, 10), SkiaHelper::imageSize(image2)); // Draw the bitmap scaled to size 10x10 and check that the 10x10 image was used (and kept), // even though technically the bitmap is 5x5.
device->DrawBitmap(Point(0, 0), Size(10, 10), bitmap);
SkiaSalBitmap* skiaBitmap3 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
CPPUNIT_ASSERT(skiaBitmap3->unittestHasImage());
sk_sp<SkImage> image3 = skiaBitmap3->GetSkImage(SkiaHelper::DirectImage::Yes);
CPPUNIT_ASSERT_EQUAL(image1, image3);
CPPUNIT_ASSERT_EQUAL(Size(5, 5), bitmap.GetSizePixel());
CPPUNIT_ASSERT_EQUAL(Size(10, 10), SkiaHelper::imageSize(image3));
}
void SkiaTest::testChecksum()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return;
Bitmap bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
bitmap.Erase(COL_RED);
BitmapChecksum checksum1 = bitmap.GetChecksum(); // Set a pixel to create pixel data, that should change checksum.
BitmapWriteAccess(bitmap).SetPixel(0, 0, COL_BLUE);
BitmapChecksum checksum2 = bitmap.GetChecksum();
CPPUNIT_ASSERT(checksum2 != checksum1);
SkiaSalBitmap* skiaBitmap1 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get()); // Creating an image should not change the checksum.
sk_sp<SkImage> image1 = skiaBitmap1->GetSkImage();
BitmapChecksum checksum3 = bitmap.GetChecksum();
CPPUNIT_ASSERT_EQUAL(checksum2, checksum3); // Delayed scaling should change checksum even if the scaling has not taken place.
bitmap.Scale(Size(20, 20));
BitmapChecksum checksum4 = bitmap.GetChecksum();
CPPUNIT_ASSERT(checksum4 != checksum3); // Setting back to the original red content should have the original checksum. // (This also makes sure this next step is not affected by the delayed scaling // above possibly taking place now.)
bitmap = Bitmap(Size(10, 10), vcl::PixelFormat::N24_BPP);
bitmap.Erase(COL_RED);
BitmapChecksum checksum5 = bitmap.GetChecksum();
CPPUNIT_ASSERT_EQUAL(checksum1, checksum5); // The optimized changing of images to greyscale should change the checksum.
SkiaSalBitmap* skiaBitmap2 = dynamic_cast<SkiaSalBitmap*>(bitmap.ImplGetSalBitmap().get());
skiaBitmap2->unittestResetToImage();
BitmapChecksum checksum6 = skiaBitmap2->GetChecksum();
CPPUNIT_ASSERT_EQUAL(checksum5, checksum6);
CPPUNIT_ASSERT(skiaBitmap2->ConvertToGreyscale());
BitmapChecksum checksum7 = skiaBitmap2->GetChecksum();
CPPUNIT_ASSERT(checksum7 != checksum6);
}
void SkiaTest::testTdf137329()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return; // Draw a filled polygon in the entire device, with AA enabled. // All pixels in the device should be black, even those at edges (i.e. not affected by AA).
ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
device->SetOutputSizePixel(Size(10, 10));
device->SetBackground(Wallpaper(COL_WHITE));
device->SetAntialiasing(AntialiasingFlags::Enable);
device->Erase();
device->SetLineColor();
device->SetFillColor(COL_BLACK);
device->DrawPolyPolygon(
basegfx::B2DPolyPolygon(basegfx::B2DPolygon{ { 0, 0 }, { 10, 0 }, { 10, 10 }, { 0, 10 } })); // savePNG("/tmp/tdf137329.png", device);
CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0)));
CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 0)));
CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9)));
CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 9)));
CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(4, 4)));
}
void SkiaTest::testTdf132367()
{ if (!SkiaHelper::isVCLSkiaEnabled()) return;
ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::WITHOUT_ALPHA);
device->SetOutputSizePixel(Size(2, 2));
device->SetBackground(Wallpaper(COL_BLACK));
device->Erase();
device->DrawPixel(Point(1, 1), COL_WHITE); // This will make the bitmap store data in SkImage.
Bitmap bitmap = device->GetBitmap(Point(0, 0), Size(2, 2)); // Scaling will only set up delayed scaling of the SkImage.
bitmap.Scale(Size(4, 4), BmpScaleFlag::NearestNeighbor); // Now it will need to be converted to pixel buffer, check it's converted properly // from the SkImage.
BitmapReadAccess access(bitmap);
CPPUNIT_ASSERT_EQUAL(tools::Long(4), access.Width());
CPPUNIT_ASSERT_EQUAL(tools::Long(4), access.Height());
CPPUNIT_ASSERT_EQUAL(BitmapColor(COL_WHITE), access.GetColor(3, 3));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.