diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2020-09-02 11:45:10 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2020-09-04 17:29:13 +0200 |
commit | c5b6f8d6469850e14362f2c8f08cdf8c956cbf07 (patch) | |
tree | c2805f3ce0e36c26e88d9ba3e44de2d47e0e3461 | |
parent | c4ea034beb2fa0f1e874a39391a9498bdd7c7aad (diff) |
fix erasing virtual device with alpha
The background cannot be simply set as background also for the internal
alpha virtual device, since this hackish alpha uses black = opaque
and white = transparent. So e.g. setting to background to COL_WHITE
actually resulted in the content being transparent.
Try to map to what the alpha virtual device actually needs.
Change-Id: Ie5179769d9bce989eddfc96f5cbd2b94d1d88d53
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101927
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | vcl/qa/cppunit/BackendTest.cxx | 69 | ||||
-rw-r--r-- | vcl/source/outdev/outdevstate.cxx | 39 |
2 files changed, 106 insertions, 2 deletions
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx index 45793434dd1b..0e3d9c54dd08 100644 --- a/vcl/qa/cppunit/BackendTest.cxx +++ b/vcl/qa/cppunit/BackendTest.cxx @@ -49,7 +49,7 @@ class BackendTest : public test::BootstrapFixture { if (mbExportBitmap) { - BitmapEx aBitmapEx(device->GetBitmap(Point(0, 0), device->GetOutputSizePixel())); + BitmapEx aBitmapEx(device->GetBitmapEx(Point(0, 0), device->GetOutputSizePixel())); SvFileStream aStream(filename, StreamMode::WRITE | StreamMode::TRUNC); GraphicFilter::GetGraphicFilter().compressAsPNG(aBitmapEx, aStream); } @@ -517,6 +517,71 @@ public: // vcl::test::OutputDeviceTestGradient does not verify anything, cannot test here + void testErase() + { + { + // Create normal virtual device (no alpha). + ScopedVclPtr<VirtualDevice> device + = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT); + device->SetOutputSizePixel(Size(10, 10)); + // Erase with white, check it's white. + device->SetBackground(Wallpaper(COL_WHITE)); + device->Erase(); + exportDevice("/tmp/12-01_erase.png", device); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(9, 9))); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(5, 5))); + // Erase with black, check it's black. + device->SetBackground(Wallpaper(COL_BLACK)); + device->Erase(); + exportDevice("/tmp/12-02_erase.png", device); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9))); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(5, 5))); + // Erase with cyan, check it's cyan. + device->SetBackground(Wallpaper(COL_CYAN)); + device->Erase(); + exportDevice("/tmp/12-03_erase.png", device); + CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(9, 9))); + CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(5, 5))); + } + { + // Create virtual device with alpha. + ScopedVclPtr<VirtualDevice> device + = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); + device->SetOutputSizePixel(Size(10, 10)); + // Erase with white, check it's white. + device->SetBackground(Wallpaper(COL_WHITE)); + device->Erase(); + exportDevice("/tmp/12-04_erase.png", device); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(9, 9))); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(5, 5))); + // Erase with black, check it's black. + device->SetBackground(Wallpaper(COL_BLACK)); + device->Erase(); + exportDevice("/tmp/12-05_erase.png", device); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(9, 9))); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, device->GetPixel(Point(5, 5))); + // Erase with cyan, check it's cyan. + device->SetBackground(Wallpaper(COL_CYAN)); + device->Erase(); + exportDevice("/tmp/12-06_erase.png", device); + CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(9, 9))); + CPPUNIT_ASSERT_EQUAL(COL_CYAN, device->GetPixel(Point(5, 5))); + // Erase with transparent, check it's transparent. + device->SetBackground(Wallpaper(COL_TRANSPARENT)); + device->Erase(); + exportDevice("/tmp/12-07_erase.png", device); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(255), device->GetPixel(Point(0, 0)).GetTransparency()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(255), device->GetPixel(Point(9, 9)).GetTransparency()); + CPPUNIT_ASSERT_EQUAL(sal_uInt8(255), device->GetPixel(Point(5, 5)).GetTransparency()); + } + } + void testTdf124848() { ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT); @@ -626,6 +691,8 @@ public: CPPUNIT_TEST(testDashedLine); + CPPUNIT_TEST(testErase); + CPPUNIT_TEST(testTdf124848); CPPUNIT_TEST(testTdf136171); diff --git a/vcl/source/outdev/outdevstate.cxx b/vcl/source/outdev/outdevstate.cxx index 804ba883c210..4ab3093b573b 100644 --- a/vcl/source/outdev/outdevstate.cxx +++ b/vcl/source/outdev/outdevstate.cxx @@ -455,7 +455,44 @@ void OutputDevice::SetBackground( const Wallpaper& rBackground ) mbBackground = true; if( mpAlphaVDev ) - mpAlphaVDev->SetBackground( rBackground ); + { + // Some of these are probably wrong (e.g. if the gradient has transparency), + // but hopefully nobody uses that. If you do, feel free to implement it properly. + if( rBackground.GetStyle() == WallpaperStyle::NONE ) + mpAlphaVDev->SetBackground( rBackground ); + else if( rBackground.IsBitmap()) + { + BitmapEx bitmap = rBackground.GetBitmap(); + if( bitmap.IsAlpha()) + mpAlphaVDev->SetBackground( Wallpaper( BitmapEx( Bitmap( bitmap.GetAlpha())))); + else + { + switch( bitmap.GetTransparentType()) + { + case TransparentType::NONE: + mpAlphaVDev->SetBackground( Wallpaper( COL_BLACK )); + break; + case TransparentType::Color: + { + AlphaMask mask( bitmap.GetBitmap().CreateMask( bitmap.GetTransparentColor())); + mpAlphaVDev->SetBackground( Wallpaper( BitmapEx( bitmap.GetBitmap(), mask ))); + break; + } + case TransparentType::Bitmap: + mpAlphaVDev->SetBackground( Wallpaper( BitmapEx( bitmap.GetMask()))); + break; + } + } + } + else if( rBackground.IsGradient()) + mpAlphaVDev->SetBackground( Wallpaper( COL_BLACK )); + else + { + // Color background. + int transparency = rBackground.GetColor().GetTransparency(); + mpAlphaVDev->SetBackground( Wallpaper( Color( transparency, transparency, transparency ))); + } + } } void OutputDevice::SetFont( const vcl::Font& rNewFont ) |