[Libreoffice-commits] core.git: 2 commits - include/vcl vcl/source
Tomaž Vajngerl
tomaz.vajngerl at collabora.co.uk
Sun Jan 18 07:09:38 PST 2015
include/vcl/outdev.hxx | 6
vcl/source/outdev/bitmap.cxx | 438 +++++++++++++++++++++++++++----------------
2 files changed, 289 insertions(+), 155 deletions(-)
New commits:
commit d53103dd83bf20ac63485e229069f145e35b3009
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Sun Jan 18 23:51:14 2015 +0900
fdo#74124 bilinear scaling with blending for some formats
The DrawDeviceAlphaBitmapSlowPath used fast/ugly scaling with
blending. With this a bilinear scaling is used which should
improve quality for downscaling (less than 50% should start to
degrade in quality as only 2 samples are always used) and
upscaling.
Change-Id: I56cdf2b5761687be891387343a773b6fefac03e2
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index 50877be..1ee1eef 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -673,6 +673,179 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r
}
}
+namespace
+{
+
+struct ScaleContext
+{
+ boost::scoped_array<long> mpMapX;
+ boost::scoped_array<long> mpMapY;
+
+ boost::scoped_array<long> mpMapXOffset;
+ boost::scoped_array<long> mpMapYOffset;
+
+ ScaleContext(Rectangle& aDstRect, Rectangle& aBitmapRect,
+ Size& aOutSize, long nOffX, long nOffY)
+
+ : mpMapX(new long[aDstRect.GetWidth()])
+ , mpMapY(new long[aDstRect.GetHeight()])
+ , mpMapXOffset(new long[aDstRect.GetWidth()])
+ , mpMapYOffset(new long[aDstRect.GetHeight()])
+ {
+ const long nSrcWidth = aBitmapRect.GetWidth();
+ const long nSrcHeight = aBitmapRect.GetHeight();
+
+ const bool bHMirr = aOutSize.Width() < 0;
+ const bool bVMirr = aOutSize.Height() < 0;
+
+ generateSimpleMap(
+ nSrcWidth, aDstRect.GetWidth(), aBitmapRect.Left(),
+ aOutSize.Width(), nOffX, bHMirr, mpMapX.get(), mpMapXOffset.get());
+
+ generateSimpleMap(
+ nSrcHeight, aDstRect.GetHeight(), aBitmapRect.Top(),
+ aOutSize.Height(), nOffY, bVMirr, mpMapY.get(), mpMapYOffset.get());
+ }
+
+private:
+
+ static void generateSimpleMap(long nSrcDimension, long nDstDimension, long nDstLocation,
+ long nOutDimention, long nOffset, bool bMirror, long* pMap, long* pMapOffset)
+ {
+ long nMirrorOffset = 0;
+
+ if (bMirror)
+ nMirrorOffset = (nDstLocation << 1) + nSrcDimension - 1L;
+
+ double fReverseScale = (nSrcDimension - 1L) / double(nOutDimention - 1L);
+
+ for (long i = 0L; i < nDstDimension; i++)
+ {
+ double fTemp = ((nOffset + i) * fReverseScale);
+ if (bMirror)
+ fTemp = nMirrorOffset - fTemp - 1L;
+
+ pMap[i] = MinMax(nDstLocation + long(fTemp), 0, nSrcDimension - 2L);
+ pMapOffset[i] = (long) ((fTemp - pMap[i]) * 128.0);
+ }
+ }
+
+public:
+ void blendBitmap(
+ const BitmapWriteAccess* pDestination,
+ const BitmapReadAccess* pSource,
+ const BitmapReadAccess* pSourceAlpha,
+ const long nDstWidth,
+ const long nDstHeight)
+ {
+ if (pSource && pSourceAlpha && pDestination)
+ {
+ unsigned long nSourceFormat = pSource->GetScanlineFormat();
+ unsigned long nDestinationFormat = pDestination->GetScanlineFormat();
+
+ switch (nSourceFormat)
+ {
+ case BMP_FORMAT_24BIT_TC_RGB:
+ case BMP_FORMAT_24BIT_TC_BGR:
+ {
+ if ( (nSourceFormat == BMP_FORMAT_24BIT_TC_BGR && nDestinationFormat == BMP_FORMAT_32BIT_TC_BGRA)
+ || (nSourceFormat == BMP_FORMAT_24BIT_TC_RGB && nDestinationFormat == BMP_FORMAT_32BIT_TC_RGBA))
+ {
+ blendBitmap24(pDestination, pSource, pSourceAlpha, nDstWidth, nDstHeight);
+ }
+ }
+ }
+ }
+ }
+
+ void blendBitmap24(
+ const BitmapWriteAccess* pDestination,
+ const BitmapReadAccess* pSource,
+ const BitmapReadAccess* pSourceAlpha,
+ const long nDstWidth,
+ const long nDstHeight)
+ {
+ Scanline pLine0, pLine1;
+ Scanline pLineAlpha0, pLineAlpha1;
+ Scanline pColorSample1, pColorSample2;
+ Scanline pDestScanline;
+
+ long nColor1Line1, nColor2Line1, nColor3Line1;
+ long nColor1Line2, nColor2Line2, nColor3Line2;
+ long nAlphaLine1, nAlphaLine2;
+
+ sal_uInt8 nColor1, nColor2, nColor3, nAlpha;
+
+ for (long nY = 0L; nY < nDstHeight; nY++)
+ {
+ const long nMapY = mpMapY[nY];
+ const long nMapFY = mpMapYOffset[nY];
+
+ pLine0 = pSource->GetScanline(nMapY);
+ pLine1 = pSource->GetScanline(nMapY + 1);
+
+ pLineAlpha0 = pSourceAlpha->GetScanline(nMapY);
+ pLineAlpha1 = pSourceAlpha->GetScanline(nMapY + 1);
+
+ pDestScanline = pDestination->GetScanline(nY);
+
+ for (long nX = 0L; nX < nDstWidth; nX++)
+ {
+ const long nMapX = mpMapX[nX];
+ const long nMapFX = mpMapXOffset[nX];
+
+ pColorSample1 = pLine0 + 3L * nMapX;
+ pColorSample2 = pColorSample1 + 3L;
+ nColor1Line1 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1++;
+ pColorSample2++;
+ nColor2Line1 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1++;
+ pColorSample2++;
+ nColor3Line1 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1 = pLine1 + 3L * nMapX;
+ pColorSample2 = pColorSample1 + 3L;
+ nColor1Line2 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1++;
+ pColorSample2++;
+ nColor2Line2 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1++;
+ pColorSample2++;
+ nColor3Line2 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1 = pLineAlpha0 + nMapX;
+ pColorSample2 = pColorSample1 + 1L;
+ nAlphaLine1 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ pColorSample1 = pLineAlpha1 + nMapX;
+ pColorSample2 = pColorSample1 + 1L;
+ nAlphaLine2 = (static_cast<long>(*pColorSample1) << 7) + nMapFX * (static_cast<long>(*pColorSample2) - *pColorSample1);
+
+ nColor1 = (nColor1Line1 + nMapFY * ((nColor1Line2 >> 7) - (nColor1Line1 >> 7))) >> 7;
+ nColor2 = (nColor2Line1 + nMapFY * ((nColor2Line2 >> 7) - (nColor2Line1 >> 7))) >> 7;
+ nColor3 = (nColor3Line1 + nMapFY * ((nColor3Line2 >> 7) - (nColor3Line1 >> 7))) >> 7;
+
+ nAlpha = (nAlphaLine1 + nMapFY * ((nAlphaLine2 >> 7) - (nAlphaLine1 >> 7))) >> 7;
+
+ *pDestScanline = COLOR_CHANNEL_MERGE(*pDestScanline, nColor1, nAlpha);
+ pDestScanline++;
+ *pDestScanline = COLOR_CHANNEL_MERGE(*pDestScanline, nColor2, nAlpha);
+ pDestScanline++;
+ *pDestScanline = COLOR_CHANNEL_MERGE(*pDestScanline, nColor3, nAlpha);
+ pDestScanline++;
+ pDestScanline++;
+ }
+ }
+ }
+};
+
+} // end anonymous namespace
+
void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap, const AlphaMask& rAlpha, Rectangle aDstRect, Rectangle aBmpRect, Size& aOutSize, Point& aOutPoint)
{
VirtualDevice* pOldVDev = mpAlphaVDev;
@@ -701,16 +874,9 @@ void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap, const Al
aDstRect.SetSize(aBmp.GetSizePixel());
}
- BitmapColor aDstCol;
- const long nSrcWidth = aBmpRect.GetWidth();
- const long nSrcHeight = aBmpRect.GetHeight();
-
const long nDstWidth = aDstRect.GetWidth();
const long nDstHeight = aDstRect.GetHeight();
- const long nOutWidth = aOutSize.Width();
- const long nOutHeight = aOutSize.Height();
-
// calculate offset in original bitmap
// in RTL case this is a little more complicated since the contents of the
// bitmap is not mirrored (it never is), however the paint region and bmp region
@@ -722,45 +888,13 @@ void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap, const Al
const long nOffY = aDstRect.Top() - aOutPoint.Y();
- long nX, nOutX, nY, nOutY;
- long nMirrOffX = 0;
- long nMirrOffY = 0;
-
- boost::scoped_array<long> pMapX(new long[nDstWidth]);
- boost::scoped_array<long> pMapY(new long[nDstHeight]);
-
- // create horizontal mapping table
- if (bHMirr)
- {
- nMirrOffX = (aBmpRect.Left() << 1) + nSrcWidth - 1;
- }
-
- for (nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++)
- {
- pMapX[nX] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
- if(bHMirr)
- pMapX[nX] = nMirrOffX - pMapX[nX];
- }
-
- // create vertical mapping table
- if (bVMirr)
- {
- nMirrOffY = (aBmpRect.Top() << 1) + nSrcHeight - 1;
- }
-
- for(nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++)
- {
- pMapY[nY] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
-
- if (bVMirr)
- pMapY[nY] = nMirrOffY - pMapY[nY];
- }
+ ScaleContext aContext(aDstRect, aBmpRect, aOutSize, nOffX, nOffY);
Bitmap::ScopedReadAccess pBitmapReadAccess(const_cast<Bitmap&>(rBitmap));
AlphaMask::ScopedReadAccess pAlphaReadAccess(const_cast<AlphaMask&>(rAlpha));
DBG_ASSERT( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
- pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
+ pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
"OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
// #i38887# reading from screen may sometimes fail
@@ -775,17 +909,31 @@ void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap, const Al
aDstRect,
nOffY, nDstHeight,
nOffX, nDstWidth,
- pMapX.get(), pMapY.get() );
+ aContext.mpMapX.get(), aContext.mpMapY.get() );
}
else
{
- aNewBitmap = BlendBitmap(
+ bool isBitmap24bitRGB = (pBitmapReadAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB ||
+ pBitmapReadAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_BGR);
+
+ if (GetBitCount() <= 8 && !isBitmap24bitRGB)
+ {
+ aNewBitmap = BlendBitmap(
aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(),
nOffY, nDstHeight,
nOffX, nDstWidth,
aBmpRect, aOutSize,
bHMirr, bVMirr,
- pMapX.get(), pMapY.get() );
+ aContext.mpMapX.get(), aContext.mpMapY.get() );
+ }
+ else
+ {
+ Bitmap::ScopedWriteAccess pDestination(aBmp);
+ aContext.blendBitmap(
+ pDestination.get(), pBitmapReadAccess.get(), pAlphaReadAccess.get(),
+ nDstWidth, nDstHeight);
+ aNewBitmap = aBmp;
+ }
}
// #110958# Disable alpha VDev, we're doing the necessary
@@ -957,6 +1105,7 @@ void OutputDevice::DrawTransformedBitmapEx(
const bool bSheared(!basegfx::fTools::equalZero(fShearX));
const bool bMirroredX(basegfx::fTools::less(aScale.getX(), 0.0));
const bool bMirroredY(basegfx::fTools::less(aScale.getY(), 0.0));
+
static bool bForceToOwnTransformer(false);
if(!bForceToOwnTransformer && !bRotated && !bSheared && !bMirroredX && !bMirroredY)
@@ -1409,48 +1558,6 @@ Bitmap OutputDevice::BlendBitmap(
}
break;
- case( BMP_FORMAT_24BIT_TC_BGR ):
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
- Scanline pPScan = pP->GetScanline( nMapY );
- Scanline pAScan = pA->GetScanline( nMapY );
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- Scanline pTmp = pPScan + nMapX * 3;
-
- aDstCol = pB->GetPixel( nY, nX );
- pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 2 ], pTmp[ 1 ], pTmp[ 0 ],
- pAScan[ nMapX ] ) );
- }
- }
- }
- break;
-
- case( BMP_FORMAT_24BIT_TC_RGB ):
- {
- for( nY = 0; nY < nDstHeight; nY++ )
- {
- const long nMapY = pMapY[ nY ];
- Scanline pPScan = pP->GetScanline( nMapY );
- Scanline pAScan = pA->GetScanline( nMapY );
-
- for( nX = 0; nX < nDstWidth; nX++ )
- {
- const long nMapX = pMapX[ nX ];
- Scanline pTmp = pPScan + nMapX * 3;
-
- aDstCol = pB->GetPixel( nY, nX );
- pB->SetPixel( nY, nX, aDstCol.Merge( pTmp[ 0 ], pTmp[ 1 ], pTmp[ 2 ],
- pAScan[ nMapX ] ) );
- }
- }
- }
- break;
-
default:
{
for( nY = 0; nY < nDstHeight; nY++ )
commit 009c1752b1eff36827dae4fa9bd394c5089dcc55
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Sat Jan 3 13:14:55 2015 +0900
Extract slow path of DrawDeviceAlphaBitmap into its own method
Additioanlly cleanup and use ScopedReadAccess
Change-Id: Ia3365f4dc968368bdd90d4398188bffe2d56e89b
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 5ce1a27..f8fd837 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -1406,6 +1406,12 @@ private:
const Point& rSrcPtPixel,
const Size& rSrcSizePixel );
+ SAL_DLLPRIVATE void DrawDeviceAlphaBitmapSlowPath(
+ const Bitmap& rBitmap, const AlphaMask& rAlpha,
+ Rectangle aDstRect, Rectangle aBmpRect,
+ Size& aOutSz, Point& aOutPt);
+
+
SAL_DLLPRIVATE bool BlendBitmap(
const SalTwoRect& rPosAry,
const Bitmap& rBmp );
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index 680f362..50877be 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -604,36 +604,37 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r
const Point& rDestPt, const Size& rDestSize,
const Point& rSrcPtPixel, const Size& rSrcSizePixel )
{
- Point aOutPt( LogicToPixel( rDestPt ) );
- Size aOutSz( LogicToPixel( rDestSize ) );
- Rectangle aDstRect( Point(), GetOutputSizePixel() );
- const bool bHMirr = aOutSz.Width() < 0;
- const bool bVMirr = aOutSz.Height() < 0;
+ Point aOutPt(LogicToPixel(rDestPt));
+ Size aOutSz(LogicToPixel(rDestSize));
+ Rectangle aDstRect(Point(), GetOutputSizePixel());
+
+ const bool bHMirr = aOutSz.Width() < 0;
+ const bool bVMirr = aOutSz.Height() < 0;
ClipToPaintRegion(aDstRect);
- if( bHMirr )
+ if (bHMirr)
{
aOutSz.Width() = -aOutSz.Width();
- aOutPt.X() -= ( aOutSz.Width() - 1L );
+ aOutPt.X() -= aOutSz.Width() - 1L;
}
- if( bVMirr )
+ if (bVMirr)
{
aOutSz.Height() = -aOutSz.Height();
- aOutPt.Y() -= ( aOutSz.Height() - 1L );
+ aOutPt.Y() -= aOutSz.Height() - 1L;
}
- if( !aDstRect.Intersection( Rectangle( aOutPt, aOutSz ) ).IsEmpty() )
+ if (!aDstRect.Intersection(Rectangle(aOutPt, aOutSz)).IsEmpty())
{
static const char* pDisableNative = getenv( "SAL_DISABLE_NATIVE_ALPHA");
// #i83087# Naturally, system alpha blending cannot work with
// separate alpha VDev
bool bTryDirectPaint(!pDisableNative && !bHMirr && !bVMirr);
- if(bTryDirectPaint)
+ if (bTryDirectPaint)
{
- Point aRelPt = aOutPt + Point( mnOutOffX, mnOutOffY );
+ Point aRelPt = aOutPt + Point(mnOutOffX, mnOutOffY);
SalTwoRect aTR(
rSrcPtPixel.X(), rSrcPtPixel.Y(),
rSrcSizePixel.Width(), rSrcSizePixel.Height(),
@@ -644,19 +645,19 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r
SalBitmap* pSalAlphaBmp = rAlpha.ImplGetImpBitmap()->ImplGetSalBitmap();
// try the blen the alpha bitmap with the alpha virtual device
- if( mpAlphaVDev )
+ if (mpAlphaVDev)
{
Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( aRelPt, aOutSz ) );
SalBitmap* pSalAlphaBmp2 = aAlphaBitmap.ImplGetImpBitmap()->ImplGetSalBitmap();
- if( mpGraphics->BlendAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, *pSalAlphaBmp2, this ) )
+ if (mpGraphics->BlendAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, *pSalAlphaBmp2, this))
{
- mpAlphaVDev->BlendBitmap( aTR, rAlpha );
+ mpAlphaVDev->BlendBitmap(aTR, rAlpha);
return;
}
}
else
{
- if (mpGraphics->DrawAlphaBitmap( aTR, *pSalSrcBmp, *pSalAlphaBmp, this ))
+ if (mpGraphics->DrawAlphaBitmap(aTR, *pSalSrcBmp, *pSalAlphaBmp, this))
return;
}
}
@@ -664,122 +665,142 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r
// we need to make sure OpenGL never reaches this slow code path
assert(!OpenGLHelper::isVCLOpenGLEnabled());
- VirtualDevice* pOldVDev = mpAlphaVDev;
-
- Rectangle aBmpRect( Point(), rBmp.GetSizePixel() );
+ Rectangle aBmpRect(Point(), rBmp.GetSizePixel());
if (!aBmpRect.Intersection(Rectangle(rSrcPtPixel, rSrcSizePixel)).IsEmpty())
{
- // The scaling in this code path produces really ugly results - it
- // does the most trivial scaling with no smoothing.
-
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- const bool bOldMap = mbMap;
- mpMetaFile = NULL; // fdo#55044 reset before GetBitmap!
- mbMap = false;
- Bitmap aBmp( GetBitmap( aDstRect.TopLeft(), aDstRect.GetSize() ) );
-
- // #109044# The generated bitmap need not necessarily be
- // of aDstRect dimensions, it's internally clipped to
- // window bounds. Thus, we correct the dest size here,
- // since we later use it (in nDstWidth/Height) for pixel
- // access)
- // #i38887# reading from screen may sometimes fail
- if( aBmp.ImplGetImpBitmap() )
- aDstRect.SetSize( aBmp.GetSizePixel() );
-
- BitmapColor aDstCol;
- const long nSrcWidth = aBmpRect.GetWidth(), nSrcHeight = aBmpRect.GetHeight();
- const long nDstWidth = aDstRect.GetWidth(), nDstHeight = aDstRect.GetHeight();
- const long nOutWidth = aOutSz.Width(), nOutHeight = aOutSz.Height();
- // calculate offset in original bitmap
- // in RTL case this is a little more complicated since the contents of the
- // bitmap is not mirrored (it never is), however the paint region and bmp region
- // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
- // is content wise somewhere else and needs to take mirroring into account
- const long nOffX = IsRTLEnabled()
- ? aOutSz.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPt.X())
- : aDstRect.Left() - aOutPt.X(),
- nOffY = aDstRect.Top() - aOutPt.Y();
- long nX, nOutX, nY, nOutY;
- long nMirrOffX = 0;
- long nMirrOffY = 0;
- boost::scoped_array<long> pMapX(new long[ nDstWidth ]);
- boost::scoped_array<long> pMapY(new long[ nDstHeight ]);
-
- // create horizontal mapping table
- if( bHMirr )
- nMirrOffX = ( aBmpRect.Left() << 1 ) + nSrcWidth - 1;
-
- for( nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++ )
- {
- pMapX[ nX ] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
- if( bHMirr )
- pMapX[ nX ] = nMirrOffX - pMapX[ nX ];
- }
+ DrawDeviceAlphaBitmapSlowPath(rBmp, rAlpha, aDstRect, aBmpRect, aOutSz, aOutPt);
+ }
+ }
+}
- // create vertical mapping table
- if( bVMirr )
- nMirrOffY = ( aBmpRect.Top() << 1 ) + nSrcHeight - 1;
+void OutputDevice::DrawDeviceAlphaBitmapSlowPath(const Bitmap& rBitmap, const AlphaMask& rAlpha, Rectangle aDstRect, Rectangle aBmpRect, Size& aOutSize, Point& aOutPoint)
+{
+ VirtualDevice* pOldVDev = mpAlphaVDev;
- for( nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++ )
- {
- pMapY[ nY ] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
+ const bool bHMirr = aOutSize.Width() < 0;
+ const bool bVMirr = aOutSize.Height() < 0;
- if( bVMirr )
- pMapY[ nY ] = nMirrOffY - pMapY[ nY ];
- }
+ // The scaling in this code path produces really ugly results - it
+ // does the most trivial scaling with no smoothing.
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ const bool bOldMap = mbMap;
- BitmapReadAccess* pP = ( (Bitmap&) rBmp ).AcquireReadAccess();
- BitmapReadAccess* pA = ( (AlphaMask&) rAlpha ).AcquireReadAccess();
+ mpMetaFile = NULL; // fdo#55044 reset before GetBitmap!
+ mbMap = false;
- DBG_ASSERT( pA->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
- pA->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
- "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
+ Bitmap aBmp(GetBitmap(aDstRect.TopLeft(), aDstRect.GetSize()));
- // #i38887# reading from screen may sometimes fail
- if( aBmp.ImplGetImpBitmap() )
- {
- Bitmap aTmp;
+ // #109044# The generated bitmap need not necessarily be
+ // of aDstRect dimensions, it's internally clipped to
+ // window bounds. Thus, we correct the dest size here,
+ // since we later use it (in nDstWidth/Height) for pixel
+ // access)
+ // #i38887# reading from screen may sometimes fail
+ if (aBmp.ImplGetImpBitmap())
+ {
+ aDstRect.SetSize(aBmp.GetSizePixel());
+ }
- if( mpAlphaVDev )
- {
- aTmp = BlendBitmapWithAlpha(
- aBmp,pP,pA,
- aDstRect,
- nOffY,nDstHeight,
- nOffX,nDstWidth,
- pMapX.get(),pMapY.get() );
- }
- else
- {
- aTmp = BlendBitmap(
- aBmp,pP,pA,
- nOffY,nDstHeight,
- nOffX,nDstWidth,
- aBmpRect,aOutSz,
- bHMirr,bVMirr,
- pMapX.get(),pMapY.get() );
- }
+ BitmapColor aDstCol;
+ const long nSrcWidth = aBmpRect.GetWidth();
+ const long nSrcHeight = aBmpRect.GetHeight();
- // #110958# Disable alpha VDev, we're doing the necessary
- // stuff explicitly furher below
- if( mpAlphaVDev )
- mpAlphaVDev = NULL;
+ const long nDstWidth = aDstRect.GetWidth();
+ const long nDstHeight = aDstRect.GetHeight();
- DrawBitmap( aDstRect.TopLeft(),
- aTmp );
+ const long nOutWidth = aOutSize.Width();
+ const long nOutHeight = aOutSize.Height();
- // #110958# Enable alpha VDev again
- mpAlphaVDev = pOldVDev;
- }
+ // calculate offset in original bitmap
+ // in RTL case this is a little more complicated since the contents of the
+ // bitmap is not mirrored (it never is), however the paint region and bmp region
+ // are in mirrored coordinates, so the intersection of (aOutPt,aOutSz) with these
+ // is content wise somewhere else and needs to take mirroring into account
+ const long nOffX = IsRTLEnabled()
+ ? aOutSize.Width() - aDstRect.GetWidth() - (aDstRect.Left() - aOutPoint.X())
+ : aDstRect.Left() - aOutPoint.X();
+
+ const long nOffY = aDstRect.Top() - aOutPoint.Y();
- ( (Bitmap&) rBmp ).ReleaseAccess( pP );
- ( (AlphaMask&) rAlpha ).ReleaseAccess( pA );
+ long nX, nOutX, nY, nOutY;
+ long nMirrOffX = 0;
+ long nMirrOffY = 0;
- mbMap = bOldMap;
- mpMetaFile = pOldMetaFile;
+ boost::scoped_array<long> pMapX(new long[nDstWidth]);
+ boost::scoped_array<long> pMapY(new long[nDstHeight]);
+
+ // create horizontal mapping table
+ if (bHMirr)
+ {
+ nMirrOffX = (aBmpRect.Left() << 1) + nSrcWidth - 1;
+ }
+
+ for (nX = 0L, nOutX = nOffX; nX < nDstWidth; nX++, nOutX++)
+ {
+ pMapX[nX] = aBmpRect.Left() + nOutX * nSrcWidth / nOutWidth;
+ if(bHMirr)
+ pMapX[nX] = nMirrOffX - pMapX[nX];
+ }
+
+ // create vertical mapping table
+ if (bVMirr)
+ {
+ nMirrOffY = (aBmpRect.Top() << 1) + nSrcHeight - 1;
+ }
+
+ for(nY = 0L, nOutY = nOffY; nY < nDstHeight; nY++, nOutY++)
+ {
+ pMapY[nY] = aBmpRect.Top() + nOutY * nSrcHeight / nOutHeight;
+
+ if (bVMirr)
+ pMapY[nY] = nMirrOffY - pMapY[nY];
+ }
+
+ Bitmap::ScopedReadAccess pBitmapReadAccess(const_cast<Bitmap&>(rBitmap));
+ AlphaMask::ScopedReadAccess pAlphaReadAccess(const_cast<AlphaMask&>(rAlpha));
+
+ DBG_ASSERT( pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_PAL ||
+ pAlphaReadAccess->GetScanlineFormat() == BMP_FORMAT_8BIT_TC_MASK,
+ "OutputDevice::ImplDrawAlpha(): non-8bit alpha no longer supported!" );
+
+ // #i38887# reading from screen may sometimes fail
+ if (aBmp.ImplGetImpBitmap())
+ {
+ Bitmap aNewBitmap;
+
+ if (mpAlphaVDev)
+ {
+ aNewBitmap = BlendBitmapWithAlpha(
+ aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(),
+ aDstRect,
+ nOffY, nDstHeight,
+ nOffX, nDstWidth,
+ pMapX.get(), pMapY.get() );
}
+ else
+ {
+ aNewBitmap = BlendBitmap(
+ aBmp, pBitmapReadAccess.get(), pAlphaReadAccess.get(),
+ nOffY, nDstHeight,
+ nOffX, nDstWidth,
+ aBmpRect, aOutSize,
+ bHMirr, bVMirr,
+ pMapX.get(), pMapY.get() );
+ }
+
+ // #110958# Disable alpha VDev, we're doing the necessary
+ // stuff explicitly furher below
+ if (mpAlphaVDev)
+ mpAlphaVDev = NULL;
+
+ DrawBitmap(aDstRect.TopLeft(), aNewBitmap);
+
+ // #110958# Enable alpha VDev again
+ mpAlphaVDev = pOldVDev;
}
+
+ mbMap = bOldMap;
+ mpMetaFile = pOldMetaFile;
}
void OutputDevice::ScaleBitmap (Bitmap &rBmp, SalTwoRect &rPosAry)
More information about the Libreoffice-commits
mailing list