summaryrefslogtreecommitdiff
path: root/vcl/source
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/source
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/source')
-rw-r--r--vcl/source/gdi/print.cxx3
-rw-r--r--vcl/source/gdi/salgdilayout.cxx9
-rw-r--r--vcl/source/outdev/bitmap.cxx61
3 files changed, 56 insertions, 17 deletions
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