[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