[Libreoffice-commits] core.git: 4 commits - include/vcl vcl/source
Chris Sherlock
chris.sherlock79 at gmail.com
Wed Apr 23 10:23:27 PDT 2014
include/vcl/outdev.hxx | 67 +--
vcl/source/outdev/bitmap.cxx | 913 ++++++++++++++++++++++---------------------
vcl/source/outdev/mask.cxx | 13
vcl/source/outdev/outdev.cxx | 39 +
4 files changed, 543 insertions(+), 489 deletions(-)
New commits:
commit 6658367b2ee358417b602edfd5f0fb9d69e6caed
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date: Thu Apr 24 03:20:50 2014 +1000
outdev/bitmap.cxx: remove unnecessary headers, fix SAL_WARN_IF statement
Change-Id: I01e380cf87c6c18ebfc15b1f2a1055d100074991
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index bb5c91b..439bc6c 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -20,13 +20,13 @@
#include <tools/debug.hxx>
#include <vcl/bitmap.hxx>
#include <vcl/bitmapex.hxx>
-#include <vcl/window.hxx>
#include <vcl/metaact.hxx>
#include <vcl/gdimtf.hxx>
-#include <vcl/virdev.hxx>
#include <vcl/bmpacc.hxx>
#include <vcl/outdev.hxx>
+#include <vcl/virdev.hxx>
#include <vcl/image.hxx>
+
#include <bmpfast.hxx>
#include <salbmp.hxx>
#include <salgdi.hxx>
@@ -36,6 +36,7 @@
#include <outdev.h>
#include <window.h>
#include <outdata.hxx>
+
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <boost/scoped_array.hpp>
@@ -1261,7 +1262,7 @@ Bitmap OutputDevice::BlendBitmapWithAlpha(
int nX, nY;
sal_uInt8 nResAlpha;
- SAL_WARN_IF( !mpAlphaVDev, "BlendBitmapWithAlpha(): call me only with valid alpha VirtualDevice!" );
+ SAL_WARN_IF( !mpAlphaVDev, "vcl.gdi", "BlendBitmapWithAlpha(): call me only with valid alpha VirtualDevice!" );
bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
mpAlphaVDev->EnableMapMode(false);
commit 3dbed9ac7a5200b5c7fbaba2114c3ee1e14af8da
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date: Wed Apr 23 20:12:17 2014 +1000
Rearrange VCL OutputDevice bitmap functions
Change-Id: I9bb6a5d123c35d3de2d2fa7b8a427c92f599afd7
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 8808d13..71f8022 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -745,11 +745,11 @@ protected:
virtual void CopyAreaFinal( SalTwoRect& aPosAry, sal_uInt32 nFlags);
-public:
/** @name Bitmap functions
*/
///@{
+public:
/** @overload
void DrawBitmap(
const Point& rDestPt,
@@ -846,19 +846,6 @@ public:
*/
BitmapEx GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const;
- /** Retrieve downsampled and cropped bitmap
-
- @attention This method ignores negative rDstSz values, thus
- mirroring must happen outside this method (e.g. in DrawBitmap)
- */
- Bitmap GetDownsampledBitmap(
- const Size& rDstSz,
- const Point& rSrcPt,
- const Size& rSrcSz,
- const Bitmap& rBmp,
- long nMaxBmpDPIX,
- long nMaxBmpDPIY );
-
/** Draw BitmapEx transformed
@@ -877,6 +864,13 @@ public:
protected:
+ virtual void DrawDeviceBitmap(
+ const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ BitmapEx& rBitmapEx );
+
+ virtual void ScaleBitmap ( Bitmap &rBmp, SalTwoRect &rPosAry );
+
/** Transform and draw a bitmap directly
@param aFullTransform The B2DHomMatrix used for the transformation
@@ -904,12 +898,6 @@ protected:
basegfx::B2DRange &aVisibleRange,
double &fMaximumArea);
- virtual void ScaleBitmap ( Bitmap &rBmp, SalTwoRect &rPosAry );
-
- virtual void DrawDeviceBitmap(
- const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- BitmapEx& rBitmapEx );
private:
SAL_DLLPRIVATE void DrawAlphaBitmap(
@@ -946,12 +934,27 @@ private:
const sal_Int32 nDstWidth,
const long* pMapX,
const long* pMapY );
+
+ /** Retrieve downsampled and cropped bitmap
+
+ @attention This method ignores negative rDstSz values, thus
+ mirroring must happen outside this method (e.g. in DrawBitmap)
+ */
+ Bitmap GetDownsampledBitmap(
+ const Size& rDstSz,
+ const Point& rSrcPt,
+ const Size& rSrcSz,
+ const Bitmap& rBmp,
+ long nMaxBmpDPIX,
+ long nMaxBmpDPIY );
+
///@}
-public:
/** @name Curved shape functions
*/
///@{
+public:
+
void DrawEllipse( const Rectangle& rRect );
void DrawArc( const Rectangle& rRect,
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index faab91e..bb5c91b 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -374,6 +374,293 @@ void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
}
}
+Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
+{
+ Bitmap aBmp;
+ long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
+ long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
+ long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
+ long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
+
+ if ( mpGraphics || AcquireGraphics() )
+ {
+ if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY))
+ {
+ Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
+ bool bClipped = false;
+
+ // X-Coordinate outside of draw area?
+ if ( nX < mnOutOffX )
+ {
+ nWidth -= ( mnOutOffX - nX );
+ nX = mnOutOffX;
+ bClipped = true;
+ }
+
+ // Y-Coordinate outside of draw area?
+ if ( nY < mnOutOffY )
+ {
+ nHeight -= ( mnOutOffY - nY );
+ nY = mnOutOffY;
+ bClipped = true;
+ }
+
+ // Width outside of draw area?
+ if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
+ {
+ nWidth = mnOutOffX + mnOutWidth - nX;
+ bClipped = true;
+ }
+
+ // Height outside of draw area?
+ if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
+ {
+ nHeight = mnOutOffY + mnOutHeight - nY;
+ bClipped = true;
+ }
+
+ if ( bClipped )
+ {
+ // If the visible part has been clipped, we have to create a
+ // Bitmap with the correct size in which we copy the clipped
+ // Bitmap to the correct position.
+ VirtualDevice aVDev( *this );
+
+ if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
+ {
+ if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->AcquireGraphics() )
+ {
+ SalTwoRect aPosAry;
+
+ aPosAry.mnSrcX = nX;
+ aPosAry.mnSrcY = nY;
+ aPosAry.mnSrcWidth = nWidth;
+ aPosAry.mnSrcHeight = nHeight;
+ aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
+ aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
+ aPosAry.mnDestWidth = nWidth;
+ aPosAry.mnDestHeight = nHeight;
+
+ if ( (nWidth > 0) && (nHeight > 0) )
+ {
+ (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( aPosAry, mpGraphics, this, this );
+ }
+ else
+ {
+ OSL_ENSURE(false, "CopyBits with negative width or height (!)");
+ }
+
+ aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
+ }
+ else
+ bClipped = false;
+ }
+ else
+ bClipped = false;
+ }
+
+ if ( !bClipped )
+ {
+ SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
+
+ if( pSalBmp )
+ {
+ ImpBitmap* pImpBmp = new ImpBitmap;
+ pImpBmp->ImplSetSalBitmap( pSalBmp );
+ aBmp.ImplSetImpBitmap( pImpBmp );
+ }
+ }
+ }
+ }
+
+ return aBmp;
+}
+
+BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
+{
+
+ // #110958# Extract alpha value from VDev, if any
+ if( mpAlphaVDev )
+ {
+ Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
+
+ // ensure 8 bit alpha
+ if( aAlphaBitmap.GetBitCount() > 8 )
+ aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
+
+ return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
+ }
+ else
+ return GetBitmap( rSrcPt, rSize );
+}
+
+
+
+void OutputDevice::DrawDeviceBitmap( const Point& rDestPt, const Size& rDestSize,
+ const Point& rSrcPtPixel, const Size& rSrcSizePixel,
+ BitmapEx& rBmpEx )
+{
+ if(rBmpEx.IsAlpha())
+ {
+ Size aDestSizePixel(LogicToPixel(rDestSize));
+
+ BitmapEx aScaledBitmapEx(rBmpEx);
+ Point aSrcPtPixel(rSrcPtPixel);
+ Size aSrcSizePixel(rSrcSizePixel);
+
+ // we have beautiful scaling algorithms, let's use them
+ if (aDestSizePixel != rSrcSizePixel && rSrcSizePixel.Width() != 0 && rSrcSizePixel.Height() != 0)
+ {
+ double fScaleX = double(aDestSizePixel.Width()) / rSrcSizePixel.Width();
+ double fScaleY = double(aDestSizePixel.Height()) / rSrcSizePixel.Height();
+
+ aScaledBitmapEx.Scale(fScaleX, fScaleY);
+
+ aSrcSizePixel = aDestSizePixel;
+ aSrcPtPixel.X() = rSrcPtPixel.X() * fScaleX;
+ aSrcPtPixel.Y() = rSrcPtPixel.Y() * fScaleY;
+ }
+ DrawAlphaBitmap(aScaledBitmapEx.GetBitmap(), aScaledBitmapEx.GetAlpha(), rDestPt, rDestSize, aSrcPtPixel, aSrcSizePixel);
+ return;
+ }
+
+ if( !( !rBmpEx ) )
+ {
+ SalTwoRect aPosAry;
+
+ aPosAry.mnSrcX = rSrcPtPixel.X();
+ aPosAry.mnSrcY = rSrcPtPixel.Y();
+ aPosAry.mnSrcWidth = rSrcSizePixel.Width();
+ aPosAry.mnSrcHeight = rSrcSizePixel.Height();
+ aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
+ aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
+ aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
+ aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
+
+ const sal_uLong nMirrFlags = AdjustTwoRect( aPosAry, rBmpEx.GetSizePixel() );
+
+ if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
+ {
+
+ if( nMirrFlags )
+ rBmpEx.Mirror( nMirrFlags );
+
+ const SalBitmap* pSalSrcBmp = rBmpEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap();
+ const ImpBitmap* pMaskBmp = rBmpEx.ImplGetMaskImpBitmap();
+
+ if ( pMaskBmp )
+ {
+ SalBitmap* pSalAlphaBmp = pMaskBmp->ImplGetSalBitmap();
+ bool bTryDirectPaint(pSalSrcBmp && pSalAlphaBmp);
+
+ if(bTryDirectPaint)
+ {
+ // only paint direct when no scaling and no MapMode, else the
+ // more expensive conversions may be done for short-time Bitmap/BitmapEx
+ // used for buffering only
+ if(!IsMapMode() && aPosAry.mnSrcWidth == aPosAry.mnDestWidth && aPosAry.mnSrcHeight == aPosAry.mnDestHeight)
+ {
+ bTryDirectPaint = false;
+ }
+ }
+
+ if(bTryDirectPaint && mpGraphics->DrawAlphaBitmap(aPosAry, *pSalSrcBmp, *pSalAlphaBmp, this))
+ {
+ // tried to paint as alpha directly. If tis worked, we are done (except
+ // alpha, see below)
+ }
+ else
+ {
+ // #4919452# reduce operation area to bounds of
+ // cliprect. since masked transparency involves
+ // creation of a large vdev and copying the screen
+ // content into that (slooow read from framebuffer),
+ // that should considerably increase performance for
+ // large bitmaps and small clippings.
+
+ // Note that this optimization is a workaround for a
+ // Writer peculiarity, namely, to decompose background
+ // graphics into myriads of disjunct, tiny
+ // rectangles. That otherwise kills us here, since for
+ // transparent output, SAL always prepares the whole
+ // bitmap, if aPosAry contains the whole bitmap (and
+ // it's _not_ to blame for that).
+
+ // Note the call to ImplPixelToDevicePixel(), since
+ // aPosAry already contains the mnOutOff-offsets, they
+ // also have to be applied to the region
+ Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
+
+ // TODO: Also respect scaling (that's a bit tricky,
+ // since the source points have to move fractional
+ // amounts (which is not possible, thus has to be
+ // emulated by increases copy area)
+ // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
+ // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
+
+ // for now, only identity scales allowed
+ if( !aClipRegionBounds.IsEmpty() &&
+ aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
+ aPosAry.mnDestHeight == aPosAry.mnSrcHeight )
+ {
+ // now intersect dest rect with clip region
+ aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX,
+ aPosAry.mnDestY,
+ aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
+ aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) );
+
+ // Note: I could theoretically optimize away the
+ // DrawBitmap below, if the region is empty
+ // here. Unfortunately, cannot rule out that
+ // somebody relies on the side effects.
+ if( !aClipRegionBounds.IsEmpty() )
+ {
+ aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
+ aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
+ aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
+ aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
+
+ aPosAry.mnDestX = aClipRegionBounds.Left();
+ aPosAry.mnDestY = aClipRegionBounds.Top();
+ aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
+ aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
+ }
+ }
+
+ mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp,
+ *pMaskBmp->ImplGetSalBitmap(),
+ this );
+ }
+
+ // #110958# Paint mask to alpha channel. Luckily, the
+ // black and white representation of the mask maps to
+ // the alpha channel
+
+ // #i25167# Restrict mask painting to _opaque_ areas
+ // of the mask, otherwise we spoil areas where no
+ // bitmap content was ever visible. Interestingly
+ // enough, this can be achieved by taking the mask as
+ // the transparency mask of itself
+ if( mpAlphaVDev )
+ mpAlphaVDev->DrawBitmapEx( rDestPt,
+ rDestSize,
+ BitmapEx( rBmpEx.GetMask(),
+ rBmpEx.GetMask() ) );
+ }
+ else
+ {
+ mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp, this );
+
+ if( mpAlphaVDev )
+ {
+ // #i32109#: Make bitmap area opaque
+ mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
+ }
+ }
+ }
+ }
+}
+
void OutputDevice::ScaleBitmap (Bitmap &rBmp, SalTwoRect &rPosAry)
{
const double nScaleX = rPosAry.mnDestWidth / static_cast<double>( rPosAry.mnSrcWidth );
@@ -553,255 +840,90 @@ void OutputDevice::DrawTransformedBitmapEx(
const basegfx::B2DHomMatrix aFullTransform(GetViewTransformation() * rTransformation);
const bool bTryDirectPaint(!bInvert && !bBitmapChangedColor && !bMetafile );
- if(!bForceToOwnTransformer && bTryDirectPaint)
- {
- bDone = DrawTransformBitmapExDirect(aFullTransform, rBitmapEx);
- }
-
- if(!bDone)
- {
- // take the fallback when no rotate and shear, but mirror (else we would have done this above)
- if(!bForceToOwnTransformer && !bRotated && !bSheared)
- {
- // with no rotation or shear it can be mapped to DrawBitmapEx
- // do *not* execute the mirroring here, it's done in the fallback
- // #i124580# the correct DestSize needs to be calculated based on MaxXY values
- const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
- const Size aDestSize(
- basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
- basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
-
- DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
- return;
- }
-
- // fallback; create transformed bitmap the hard way (back-transform
- // the pixels) and paint
- basegfx::B2DRange aVisibleRange(0.0, 0.0, 1.0, 1.0);
-
- // limit maximum area to something looking good for non-pixel-based targets (metafile, printer)
- // by using a fixed minimum (allow at least, but no need to utilize) for good smooting and an area
- // dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
- // to avoid crashes/ressource problems (ca. 1500x3000 here)
- const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel());
- const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
- const double fOrigAreaScaled(bSheared || bRotated ? fOrigArea * 1.44 : fOrigArea);
- double fMaximumArea(std::min(4500000.0, std::max(1000000.0, fOrigAreaScaled)));
-
- if(!bMetafile)
- {
- if ( !TransformAndReduceBitmapExToTargetRange( aFullTransform, aVisibleRange, fMaximumArea ) )
- return;
- }
-
- if(!aVisibleRange.isEmpty())
- {
- static bool bDoSmoothAtAll(true);
- BitmapEx aTransformed(rBitmapEx);
-
- // #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
- // in getTransformed) also creates a transformed alpha channel
- if(!aTransformed.IsTransparent() && (bSheared || bRotated))
- {
- // parts will be uncovered, extend aTransformed with a mask bitmap
- const Bitmap aContent(aTransformed.GetBitmap());
-
- AlphaMask aMaskBmp(aContent.GetSizePixel());
- aMaskBmp.Erase(0);
-
- aTransformed = BitmapEx(aContent, aMaskBmp);
- }
-
- aTransformed = aTransformed.getTransformed(
- aFullTransform,
- aVisibleRange,
- fMaximumArea,
- bDoSmoothAtAll);
- basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
-
- // get logic object target range
- aTargetRange.transform(rTransformation);
-
- // get from unified/relative VisibleRange to logoc one
- aVisibleRange.transform(
- basegfx::tools::createScaleTranslateB2DHomMatrix(
- aTargetRange.getRange(),
- aTargetRange.getMinimum()));
-
- // extract point and size; do not remove size, the bitmap may have been prepared reduced by purpose
- // #i124580# the correct DestSize needs to be calculated based on MaxXY values
- const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY()));
- const Size aDestSize(
- basegfx::fround(aVisibleRange.getMaxX()) - aDestPt.X(),
- basegfx::fround(aVisibleRange.getMaxY()) - aDestPt.Y());
-
- DrawBitmapEx(aDestPt, aDestSize, aTransformed);
- }
- }
-}
-
-void OutputDevice::DrawDeviceBitmap( const Point& rDestPt, const Size& rDestSize,
- const Point& rSrcPtPixel, const Size& rSrcSizePixel,
- BitmapEx& rBmpEx )
-{
- if(rBmpEx.IsAlpha())
- {
- Size aDestSizePixel(LogicToPixel(rDestSize));
-
- BitmapEx aScaledBitmapEx(rBmpEx);
- Point aSrcPtPixel(rSrcPtPixel);
- Size aSrcSizePixel(rSrcSizePixel);
-
- // we have beautiful scaling algorithms, let's use them
- if (aDestSizePixel != rSrcSizePixel && rSrcSizePixel.Width() != 0 && rSrcSizePixel.Height() != 0)
- {
- double fScaleX = double(aDestSizePixel.Width()) / rSrcSizePixel.Width();
- double fScaleY = double(aDestSizePixel.Height()) / rSrcSizePixel.Height();
-
- aScaledBitmapEx.Scale(fScaleX, fScaleY);
-
- aSrcSizePixel = aDestSizePixel;
- aSrcPtPixel.X() = rSrcPtPixel.X() * fScaleX;
- aSrcPtPixel.Y() = rSrcPtPixel.Y() * fScaleY;
- }
- DrawAlphaBitmap(aScaledBitmapEx.GetBitmap(), aScaledBitmapEx.GetAlpha(), rDestPt, rDestSize, aSrcPtPixel, aSrcSizePixel);
- return;
- }
-
- if( !( !rBmpEx ) )
- {
- SalTwoRect aPosAry;
-
- aPosAry.mnSrcX = rSrcPtPixel.X();
- aPosAry.mnSrcY = rSrcPtPixel.Y();
- aPosAry.mnSrcWidth = rSrcSizePixel.Width();
- aPosAry.mnSrcHeight = rSrcSizePixel.Height();
- aPosAry.mnDestX = ImplLogicXToDevicePixel( rDestPt.X() );
- aPosAry.mnDestY = ImplLogicYToDevicePixel( rDestPt.Y() );
- aPosAry.mnDestWidth = ImplLogicWidthToDevicePixel( rDestSize.Width() );
- aPosAry.mnDestHeight = ImplLogicHeightToDevicePixel( rDestSize.Height() );
-
- const sal_uLong nMirrFlags = AdjustTwoRect( aPosAry, rBmpEx.GetSizePixel() );
-
- if( aPosAry.mnSrcWidth && aPosAry.mnSrcHeight && aPosAry.mnDestWidth && aPosAry.mnDestHeight )
- {
-
- if( nMirrFlags )
- rBmpEx.Mirror( nMirrFlags );
-
- const SalBitmap* pSalSrcBmp = rBmpEx.ImplGetBitmapImpBitmap()->ImplGetSalBitmap();
- const ImpBitmap* pMaskBmp = rBmpEx.ImplGetMaskImpBitmap();
-
- if ( pMaskBmp )
- {
- SalBitmap* pSalAlphaBmp = pMaskBmp->ImplGetSalBitmap();
- bool bTryDirectPaint(pSalSrcBmp && pSalAlphaBmp);
-
- if(bTryDirectPaint)
- {
- // only paint direct when no scaling and no MapMode, else the
- // more expensive conversions may be done for short-time Bitmap/BitmapEx
- // used for buffering only
- if(!IsMapMode() && aPosAry.mnSrcWidth == aPosAry.mnDestWidth && aPosAry.mnSrcHeight == aPosAry.mnDestHeight)
- {
- bTryDirectPaint = false;
- }
- }
-
- if(bTryDirectPaint && mpGraphics->DrawAlphaBitmap(aPosAry, *pSalSrcBmp, *pSalAlphaBmp, this))
- {
- // tried to paint as alpha directly. If tis worked, we are done (except
- // alpha, see below)
- }
- else
- {
- // #4919452# reduce operation area to bounds of
- // cliprect. since masked transparency involves
- // creation of a large vdev and copying the screen
- // content into that (slooow read from framebuffer),
- // that should considerably increase performance for
- // large bitmaps and small clippings.
-
- // Note that this optimization is a workaround for a
- // Writer peculiarity, namely, to decompose background
- // graphics into myriads of disjunct, tiny
- // rectangles. That otherwise kills us here, since for
- // transparent output, SAL always prepares the whole
- // bitmap, if aPosAry contains the whole bitmap (and
- // it's _not_ to blame for that).
-
- // Note the call to ImplPixelToDevicePixel(), since
- // aPosAry already contains the mnOutOff-offsets, they
- // also have to be applied to the region
- Rectangle aClipRegionBounds( ImplPixelToDevicePixel(maRegion).GetBoundRect() );
+ if(!bForceToOwnTransformer && bTryDirectPaint)
+ {
+ bDone = DrawTransformBitmapExDirect(aFullTransform, rBitmapEx);
+ }
- // TODO: Also respect scaling (that's a bit tricky,
- // since the source points have to move fractional
- // amounts (which is not possible, thus has to be
- // emulated by increases copy area)
- // const double nScaleX( aPosAry.mnDestWidth / aPosAry.mnSrcWidth );
- // const double nScaleY( aPosAry.mnDestHeight / aPosAry.mnSrcHeight );
+ if(!bDone)
+ {
+ // take the fallback when no rotate and shear, but mirror (else we would have done this above)
+ if(!bForceToOwnTransformer && !bRotated && !bSheared)
+ {
+ // with no rotation or shear it can be mapped to DrawBitmapEx
+ // do *not* execute the mirroring here, it's done in the fallback
+ // #i124580# the correct DestSize needs to be calculated based on MaxXY values
+ const Point aDestPt(basegfx::fround(aTranslate.getX()), basegfx::fround(aTranslate.getY()));
+ const Size aDestSize(
+ basegfx::fround(aScale.getX() + aTranslate.getX()) - aDestPt.X(),
+ basegfx::fround(aScale.getY() + aTranslate.getY()) - aDestPt.Y());
- // for now, only identity scales allowed
- if( !aClipRegionBounds.IsEmpty() &&
- aPosAry.mnDestWidth == aPosAry.mnSrcWidth &&
- aPosAry.mnDestHeight == aPosAry.mnSrcHeight )
- {
- // now intersect dest rect with clip region
- aClipRegionBounds.Intersection( Rectangle( aPosAry.mnDestX,
- aPosAry.mnDestY,
- aPosAry.mnDestX + aPosAry.mnDestWidth - 1,
- aPosAry.mnDestY + aPosAry.mnDestHeight - 1 ) );
+ DrawBitmapEx(aDestPt, aDestSize, rBitmapEx);
+ return;
+ }
- // Note: I could theoretically optimize away the
- // DrawBitmap below, if the region is empty
- // here. Unfortunately, cannot rule out that
- // somebody relies on the side effects.
- if( !aClipRegionBounds.IsEmpty() )
- {
- aPosAry.mnSrcX += aClipRegionBounds.Left() - aPosAry.mnDestX;
- aPosAry.mnSrcY += aClipRegionBounds.Top() - aPosAry.mnDestY;
- aPosAry.mnSrcWidth = aClipRegionBounds.GetWidth();
- aPosAry.mnSrcHeight = aClipRegionBounds.GetHeight();
+ // fallback; create transformed bitmap the hard way (back-transform
+ // the pixels) and paint
+ basegfx::B2DRange aVisibleRange(0.0, 0.0, 1.0, 1.0);
- aPosAry.mnDestX = aClipRegionBounds.Left();
- aPosAry.mnDestY = aClipRegionBounds.Top();
- aPosAry.mnDestWidth = aClipRegionBounds.GetWidth();
- aPosAry.mnDestHeight = aClipRegionBounds.GetHeight();
- }
- }
+ // limit maximum area to something looking good for non-pixel-based targets (metafile, printer)
+ // by using a fixed minimum (allow at least, but no need to utilize) for good smooting and an area
+ // dependent of original size for good quality when e.g. rotated/sheared. Still, limit to a maximum
+ // to avoid crashes/ressource problems (ca. 1500x3000 here)
+ const Size& rOriginalSizePixel(rBitmapEx.GetSizePixel());
+ const double fOrigArea(rOriginalSizePixel.Width() * rOriginalSizePixel.Height() * 0.5);
+ const double fOrigAreaScaled(bSheared || bRotated ? fOrigArea * 1.44 : fOrigArea);
+ double fMaximumArea(std::min(4500000.0, std::max(1000000.0, fOrigAreaScaled)));
- mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp,
- *pMaskBmp->ImplGetSalBitmap(),
- this );
- }
+ if(!bMetafile)
+ {
+ if ( !TransformAndReduceBitmapExToTargetRange( aFullTransform, aVisibleRange, fMaximumArea ) )
+ return;
+ }
- // #110958# Paint mask to alpha channel. Luckily, the
- // black and white representation of the mask maps to
- // the alpha channel
+ if(!aVisibleRange.isEmpty())
+ {
+ static bool bDoSmoothAtAll(true);
+ BitmapEx aTransformed(rBitmapEx);
- // #i25167# Restrict mask painting to _opaque_ areas
- // of the mask, otherwise we spoil areas where no
- // bitmap content was ever visible. Interestingly
- // enough, this can be achieved by taking the mask as
- // the transparency mask of itself
- if( mpAlphaVDev )
- mpAlphaVDev->DrawBitmapEx( rDestPt,
- rDestSize,
- BitmapEx( rBmpEx.GetMask(),
- rBmpEx.GetMask() ) );
- }
- else
+ // #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
+ // in getTransformed) also creates a transformed alpha channel
+ if(!aTransformed.IsTransparent() && (bSheared || bRotated))
{
- mpGraphics->DrawBitmap( aPosAry, *pSalSrcBmp, this );
+ // parts will be uncovered, extend aTransformed with a mask bitmap
+ const Bitmap aContent(aTransformed.GetBitmap());
- if( mpAlphaVDev )
- {
- // #i32109#: Make bitmap area opaque
- mpAlphaVDev->ImplFillOpaqueRectangle( Rectangle(rDestPt, rDestSize) );
- }
+ AlphaMask aMaskBmp(aContent.GetSizePixel());
+ aMaskBmp.Erase(0);
+
+ aTransformed = BitmapEx(aContent, aMaskBmp);
}
+
+ aTransformed = aTransformed.getTransformed(
+ aFullTransform,
+ aVisibleRange,
+ fMaximumArea,
+ bDoSmoothAtAll);
+ basegfx::B2DRange aTargetRange(0.0, 0.0, 1.0, 1.0);
+
+ // get logic object target range
+ aTargetRange.transform(rTransformation);
+
+ // get from unified/relative VisibleRange to logoc one
+ aVisibleRange.transform(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aTargetRange.getRange(),
+ aTargetRange.getMinimum()));
+
+ // extract point and size; do not remove size, the bitmap may have been prepared reduced by purpose
+ // #i124580# the correct DestSize needs to be calculated based on MaxXY values
+ const Point aDestPt(basegfx::fround(aVisibleRange.getMinX()), basegfx::fround(aVisibleRange.getMinY()));
+ const Size aDestSize(
+ basegfx::fround(aVisibleRange.getMaxX()) - aDestPt.X(),
+ basegfx::fround(aVisibleRange.getMaxY()) - aDestPt.Y());
+
+ DrawBitmapEx(aDestPt, aDestSize, aTransformed);
}
}
}
@@ -900,126 +1022,6 @@ void OutputDevice::DrawImage( const Point& rPos, const Size& rSize,
}
}
-Bitmap OutputDevice::GetBitmap( const Point& rSrcPt, const Size& rSize ) const
-{
- Bitmap aBmp;
- long nX = ImplLogicXToDevicePixel( rSrcPt.X() );
- long nY = ImplLogicYToDevicePixel( rSrcPt.Y() );
- long nWidth = ImplLogicWidthToDevicePixel( rSize.Width() );
- long nHeight = ImplLogicHeightToDevicePixel( rSize.Height() );
-
- if ( mpGraphics || AcquireGraphics() )
- {
- if ( nWidth > 0 && nHeight > 0 && nX <= (mnOutWidth + mnOutOffX) && nY <= (mnOutHeight + mnOutOffY))
- {
- Rectangle aRect( Point( nX, nY ), Size( nWidth, nHeight ) );
- bool bClipped = false;
-
- // X-Coordinate outside of draw area?
- if ( nX < mnOutOffX )
- {
- nWidth -= ( mnOutOffX - nX );
- nX = mnOutOffX;
- bClipped = true;
- }
-
- // Y-Coordinate outside of draw area?
- if ( nY < mnOutOffY )
- {
- nHeight -= ( mnOutOffY - nY );
- nY = mnOutOffY;
- bClipped = true;
- }
-
- // Width outside of draw area?
- if ( (nWidth + nX) > (mnOutWidth + mnOutOffX) )
- {
- nWidth = mnOutOffX + mnOutWidth - nX;
- bClipped = true;
- }
-
- // Height outside of draw area?
- if ( (nHeight + nY) > (mnOutHeight + mnOutOffY) )
- {
- nHeight = mnOutOffY + mnOutHeight - nY;
- bClipped = true;
- }
-
- if ( bClipped )
- {
- // If the visible part has been clipped, we have to create a
- // Bitmap with the correct size in which we copy the clipped
- // Bitmap to the correct position.
- VirtualDevice aVDev( *this );
-
- if ( aVDev.SetOutputSizePixel( aRect.GetSize() ) )
- {
- if ( ((OutputDevice*)&aVDev)->mpGraphics || ((OutputDevice*)&aVDev)->AcquireGraphics() )
- {
- SalTwoRect aPosAry;
-
- aPosAry.mnSrcX = nX;
- aPosAry.mnSrcY = nY;
- aPosAry.mnSrcWidth = nWidth;
- aPosAry.mnSrcHeight = nHeight;
- aPosAry.mnDestX = ( aRect.Left() < mnOutOffX ) ? ( mnOutOffX - aRect.Left() ) : 0L;
- aPosAry.mnDestY = ( aRect.Top() < mnOutOffY ) ? ( mnOutOffY - aRect.Top() ) : 0L;
- aPosAry.mnDestWidth = nWidth;
- aPosAry.mnDestHeight = nHeight;
-
- if ( (nWidth > 0) && (nHeight > 0) )
- {
- (((OutputDevice*)&aVDev)->mpGraphics)->CopyBits( aPosAry, mpGraphics, this, this );
- }
- else
- {
- OSL_ENSURE(false, "CopyBits with negative width or height (!)");
- }
-
- aBmp = aVDev.GetBitmap( Point(), aVDev.GetOutputSizePixel() );
- }
- else
- bClipped = false;
- }
- else
- bClipped = false;
- }
-
- if ( !bClipped )
- {
- SalBitmap* pSalBmp = mpGraphics->GetBitmap( nX, nY, nWidth, nHeight, this );
-
- if( pSalBmp )
- {
- ImpBitmap* pImpBmp = new ImpBitmap;
- pImpBmp->ImplSetSalBitmap( pSalBmp );
- aBmp.ImplSetImpBitmap( pImpBmp );
- }
- }
- }
- }
-
- return aBmp;
-}
-
-BitmapEx OutputDevice::GetBitmapEx( const Point& rSrcPt, const Size& rSize ) const
-{
-
- // #110958# Extract alpha value from VDev, if any
- if( mpAlphaVDev )
- {
- Bitmap aAlphaBitmap( mpAlphaVDev->GetBitmap( rSrcPt, rSize ) );
-
- // ensure 8 bit alpha
- if( aAlphaBitmap.GetBitCount() > 8 )
- aAlphaBitmap.Convert( BMP_CONVERSION_8BIT_GREYS );
-
- return BitmapEx(GetBitmap( rSrcPt, rSize ), AlphaMask( aAlphaBitmap ) );
- }
- else
- return GetBitmap( rSrcPt, rSize );
-}
-
void OutputDevice::DrawAlphaBitmap( const Bitmap& rBmp, const AlphaMask& rAlpha,
const Point& rDestPt, const Size& rDestSize,
const Point& rSrcPtPixel, const Size& rSrcSizePixel )
@@ -1198,7 +1200,6 @@ void OutputDevice::DrawAlphaBitmap( const Bitmap& rBmp, const AlphaMask& rAlpha,
}
}
-
namespace
{
// Co = Cs + Cd*(1-As) premultiplied alpha -or-
@@ -1260,8 +1261,7 @@ Bitmap OutputDevice::BlendBitmapWithAlpha(
int nX, nY;
sal_uInt8 nResAlpha;
- OSL_ENSURE(mpAlphaVDev,
- "BlendBitmapWithAlpha(): call me only with valid alpha VDev!" );
+ SAL_WARN_IF( !mpAlphaVDev, "BlendBitmapWithAlpha(): call me only with valid alpha VirtualDevice!" );
bool bOldMapMode( mpAlphaVDev->IsMapModeEnabled() );
mpAlphaVDev->EnableMapMode(false);
commit d0ad5518013c4e5f263fe9f9ce67057122e8b2b1
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date: Wed Apr 23 19:09:44 2014 +1000
Comment documentation error fixup in outdev.hxx
Change-Id: Id03ffc9681b457d702b4d8beef4c8a3a52d1641b
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 93af80e..8808d13 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -20,9 +20,6 @@
#ifndef INCLUDED_VCL_OUTDEV_HXX
#define INCLUDED_VCL_OUTDEV_HXX
-#define META_BMPSCALEPART_ACTION (118)
-#define META_BMPEXSCALEPART_ACTION (121)
-
#include <tools/gen.hxx>
#include <tools/solar.h>
#include <vcl/dllapi.h>
@@ -50,6 +47,9 @@
#define GLYPH_FONT_HEIGHT 256
#endif
+#define META_BMPSCALEPART_ACTION (118)
+#define META_BMPEXSCALEPART_ACTION (121)
+
struct ImplOutDevData;
class ImplFontEntry;
struct ImplObjStack;
@@ -1096,7 +1096,7 @@ private:
public:
- /** @name Polyline functions
+ /** @name Mask functions
*/
///@{
commit 2a591848d41b4ec176a74a7f38ca0953d2ca30e7
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date: Wed Apr 23 19:06:17 2014 +1000
Remove unnecessary OUTDEV_INIT() macro in VCL's outdev.hxx
Change-Id: I0eba1f88f607ba1faf40d8507bb184bdc88085be
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 901cfbe..93af80e 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -50,22 +50,6 @@
#define GLYPH_FONT_HEIGHT 256
#endif
-#define OUTDEV_INIT() \
-{ \
- if ( !IsDeviceOutputNecessary() ) \
- return; \
- \
- if ( !mpGraphics ) \
- if ( !AcquireGraphics() ) \
- return; \
- \
- if ( mbInitClipRegion ) \
- ImplInitClipRegion(); \
- \
- if ( mbOutputClipped ) \
- return; \
-}
-
struct ImplOutDevData;
class ImplFontEntry;
struct ImplObjStack;
diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx
index 056af7e..faab91e 100644
--- a/vcl/source/outdev/bitmap.cxx
+++ b/vcl/source/outdev/bitmap.cxx
@@ -121,7 +121,18 @@ void OutputDevice::DrawBitmap( const Point& rDestPt, const Size& rDestSize,
}
}
- OUTDEV_INIT();
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ if ( !AcquireGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
if( !aBmp.IsEmpty() )
{
@@ -346,7 +357,18 @@ void OutputDevice::DrawBitmapEx( const Point& rDestPt, const Size& rDestSize,
}
}
- OUTDEV_INIT();
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ if ( !AcquireGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
DrawDeviceBitmap( rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel, aBmpEx );
}
diff --git a/vcl/source/outdev/mask.cxx b/vcl/source/outdev/mask.cxx
index 4888c03..39af4ba 100644
--- a/vcl/source/outdev/mask.cxx
+++ b/vcl/source/outdev/mask.cxx
@@ -94,7 +94,18 @@ void OutputDevice::DrawMask( const Point& rDestPt, const Size& rDestSize,
}
}
- OUTDEV_INIT();
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ if ( !AcquireGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
ApplyMask( rBitmap, rMaskColor, rDestPt, rDestSize, rSrcPtPixel, rSrcSizePixel );
diff --git a/vcl/source/outdev/outdev.cxx b/vcl/source/outdev/outdev.cxx
index 7b81420..5eedc98 100644
--- a/vcl/source/outdev/outdev.cxx
+++ b/vcl/source/outdev/outdev.cxx
@@ -566,7 +566,18 @@ void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
}
- OUTDEV_INIT();
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ if ( !AcquireGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
SalTwoRect aPosAry;
aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
@@ -613,7 +624,18 @@ void OutputDevice::DrawOutDev( const Point& rDestPt, const Size& rDestSize,
mpMetaFile->AddAction( new MetaBmpScaleAction( rDestPt, rDestSize, aBmp ) );
}
- OUTDEV_INIT();
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ if ( !AcquireGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
SalTwoRect aPosAry;
aPosAry.mnSrcX = rOutDev.ImplLogicXToDevicePixel( rSrcPt.X() );
@@ -665,7 +687,18 @@ void OutputDevice::CopyArea( const Point& rDestPt,
RasterOp eOldRop = GetRasterOp();
SetRasterOp( ROP_OVERPAINT );
- OUTDEV_INIT();
+ if ( !IsDeviceOutputNecessary() )
+ return;
+
+ if ( !mpGraphics )
+ if ( !AcquireGraphics() )
+ return;
+
+ if ( mbInitClipRegion )
+ ImplInitClipRegion();
+
+ if ( mbOutputClipped )
+ return;
SalTwoRect aPosAry;
aPosAry.mnSrcWidth = ImplLogicWidthToDevicePixel( rSrcSize.Width() );
More information about the Libreoffice-commits
mailing list