diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/qa/cppunit/BackendTest.cxx | 59 | ||||
-rw-r--r-- | vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx | 38 | ||||
-rw-r--r-- | vcl/source/outdev/bitmap.cxx | 47 |
3 files changed, 112 insertions, 32 deletions
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx index cb2dca9cfe91..1342c3a5ade9 100644 --- a/vcl/qa/cppunit/BackendTest.cxx +++ b/vcl/qa/cppunit/BackendTest.cxx @@ -711,6 +711,64 @@ public: CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(6, 6))); } + void testDrawAlphaBitmapMirrored() + { + // Normal virtual device. + ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT); + // Virtual device with alpha. + ScopedVclPtr<VirtualDevice> alphaDevice + = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT); + device->SetOutputSizePixel(Size(20, 20)); + device->SetBackground(Wallpaper(COL_BLACK)); + device->Erase(); + alphaDevice->SetOutputSizePixel(Size(20, 20)); + alphaDevice->SetBackground(Wallpaper(COL_BLACK)); + alphaDevice->Erase(); + Bitmap bitmap(Size(4, 4), 24); + AlphaMask alpha(Size(4, 4)); + bitmap.Erase(COL_LIGHTBLUE); + { + BitmapScopedWriteAccess writeAccess(bitmap); + writeAccess->SetPixel(3, 3, COL_LIGHTRED); + } + // alpha 127 will make COL_LIGHTRED -> COL_RED and the same for blue + alpha.Erase(127); + // Normal device. + device->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap)); + device->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap)); + exportDevice("/tmp/draw_alpha_bitmap_mirrored_01.png", device); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, device->GetPixel(Point(18, 18))); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, device->GetPixel(Point(17, 18))); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, device->GetPixel(Point(2, 2))); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, device->GetPixel(Point(3, 2))); + device->Erase(); + device->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap, alpha)); + device->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap, alpha)); + exportDevice("/tmp/draw_alpha_bitmap_mirrored_02.png", device); + CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(18, 18))); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(17, 18))); + CPPUNIT_ASSERT_EQUAL(COL_RED, device->GetPixel(Point(2, 2))); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(3, 2))); + device->Erase(); + // Now with alpha device. + alphaDevice->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap)); + alphaDevice->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap)); + exportDevice("/tmp/draw_alpha_bitmap_mirrored_03.png", alphaDevice); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, alphaDevice->GetPixel(Point(18, 18))); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, alphaDevice->GetPixel(Point(17, 18))); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, alphaDevice->GetPixel(Point(2, 2))); + CPPUNIT_ASSERT_EQUAL(COL_LIGHTBLUE, alphaDevice->GetPixel(Point(3, 2))); + alphaDevice->Erase(); + alphaDevice->DrawBitmapEx(Point(5, 5), Size(-4, -4), BitmapEx(bitmap, alpha)); + alphaDevice->DrawBitmapEx(Point(15, 15), Size(4, 4), BitmapEx(bitmap, alpha)); + exportDevice("/tmp/draw_alpha_bitmap_mirrored_04.png", alphaDevice); + CPPUNIT_ASSERT_EQUAL(COL_RED, alphaDevice->GetPixel(Point(18, 18))); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, alphaDevice->GetPixel(Point(17, 18))); + CPPUNIT_ASSERT_EQUAL(COL_RED, alphaDevice->GetPixel(Point(2, 2))); + CPPUNIT_ASSERT_EQUAL(COL_BLUE, alphaDevice->GetPixel(Point(3, 2))); + alphaDevice->Erase(); + } + void testTdf124848() { ScopedVclPtr<VirtualDevice> device = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT); @@ -832,6 +890,7 @@ public: CPPUNIT_TEST(testRadialGradientOfs); CPPUNIT_TEST(testDrawBlendExtended); + CPPUNIT_TEST(testDrawAlphaBitmapMirrored); CPPUNIT_TEST(testTdf124848); CPPUNIT_TEST(testTdf136171); diff --git a/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx b/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx index d13696571a9e..b6bd724910b8 100644 --- a/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx +++ b/vcl/qa/cppunit/bitmaprender/BitmapRenderTest.cxx @@ -101,6 +101,22 @@ void BitmapRenderTest::testTdf113918() CPPUNIT_ASSERT(aColor.GetGreen() > 100); } +#if defined(_WIN32) || defined(MACOSX) || defined(IOS) + +namespace +{ +int deltaColor(BitmapColor aColor1, BitmapColor aColor2) +{ + int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed()); + int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen()); + int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue()); + + return std::max(std::max(deltaR, deltaG), deltaB); +} +} + +#endif + void BitmapRenderTest::testDrawAlphaBitmapEx() { ScopedVclPtrInstance<VirtualDevice> pVDev; @@ -141,28 +157,14 @@ void BitmapRenderTest::testDrawAlphaBitmapEx() CPPUNIT_ASSERT_EQUAL(Color(0x00, 0xFF, 0xFF, 0xFF), pVDev->GetPixel(Point(0, 0))); CPPUNIT_ASSERT_EQUAL(Color(0x00, 0xFF, 0xFF, 0x00), pVDev->GetPixel(Point(1, 1))); -// sometimes on Windows we get rounding error in blending so let's ignore this on Windows for now. -#if !defined(_WIN32) +#if defined(_WIN32) || defined(MACOSX) || defined(IOS) + // sometimes on Windows we get rounding error in blending so let's ignore this on Windows for now. + CPPUNIT_ASSERT_LESS(2, deltaColor(Color(0x00, 0x7F, 0xFF, 0x7F), pVDev->GetPixel(Point(2, 2)))); +#else CPPUNIT_ASSERT_EQUAL(Color(0x00, 0x7F, 0xFF, 0x7F), pVDev->GetPixel(Point(2, 2))); #endif } -#ifdef _WIN32 - -namespace -{ -int deltaColor(BitmapColor aColor1, BitmapColor aColor2) -{ - int deltaR = std::abs(aColor1.GetRed() - aColor2.GetRed()); - int deltaG = std::abs(aColor1.GetGreen() - aColor2.GetGreen()); - int deltaB = std::abs(aColor1.GetBlue() - aColor2.GetBlue()); - - return std::max(std::max(deltaR, deltaG), deltaB); -} -} - -#endif - void BitmapRenderTest::testAlphaVirtualDevice() { // Create an alpha virtual device diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx index a9f264fa2854..bcab1a4d7793 100644 --- a/vcl/source/outdev/bitmap.cxx +++ b/vcl/source/outdev/bitmap.cxx @@ -632,23 +632,34 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r ClipToPaintRegion(aDstRect); + BmpMirrorFlags mirrorFlags = BmpMirrorFlags::NONE; if (bHMirr) { aOutSz.setWidth( -aOutSz.Width() ); aOutPt.AdjustX( -(aOutSz.Width() - 1) ); + mirrorFlags |= BmpMirrorFlags::Horizontal; } if (bVMirr) { aOutSz.setHeight( -aOutSz.Height() ); aOutPt.AdjustY( -(aOutSz.Height() - 1) ); + mirrorFlags |= BmpMirrorFlags::Vertical; } if (aDstRect.Intersection(tools::Rectangle(aOutPt, aOutSz)).IsEmpty()) return; + bool bTryDirectPaint = false; + if(SkiaHelper::isVCLSkiaEnabled()) + bTryDirectPaint = true; +#if HAVE_FEATURE_OPENGL + if(OpenGLHelper::isVCLOpenGLEnabled()) + bTryDirectPaint = true; +#endif static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA"); - bool bTryDirectPaint(!pDisableNative && !bHMirr && !bVMirr); + if(pDisableNative) + bTryDirectPaint = false; if (bTryDirectPaint) { @@ -659,8 +670,15 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r aRelPt.X(), aRelPt.Y(), aOutSz.Width(), aOutSz.Height()); - SalBitmap* pSalSrcBmp = rBmp.ImplGetSalBitmap().get(); - SalBitmap* pSalAlphaBmp = rAlpha.ImplGetSalBitmap().get(); + Bitmap bitmap(rBmp); + AlphaMask alpha(rAlpha); + if(bHMirr || bVMirr) + { + bitmap.Mirror(mirrorFlags); + alpha.Mirror(mirrorFlags); + } + SalBitmap* pSalSrcBmp = bitmap.ImplGetSalBitmap().get(); + SalBitmap* pSalAlphaBmp = alpha.ImplGetSalBitmap().get(); // #i83087# Naturally, system alpha blending (SalGraphics::DrawAlphaBitmap) cannot work // with separate alpha VDev @@ -683,25 +701,26 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r if (mpGraphics->DrawAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, this)) return; } + assert(false); } - // we need to make sure OpenGL never reaches this slow code path - // tdf#136223: The slow code path will be obviously also reached if mirroring - // is used, which makes the block above be skipped, as the blend bitmap calls - // do not handle that case. Given that this seems to be rather rare, just - // disable the assert, until faster mirroring is actually needed. - - assert(!SkiaHelper::isVCLSkiaEnabled() || !bTryDirectPaint); -#if HAVE_FEATURE_OPENGL - assert(!OpenGLHelper::isVCLOpenGLEnabled() || !bTryDirectPaint); -#endif tools::Rectangle aBmpRect(Point(), rBmp.GetSizePixel()); if (!aBmpRect.Intersection(tools::Rectangle(rSrcPtPixel, rSrcSizePixel)).IsEmpty()) { Point auxOutPt(LogicToPixel(rDestPt)); Size auxOutSz(LogicToPixel(rDestSize)); - DrawDeviceAlphaBitmapSlowPath(rBmp, rAlpha, aDstRect, aBmpRect, auxOutSz, auxOutPt); + // HACK: The function is broken with alpha vdev and mirroring, mirror here. + Bitmap bitmap(rBmp); + AlphaMask alpha(rAlpha); + if(mpAlphaVDev && (bHMirr || bVMirr)) + { + bitmap.Mirror(mirrorFlags); + alpha.Mirror(mirrorFlags); + auxOutPt = aOutPt; + auxOutSz = aOutSz; + } + DrawDeviceAlphaBitmapSlowPath(bitmap, alpha, aDstRect, aBmpRect, auxOutSz, auxOutPt); } } |