summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--canvas/source/vcl/canvashelper.cxx5
-rw-r--r--canvas/source/vcl/spritehelper.cxx23
-rw-r--r--include/vcl/outdev.hxx9
-rw-r--r--include/vcl/print.hxx2
-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
28 files changed, 177 insertions, 69 deletions
diff --git a/canvas/source/vcl/canvashelper.cxx b/canvas/source/vcl/canvashelper.cxx
index 89ee207989c6..bec73b3d336a 100644
--- a/canvas/source/vcl/canvashelper.cxx
+++ b/canvas/source/vcl/canvashelper.cxx
@@ -723,13 +723,14 @@ namespace vclcanvas
// itself serves this purpose
return uno::Reference< rendering::XCachedPrimitive >(nullptr);
}
- else if( !bModulateColors && mpOutDevProvider->getOutDev().HasFastDrawTransformedBitmap())
+ else if( mpOutDevProvider->getOutDev().HasFastDrawTransformedBitmap())
{
::basegfx::B2DHomMatrix aSizeTransform;
aSizeTransform.scale( aBmpEx.GetSizePixel().Width(), aBmpEx.GetSizePixel().Height() );
aMatrix = aMatrix * aSizeTransform;
+ const double fAlpha = bModulateColors ? renderState.DeviceColor[3] : 1.0;
- mpOutDevProvider->getOutDev().DrawTransformedBitmapEx( aMatrix, aBmpEx );
+ mpOutDevProvider->getOutDev().DrawTransformedBitmapEx( aMatrix, aBmpEx, fAlpha );
if( mp2ndOutDevProvider )
{
// HACK. Normally, CanvasHelper does not care about
diff --git a/canvas/source/vcl/spritehelper.cxx b/canvas/source/vcl/spritehelper.cxx
index 31d16032e576..e8d4fa726e10 100644
--- a/canvas/source/vcl/spritehelper.cxx
+++ b/canvas/source/vcl/spritehelper.cxx
@@ -210,28 +210,7 @@ namespace vclcanvas
aMoveTransform.translate( aOutPos.X(), aOutPos.Y() );
aTransform = aMoveTransform * aTransform * aSizeTransform;
- if( ::rtl::math::approxEqual(fAlpha, 1.0) )
- {
- // no alpha modulation -> just copy to output
- rTargetSurface.DrawTransformedBitmapEx( aTransform, *maContent );
- }
- else
- {
- // TODO(P3): Switch to OutputDevice::DrawTransparent()
- // here
-
- // draw semi-transparent
- sal_uInt8 nColor( static_cast<sal_uInt8>( ::basegfx::fround( 255.0*(1.0 - fAlpha) + .5) ) );
- AlphaMask aAlpha( maContent->GetSizePixel(),
- &nColor );
-
- // mask out fully transparent areas
- if( maContent->IsTransparent() )
- aAlpha.Replace( maContent->GetMask(), 255 );
-
- // alpha-blend to output
- rTargetSurface.DrawTransformedBitmapEx( aTransform, BitmapEx( maContent->GetBitmap(), aAlpha ) );
- }
+ rTargetSurface.DrawTransformedBitmapEx( aTransform, *maContent, fAlpha );
rTargetSurface.Pop();
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 2eb6fd9e882e..a8d77c77b30e 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1480,10 +1480,14 @@ public:
@param rBitmapEx
The BitmapEx to be painted
+
+ @param fAlpha
+ Optional additional alpha to use for drawing (0 to 1, 1 being no change).
*/
void DrawTransformedBitmapEx(
const basegfx::B2DHomMatrix& rTransformation,
- const BitmapEx& rBitmapEx);
+ const BitmapEx& rBitmapEx,
+ double fAlpha = 1.0);
/** Return true if DrawTransformedBitmapEx() is fast.
@@ -1509,7 +1513,8 @@ protected:
*/
virtual bool DrawTransformBitmapExDirect(
const basegfx::B2DHomMatrix& aFullTransform,
- const BitmapEx& rBitmapEx);
+ const BitmapEx& rBitmapEx,
+ double fAlpha = 1.0);
/** Transform and reduce the area that needs to be drawn of the bitmap and return the new
visible range and the maximum area.
diff --git a/include/vcl/print.hxx b/include/vcl/print.hxx
index 8ddd8bc7fbd3..e787ce40fca8 100644
--- a/include/vcl/print.hxx
+++ b/include/vcl/print.hxx
@@ -234,7 +234,7 @@ protected:
const Point& rSrcPtPixel, const Size& rSrcSizePixel) override;
bool DrawTransformBitmapExDirect( const basegfx::B2DHomMatrix& aFullTransform,
- const BitmapEx& rBitmapEx) override;
+ const BitmapEx& rBitmapEx, double fAlpha = 1.0) override;
bool TransformAndReduceBitmapExToTargetRange( const basegfx::B2DHomMatrix& aFullTransform,
basegfx::B2DRange &aVisibleRange, double &fMaximumArea) override;
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