summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2021-02-19 18:36:23 +0100
committerLuboš Luňák <l.lunak@collabora.com>2021-02-24 12:40:13 +0100
commit5ba5ac948db1092712ffeaef41983ea5f5dcb5cc (patch)
tree1efc83d9f17c5f458908300eb9d918e665531662 /vcl
parentf57872d2da23c8a3f90c67b6ad4a3ad0f699a276 (diff)
add additional 0-1 alpha argument to DrawTransformedBitmap()
This allows the VCL backends the apply the extra alpha transformation as it sees fit, rather than it being done manually elsewhere (and even if the backend doesn't implement it, at least do it in one place in the function). With the document from tdf#136223, going from slide 2 to slide 3, this easily saves 10-30% of CPU cycles. As an additional bonus, using AlphaMask::BlendWith() rather than AlphaMask::Replace() makes edges of shapes noticeably more smooth. Change-Id: I036dc9b887d6def0c7cdad3982becabdc7cd5206 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111247 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/headless/svpgdi.cxx6
-rw-r--r--vcl/inc/headless/svpgdi.hxx3
-rw-r--r--vcl/inc/qt5/Qt5Graphics.hxx2
-rw-r--r--vcl/inc/quartz/salgdi.h3
-rw-r--r--vcl/inc/salgdi.hxx9
-rw-r--r--vcl/inc/salgdiimpl.hxx3
-rw-r--r--vcl/inc/skia/gdiimpl.hxx2
-rw-r--r--vcl/inc/unx/genpspgraphics.h3
-rw-r--r--vcl/inc/unx/salgdi.h3
-rw-r--r--vcl/inc/win/salgdi.h3
-rw-r--r--vcl/qa/cppunit/BackendTest.cxx36
-rw-r--r--vcl/qt5/Qt5Graphics_GDI.cxx4
-rw-r--r--vcl/quartz/salgdicommon.cxx5
-rw-r--r--vcl/skia/gdiimpl.cxx24
-rw-r--r--vcl/source/gdi/print.cxx3
-rw-r--r--vcl/source/gdi/salgdilayout.cxx9
-rw-r--r--vcl/source/outdev/bitmap.cxx61
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.cxx3
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.hxx3
-rw-r--r--vcl/unx/generic/gdi/salgdi2.cxx5
-rw-r--r--vcl/unx/generic/print/genpspgraphics.cxx3
-rw-r--r--vcl/win/gdi/gdiimpl.cxx6
-rw-r--r--vcl/win/gdi/gdiimpl.hxx3
-rw-r--r--vcl/win/gdi/salgdi_gdiplus.cxx5
24 files changed, 165 insertions, 42 deletions
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 5c713657d755..67f3c9142567 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -752,7 +752,8 @@ bool SvpSalGraphics::drawTransformedBitmap(
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap)
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha)
{
if (pAlphaBitmap && pAlphaBitmap->GetBitCount() != 8 && pAlphaBitmap->GetBitCount() != 1)
{
@@ -760,6 +761,9 @@ bool SvpSalGraphics::drawTransformedBitmap(
return false;
}
+ if( fAlpha != 1.0 )
+ return false;
+
// MM02 try to access buffered BitmapHelper
std::shared_ptr<BitmapHelper> aSurface;
tryToUseSourceBuffer(rSourceBitmap, aSurface);
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index a0a20e508d72..e14279978d6d 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -144,7 +144,8 @@ protected:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
virtual bool drawAlphaRect( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt8 nTransparency ) override;
diff --git a/vcl/inc/qt5/Qt5Graphics.hxx b/vcl/inc/qt5/Qt5Graphics.hxx
index 87ffc938becf..e90731179d53 100644
--- a/vcl/inc/qt5/Qt5Graphics.hxx
+++ b/vcl/inc/qt5/Qt5Graphics.hxx
@@ -154,7 +154,7 @@ public:
bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap, double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
virtual bool drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth,
diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h
index b3df7550ebf9..421cbffba55b 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -294,7 +294,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index 44ddf34a50ff..494f03eef5a5 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -414,6 +414,7 @@ public:
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
const SalBitmap* pAlphaBitmap,
+ double fAlpha,
const OutputDevice& rOutDev );
bool HasFastDrawTransformedBitmap() const;
@@ -574,13 +575,17 @@ protected:
const SalBitmap& rSourceBitmap,
const SalBitmap& rAlphaBitmap ) = 0;
- /** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
+ /** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system
+
+ @param fAlpha additional alpha (0 to 1) to apply while drawing
+ */
virtual bool drawTransformedBitmap(
const basegfx::B2DPoint& rNull,
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) = 0;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) = 0;
/// Used e.g. by canvas to know whether to cache the drawing.
virtual bool hasFastDrawTransformedBitmap() const = 0;
diff --git a/vcl/inc/salgdiimpl.hxx b/vcl/inc/salgdiimpl.hxx
index eb1508dcf7d6..8b310c586e1a 100644
--- a/vcl/inc/salgdiimpl.hxx
+++ b/vcl/inc/salgdiimpl.hxx
@@ -194,7 +194,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) = 0;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) = 0;
/// Used e.g. by canvas to know whether to cache the drawing.
virtual bool hasFastDrawTransformedBitmap() const = 0;
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index 53a9a0ae0978..64707e35d134 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -174,7 +174,7 @@ public:
/** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
virtual bool drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap, double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
diff --git a/vcl/inc/unx/genpspgraphics.h b/vcl/inc/unx/genpspgraphics.h
index a572a9013c63..d3ff919a9778 100644
--- a/vcl/inc/unx/genpspgraphics.h
+++ b/vcl/inc/unx/genpspgraphics.h
@@ -189,7 +189,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
virtual bool drawAlphaRect( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight,
sal_uInt8 nTransparency ) override;
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index d8e175750813..41e0f57598c8 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -246,7 +246,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index ca04f2469d66..21f1b46ec016 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -289,7 +289,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx
index 56796f8b68c3..018541aa40ab 100644
--- a/vcl/qa/cppunit/BackendTest.cxx
+++ b/vcl/qa/cppunit/BackendTest.cxx
@@ -465,6 +465,41 @@ public:
CPPUNIT_ASSERT(eResult != vcl::test::TestResult::Failed);
}
+ void testDrawTransformedBitmapExAlpha()
+ {
+ ScopedVclPtrInstance<VirtualDevice> device;
+ device->SetOutputSizePixel(Size(16, 16));
+ device->SetBackground(Wallpaper(COL_WHITE));
+ device->Erase();
+ Bitmap aBitmap(Size(16, 16), 24);
+ {
+ // Fill the top left quarter with black.
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ pWriteAccess->Erase(COL_WHITE);
+ for (int i = 0; i < 8; ++i)
+ for (int j = 0; j < 8; ++j)
+ pWriteAccess->SetPixel(j, i, COL_BLACK);
+ }
+ BitmapEx aBitmapEx(aBitmap);
+ basegfx::B2DHomMatrix aMatrix;
+ // Draw with no transformation, only alpha change.
+ aMatrix.scale(16, 16);
+ device->DrawTransformedBitmapEx(aMatrix, aBitmapEx, 0.5);
+ BitmapEx result = device->GetBitmapEx(Point(0, 0), Size(16, 16));
+ CPPUNIT_ASSERT_EQUAL(Color(0x80, 0x80, 0x80), result.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, result.GetPixelColor(15, 15));
+ // Draw rotated and move to the bottom-left corner.
+ device->Erase();
+ aMatrix.identity();
+ aMatrix.scale(16, 16);
+ aMatrix.rotate(M_PI / 2);
+ aMatrix.translate(8, 8);
+ device->DrawTransformedBitmapEx(aMatrix, aBitmapEx, 0.5);
+ result = device->GetBitmap(Point(0, 0), Size(16, 16));
+ CPPUNIT_ASSERT_EQUAL(COL_WHITE, result.GetPixelColor(0, 0));
+ CPPUNIT_ASSERT_EQUAL(Color(0x80, 0x80, 0x80), result.GetPixelColor(0, 15));
+ }
+
void testClipRectangle()
{
vcl::test::OutputDeviceTestClip aOutDevTest;
@@ -877,6 +912,7 @@ public:
CPPUNIT_TEST(testDrawMask);
CPPUNIT_TEST(testDrawBlend);
CPPUNIT_TEST(testDrawXor);
+ CPPUNIT_TEST(testDrawTransformedBitmapExAlpha);
CPPUNIT_TEST(testClipRectangle);
CPPUNIT_TEST(testClipPolygon);
diff --git a/vcl/qt5/Qt5Graphics_GDI.cxx b/vcl/qt5/Qt5Graphics_GDI.cxx
index fbcc3d32d0d9..fabed0b3047b 100644
--- a/vcl/qt5/Qt5Graphics_GDI.cxx
+++ b/vcl/qt5/Qt5Graphics_GDI.cxx
@@ -626,8 +626,10 @@ bool Qt5Graphics::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBitmap& rS
bool Qt5Graphics::drawTransformedBitmap(const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY, const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap)
+ const SalBitmap* pAlphaBitmap, double fAlpha)
{
+ if (fAlpha != 1.0)
+ return false;
QImage aImage;
if (pAlphaBitmap && !getAlphaImage(rSourceBitmap, *pAlphaBitmap, aImage))
return false;
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index b74dbda15360..d82681f1091f 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -330,11 +330,14 @@ bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
bool AquaSalGraphics::drawTransformedBitmap(
const basegfx::B2DPoint& rNull, const basegfx::B2DPoint& rX, const basegfx::B2DPoint& rY,
- const SalBitmap& rSrcBitmap, const SalBitmap* pAlphaBmp )
+ const SalBitmap& rSrcBitmap, const SalBitmap* pAlphaBmp, double fAlpha )
{
if( !CheckContext() )
return true;
+ if( fAlpha != 1.0 )
+ return false;
+
// get the Quartz image
CGImageRef xImage = nullptr;
const Size aSize = rSrcBitmap.GetSize();
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index d8077df48a68..950010183cb1 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -1762,7 +1762,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap)
+ const SalBitmap* pAlphaBitmap, double fAlpha)
{
assert(dynamic_cast<const SkiaSalBitmap*>(&rSourceBitmap));
assert(!pAlphaBitmap || dynamic_cast<const SkiaSalBitmap*>(pAlphaBitmap));
@@ -1787,6 +1787,8 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
// so use mergeCacheBitmaps(), which will cache the result if useful.
// It is better to use SkShader if in GPU mode, if the operation is simple or if the temporary
// image would be very large.
+ // The extra fAlpha blending is not cached, with the assumption that it usually gradually changes
+ // for each invocation.
sk_sp<SkImage> imageToDraw = mergeCacheBitmaps(
rSkiaBitmap, pSkiaAlphaBitmap, Size(round(aXRel.getLength()), round(aYRel.getLength())));
if (imageToDraw)
@@ -1808,7 +1810,15 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
SkPaint paint;
if (!matrix.isTranslate())
paint.setFilterQuality(kHigh_SkFilterQuality);
- canvas->drawImage(imageToDraw, 0, 0, &paint);
+ if (fAlpha == 1.0)
+ canvas->drawImage(imageToDraw, 0, 0, &paint);
+ else
+ {
+ paint.setShader(
+ SkShaders::Blend(SkBlendMode::kDstIn, imageToDraw->makeShader(),
+ SkShaders::Color(SkColorSetARGB(fAlpha * 255, 0, 0, 0))));
+ canvas->drawRect(SkRect::MakeWH(imageToDraw->width(), imageToDraw->height()), paint);
+ }
}
else
{
@@ -1831,11 +1841,19 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull,
paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, // VCL alpha is one-minus-alpha.
rSkiaBitmap.GetSkShader(),
pSkiaAlphaBitmap->GetAlphaSkShader()));
+ if (fAlpha != 1.0)
+ paint.setShader(
+ SkShaders::Blend(SkBlendMode::kDstIn, paint.refShader(),
+ SkShaders::Color(SkColorSetARGB(fAlpha * 255, 0, 0, 0))));
canvas->drawRect(SkRect::MakeWH(aSize.Width(), aSize.Height()), paint);
}
- else if (rSkiaBitmap.PreferSkShader())
+ else if (rSkiaBitmap.PreferSkShader() || fAlpha != 1.0)
{
paint.setShader(rSkiaBitmap.GetSkShader());
+ if (fAlpha != 1.0)
+ paint.setShader(
+ SkShaders::Blend(SkBlendMode::kDstIn, paint.refShader(),
+ SkShaders::Color(SkColorSetARGB(fAlpha * 255, 0, 0, 0))));
canvas->drawRect(SkRect::MakeWH(aSize.Width(), aSize.Height()), paint);
}
else
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
index 41548a91c60c..55c0bbdeaac8 100644
--- a/vcl/source/gdi/print.cxx
+++ b/vcl/source/gdi/print.cxx
@@ -275,7 +275,8 @@ void Printer::ImplPrintTransparent( const Bitmap& rBmp, const Bitmap& rMask,
bool Printer::DrawTransformBitmapExDirect(
const basegfx::B2DHomMatrix& /*aFullTransform*/,
- const BitmapEx& /*rBitmapEx*/)
+ const BitmapEx& /*rBitmapEx*/,
+ double /*fAlpha*/)
{
// printers can't draw bitmaps directly
return false;
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index d019b93e816b..adf26d97d9ac 100644
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -28,6 +28,7 @@
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <FileDefinitionWidgetDraw.hxx>
+#include <rtl/math.hxx>
// The only common SalFrame method
@@ -87,7 +88,8 @@ bool SalGraphics::drawTransformedBitmap(
const basegfx::B2DPoint& /* rX */,
const basegfx::B2DPoint& /* rY */,
const SalBitmap& /* rSourceBitmap */,
- const SalBitmap* /* pAlphaBitmap */)
+ const SalBitmap* /* pAlphaBitmap */,
+ double /* fAlpha */)
{
// here direct support for transformed bitmaps can be implemented
return false;
@@ -836,6 +838,7 @@ bool SalGraphics::DrawTransformedBitmap(
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
const SalBitmap* pAlphaBitmap,
+ double fAlpha,
const OutputDevice& rOutDev)
{
if( (m_nLayout & SalLayoutFlags::BiDiRtl) || rOutDev.IsRTLEnabled() )
@@ -852,11 +855,11 @@ bool SalGraphics::DrawTransformedBitmap(
basegfx::B2DPoint aX = aTranslateToMirroredBounds * rX;
basegfx::B2DPoint aY = aTranslateToMirroredBounds * rY;
- return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, pAlphaBitmap);
+ return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, pAlphaBitmap, fAlpha);
}
}
- return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap);
+ return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap, fAlpha);
}
bool SalGraphics::HasFastDrawTransformedBitmap() const
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index 8f4fbef24ee0..563989cc366d 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -1052,7 +1052,8 @@ void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap,
bool OutputDevice::DrawTransformBitmapExDirect(
const basegfx::B2DHomMatrix& aFullTransform,
- const BitmapEx& rBitmapEx)
+ const BitmapEx& rBitmapEx,
+ double fAlpha)
{
assert(!is_double_buffered_window());
@@ -1090,14 +1091,15 @@ bool OutputDevice::DrawTransformBitmapExDirect(
aTopY,
*pSalSrcBmp,
pSalAlphaBmp,
+ fAlpha,
*this);
if (mpAlphaVDev)
{
// Merge bitmap alpha to alpha device
- AlphaMask aBlack(rBitmapEx.GetSizePixel());
- aBlack.Erase(0); // opaque
- mpAlphaVDev->DrawTransformBitmapExDirect(aFullTransform, BitmapEx(aBlack, aAlphaBitmap));
+ AlphaMask aAlpha(rBitmapEx.GetSizePixel());
+ aAlpha.Erase( ( 1 - fAlpha ) * 255 );
+ mpAlphaVDev->DrawTransformBitmapExDirect(aFullTransform, BitmapEx(aAlpha, aAlphaBitmap));
}
return bDone;
@@ -1212,7 +1214,8 @@ struct LocalTimeTest
void OutputDevice::DrawTransformedBitmapEx(
const basegfx::B2DHomMatrix& rTransformation,
- const BitmapEx& rBitmapEx)
+ const BitmapEx& rBitmapEx,
+ double fAlpha)
{
assert(!is_double_buffered_window());
@@ -1222,6 +1225,9 @@ void OutputDevice::DrawTransformedBitmapEx(
if(rBitmapEx.IsEmpty())
return;
+ if(rtl::math::approxEqual( fAlpha, 0.0 ))
+ return;
+
// MM02 compared to other public methods of OutputDevice
// this test was missing and led to zero-ptr-accesses
if ( !mpGraphics && !AcquireGraphics() )
@@ -1254,6 +1260,38 @@ void OutputDevice::DrawTransformedBitmapEx(
: nullptr);
#endif
+ BitmapEx bitmapEx = rBitmapEx;
+
+ const bool bInvert(RasterOp::Invert == meRasterOp);
+ const bool bBitmapChangedColor(mnDrawMode & (DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap | DrawModeFlags::GrayBitmap ));
+ const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile);
+
+ // First try to handle additional alpha blending, either directly, or modify the bitmap.
+ if(!rtl::math::approxEqual( fAlpha, 1.0 ))
+ {
+ if(bTryDirectPaint)
+ {
+ // tdf#130768 CAUTION(!) using GetViewTransformation() is *not* enough here, it may
+ // be that mnOutOffX/mnOutOffY is used - see AOO bug 75163, mentioned at
+ // ImplGetDeviceTransformation declaration
+ const basegfx::B2DHomMatrix aFullTransform(ImplGetDeviceTransformation() * rTransformation);
+
+ if(DrawTransformBitmapExDirect(aFullTransform, bitmapEx, fAlpha))
+ {
+ // we are done
+ return;
+ }
+ }
+ // Apply the alpha manually.
+ sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
+ AlphaMask aAlpha( bitmapEx.GetSizePixel(), &nColor );
+ if( bitmapEx.IsTransparent())
+ aAlpha.BlendWith( bitmapEx.GetAlpha());
+ bitmapEx = BitmapEx( bitmapEx.GetBitmap(), aAlpha );
+ }
+ if(rtl::math::approxEqual( fAlpha, 1.0 ))
+ fAlpha = 1.0; // avoid the need for approxEqual in backends
+
// decompose matrix to check rotation and shear
basegfx::B2DVector aScale, aTranslate;
double fRotate, fShearX;
@@ -1279,7 +1317,7 @@ void OutputDevice::DrawTransformedBitmapEx(
EnableMapMode(false);
}
- DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
+ DrawBitmapEx(aDestPt, aDestSize, bitmapEx);
if (!bMetafile && comphelper::LibreOfficeKit::isActive() && GetMapMode().GetMapUnit() != MapUnit::MapPixel)
{
EnableMapMode();
@@ -1288,9 +1326,6 @@ void OutputDevice::DrawTransformedBitmapEx(
return;
}
- const bool bInvert(RasterOp::Invert == meRasterOp);
- const bool bBitmapChangedColor(mnDrawMode & (DrawModeFlags::BlackBitmap | DrawModeFlags::WhiteBitmap | DrawModeFlags::GrayBitmap ));
- const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile);
if(bTryDirectPaint)
{
// tdf#130768 CAUTION(!) using GetViewTransformation() is *not* enough here, it may
@@ -1298,7 +1333,7 @@ void OutputDevice::DrawTransformedBitmapEx(
// ImplGetDeviceTransformation declaration
const basegfx::B2DHomMatrix aFullTransform(ImplGetDeviceTransformation() * rTransformation);
- if(DrawTransformBitmapExDirect(aFullTransform, rBitmapEx))
+ if(DrawTransformBitmapExDirect(aFullTransform, bitmapEx))
{
// we are done
return;
@@ -1316,7 +1351,7 @@ void OutputDevice::DrawTransformedBitmapEx(
basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
- DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
+ DrawBitmapEx(aDestPt, aDestSize, bitmapEx);
return;
}
@@ -1331,7 +1366,7 @@ void OutputDevice::DrawTransformedBitmapEx(
// by using a fixed minimum (allow at least, but no need to utilize) for good smoothing and an area
// dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
// to avoid crashes/resource problems (ca. 1500x3000 here)
- const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel());
+ const Size& rOriginalSizePixel(bitmapEx.GetSizePixel());
const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
const double fOrigAreaScaled(fOrigArea * 1.44);
double fMaximumArea(std::clamp(fOrigAreaScaled, 1000000.0, 4500000.0));
@@ -1349,7 +1384,7 @@ void OutputDevice::DrawTransformedBitmapEx(
if(aVisibleRange.isEmpty())
return;
- BitmapEx aTransformed(rBitmapEx);
+ BitmapEx aTransformed(bitmapEx);
// #122923# when the result needs an alpha channel due to being rotated or sheared
// and thus uncovering areas, add these channels so that the own transformer (used
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index 680a9e5d14b8..5838c1aef978 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -845,7 +845,8 @@ bool X11SalGraphicsImpl::drawTransformedBitmap(
const basegfx::B2DPoint&,
const basegfx::B2DPoint&,
const SalBitmap&,
- const SalBitmap*)
+ const SalBitmap*,
+ double)
{
// here direct support for transformed bitmaps can be implemented
return false;
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index dcc4f641f3a3..99499e08b444 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -270,7 +270,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index c4954e9e6119..cfdb272005a5 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -136,9 +136,10 @@ bool X11SalGraphics::drawTransformedBitmap(
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap)
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha)
{
- return mxImpl->drawTransformedBitmap( rNull, rX, rY, rSourceBitmap, pAlphaBitmap );
+ return mxImpl->drawTransformedBitmap( rNull, rX, rY, rSourceBitmap, pAlphaBitmap, fAlpha );
}
bool X11SalGraphics::hasFastDrawTransformedBitmap() const
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
index 4218da4ed53b..eb427b2a73af 100644
--- a/vcl/unx/generic/print/genpspgraphics.cxx
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
@@ -848,7 +848,8 @@ bool GenPspGraphics::drawTransformedBitmap(
const basegfx::B2DPoint&,
const basegfx::B2DPoint&,
const SalBitmap&,
- const SalBitmap*)
+ const SalBitmap*,
+ double)
{
// here direct support for transformed bitmaps can be implemented
return false;
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index 40c7bbbbdb84..cedd5f42a802 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -2649,11 +2649,15 @@ bool WinSalGraphicsImpl::drawTransformedBitmap(
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap)
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha)
{
assert(dynamic_cast<const WinSalBitmap*>(&rSourceBitmap));
assert(!pAlphaBitmap || dynamic_cast<const WinSalBitmap*>(pAlphaBitmap));
+ if( fAlpha != 1.0 )
+ return false;
+
const WinSalBitmap& rSalBitmap = static_cast< const WinSalBitmap& >(rSourceBitmap);
const WinSalBitmap* pSalAlpha = static_cast< const WinSalBitmap* >(pAlphaBitmap);
std::shared_ptr< Gdiplus::Bitmap > aARGB(rSalBitmap.ImplGetGdiPlusBitmap(pSalAlpha));
diff --git a/vcl/win/gdi/gdiimpl.hxx b/vcl/win/gdi/gdiimpl.hxx
index 0d9d9b30ce2c..3f4d13f1c517 100644
--- a/vcl/win/gdi/gdiimpl.hxx
+++ b/vcl/win/gdi/gdiimpl.hxx
@@ -226,7 +226,8 @@ public:
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap) override;
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha) override;
virtual bool hasFastDrawTransformedBitmap() const override;
diff --git a/vcl/win/gdi/salgdi_gdiplus.cxx b/vcl/win/gdi/salgdi_gdiplus.cxx
index 8a85f033783b..13452f5c7a6e 100644
--- a/vcl/win/gdi/salgdi_gdiplus.cxx
+++ b/vcl/win/gdi/salgdi_gdiplus.cxx
@@ -89,10 +89,11 @@ bool WinSalGraphics::drawTransformedBitmap(
const basegfx::B2DPoint& rX,
const basegfx::B2DPoint& rY,
const SalBitmap& rSourceBitmap,
- const SalBitmap* pAlphaBitmap)
+ const SalBitmap* pAlphaBitmap,
+ double fAlpha)
{
return mpImpl->drawTransformedBitmap(rNull, rX, rY,
- rSourceBitmap, pAlphaBitmap);
+ rSourceBitmap, pAlphaBitmap, fAlpha);
}
bool WinSalGraphics::hasFastDrawTransformedBitmap() const