[Libreoffice-commits] .: Branch 'distro/suse/suse-3.6' - 8 commits - oox/inc oox/source svtools/inc svtools/source vcl/inc vcl/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Oct 12 10:18:36 PDT 2012


 oox/inc/oox/drawingml/textparagraphproperties.hxx |    2 
 oox/source/drawingml/textparagraphproperties.cxx  |    7 
 svtools/inc/svtools/grfmgr.hxx                    |    4 
 svtools/source/filter/wmf/enhwmf.cxx              |    4 
 svtools/source/filter/wmf/winwmf.cxx              |    2 
 svtools/source/graphic/grfcache.cxx               |  312 +++++++++++++++++++++-
 svtools/source/graphic/grfmgr2.cxx                |  262 +++++++++---------
 vcl/inc/vcl/bitmap.hxx                            |  105 ++++++-
 vcl/source/gdi/bitmap3.cxx                        |  232 +++++-----------
 9 files changed, 615 insertions(+), 315 deletions(-)

New commits:
commit 898e6f94e595a53f6b6fcc22e8702a7357f76a32
Author: Muthu Subramanian <sumuthu at suse.com>
Date:   Tue Aug 14 17:41:59 2012 +0530

    n#759180: Push oox default spacing values.
    
    Conflicts:
    	oox/source/drawingml/textparagraph.cxx
    
    Change-Id: Ibb5027b3b74fb1c264fbc6b1efae9e8cd1a3b00e

diff --git a/oox/inc/oox/drawingml/textparagraphproperties.hxx b/oox/inc/oox/drawingml/textparagraphproperties.hxx
index 9e9fe88..622203d 100644
--- a/oox/inc/oox/drawingml/textparagraphproperties.hxx
+++ b/oox/inc/oox/drawingml/textparagraphproperties.hxx
@@ -106,7 +106,7 @@ public:
     void                                apply( const TextParagraphProperties& rSourceProps );
     void                                pushToPropSet( const ::oox::core::XmlFilterBase* pFilterBase,
                                             const ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet > & xPropSet,
-                                                PropertyMap& rioBulletList, const BulletList* pMasterBuList, sal_Bool bApplyBulletList, float fFontSize ) const;
+                                                PropertyMap& rioBulletList, const BulletList* pMasterBuList, sal_Bool bApplyBulletList, float fFontSize, bool bPushDefaultValues = false ) const;
     void                                pushToPropSet( const ::com::sun::star::uno::Reference < ::com::sun::star::beans::XPropertySet > & xPropSet) const;
 
     /** Returns the largest character size of this paragraph. If possible the
diff --git a/oox/source/drawingml/textparagraphproperties.cxx b/oox/source/drawingml/textparagraphproperties.cxx
index 0ca8641..e3977af 100644
--- a/oox/source/drawingml/textparagraphproperties.cxx
+++ b/oox/source/drawingml/textparagraphproperties.cxx
@@ -391,7 +391,8 @@ void TextParagraphProperties::apply( const TextParagraphProperties& rSourceProps
 }
 
 void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* pFilterBase,
-    const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, sal_Bool bApplyBulletMap, float fCharacterSize ) const
+    const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, sal_Bool bApplyBulletMap, float fCharacterSize,
+    bool bPushDefaultValues ) const
 {
     PropertySet aPropSet( xPropSet );
     aPropSet.setProperties( maTextParagraphPropertyMap );
@@ -406,9 +407,9 @@ void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* p
 
     maBulletList.pushToPropMap( pFilterBase, rioBulletMap );
 
-    if ( maParaTopMargin.bHasValue )
+    if ( maParaTopMargin.bHasValue || bPushDefaultValues )
         aPropSet.setProperty( PROP_ParaTopMargin, maParaTopMargin.toMargin( fCharacterSize != 0.0 ? fCharacterSize : getCharHeightPoints ( 18.0 ) ) );
-    if ( maParaBottomMargin.bHasValue )
+    if ( maParaBottomMargin.bHasValue || bPushDefaultValues )
         aPropSet.setProperty( PROP_ParaBottomMargin, maParaBottomMargin.toMargin( fCharacterSize != 0.0 ? fCharacterSize : getCharHeightPoints ( 18.0 ) ) );
     if ( nNumberingType == NumberingType::BITMAP )
     {
commit 73e73ca997fa921d76752b36e62bb5795b77d676
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Jun 22 15:50:30 2012 +0200

    try somewhat harder to smoothscale objects (bnc#765998)
    
    The used bilinear algorithm is apparently of a rather low quality,
    use the new generic box algorithm instead. That makes it somewhat
    slower, but the result is cached, and hopefully the speed difference
    is not that significant.
    
    Change-Id: I5a4dbe4851d467babc0d0fdcc3375b35441daf93

diff --git a/svtools/inc/svtools/grfmgr.hxx b/svtools/inc/svtools/grfmgr.hxx
index edb3db1..438efcd 100644
--- a/svtools/inc/svtools/grfmgr.hxx
+++ b/svtools/inc/svtools/grfmgr.hxx
@@ -38,11 +38,11 @@
 
 #define GRFMGR_DRAW_NOTCACHED               0x00000000UL
 #define GRFMGR_DRAW_CACHED                  0x00000001UL
-#define GRFMGR_DRAW_BILINEAR                0x00000002UL
+#define GRFMGR_DRAW_SMOOTHSCALE             0x00000002UL
 #define GRFMGR_DRAW_USE_DRAWMODE_SETTINGS   0x00000004UL
 #define GRFMGR_DRAW_SUBSTITUTE              0x00000008UL
 #define GRFMGR_DRAW_NO_SUBSTITUTE           0x00000010UL
-#define GRFMGR_DRAW_STANDARD                (GRFMGR_DRAW_CACHED|GRFMGR_DRAW_BILINEAR)
+#define GRFMGR_DRAW_STANDARD                (GRFMGR_DRAW_CACHED|GRFMGR_DRAW_SMOOTHSCALE)
 
 // --------------------
 // - AutoSwap Defines -
diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 4e7da1b..6bf2bc5 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -344,34 +344,7 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
         sal_Bool            bHMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_HORZ ) != 0;
         sal_Bool            bVMirr = ( rAttr.GetMirrorFlags() & BMP_MIRROR_VERT ) != 0;
 
-        if( nFlags & GRFMGR_DRAW_BILINEAR )
-        {
-            const double    fRevScaleX = ( nNewW > 1L ) ? ( (double) ( nW - 1L ) / ( nNewW - 1L ) ) : 0.0;
-            const double    fRevScaleY = ( nNewH > 1L ) ? ( (double) ( nH - 1L ) / ( nNewH - 1L ) ) : 0.0;
-
-            // create horizontal mapping table
-            for( nX = 0L, nTmpX = nW - 1L, nTmp = nW - 2L; nX < nNewW; nX++ )
-            {
-                fTmp = nX * fRevScaleX;
-
-                if( bHMirr )
-                    fTmp = nTmpX - fTmp;
-
-                pMapFX[ nX ] = (long) ( ( fTmp - ( pMapIX[ nX ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. );
-            }
-
-            // create vertical mapping table
-            for( nY = 0L, nTmpY = nH - 1L, nTmp = nH - 2L; nY < nNewH; nY++ )
-            {
-                fTmp = nY * fRevScaleY;
-
-                if( bVMirr )
-                    fTmp = nTmpY - fTmp;
-
-                pMapFY[ nY ] = (long) ( ( fTmp - ( pMapIY[ nY ] = MinMax( (long) fTmp, 0, nTmp ) ) ) * 1048576. );
-            }
-        }
-        else
+        if( !( nFlags & GRFMGR_DRAW_SMOOTHSCALE ))
         {
             // #98290# Use a different mapping for non-interpolating mode, to avoid missing rows/columns
             const double    fRevScaleX = ( nNewW > 1L ) ? ( (double) nW / nNewW ) : 0.0;
@@ -453,7 +426,22 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     bRet = ( aOutBmpEx = aBmpEx ).Scale( aUnrotatedSzPix );
 
                     if( bRet )
-                        aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
+                        bRet = aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
+                }
+                else if( nFlags & GRFMGR_DRAW_SMOOTHSCALE )
+                {
+                    // Scale using the Box filter, rather than this algorithm, as that one provides
+                    // better quality, while being somewhat slower (the result should be cached though).
+                    aOutBmpEx = aBmpEx;
+                    bRet = true;
+                    if( bHMirr || bVMirr )
+                        bRet = aOutBmpEx.Mirror(( bHMirr ? BMP_MIRROR_HORZ : BMP_MIRROR_NONE )
+                                    | ( bVMirr ? BMP_MIRROR_VERT : BMP_MIRROR_NONE ));
+                    if( bRet )
+                        bRet = aOutBmpEx.Rotate( nRot10, COL_TRANSPARENT );
+                    if( bRet ) // scale as last (rotating would destroy the smooth scaling)
+                        bRet = aOutBmpEx.Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ),
+                            BMP_SCALE_BOX );
                 }
                 else
                 {
@@ -479,6 +467,17 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                 {
                     if( bSimple )
                         bRet = ( aOutBmpEx = aBmpEx ).Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ) );
+                    else if( nFlags & GRFMGR_DRAW_SMOOTHSCALE )
+                    {
+                    // Scale using the Box filter, rather than this algorithm, as that one provides
+                    // better quality, while being somewhat slower (the result should be cached though).
+                        aOutBmpEx = aBmpEx;
+                        bRet = aOutBmpEx.Scale( Size( nEndX - nStartX + 1, nEndY - nStartY + 1 ),
+                            BMP_SCALE_BOX );
+                        if( bRet && ( bHMirr || bVMirr ))
+                            bRet = aOutBmpEx.Mirror(( bHMirr ? BMP_MIRROR_HORZ : BMP_MIRROR_NONE )
+                                    | ( bVMirr ? BMP_MIRROR_VERT : BMP_MIRROR_NONE ));
+                    }
                     else
                     {
                         bRet = ImplCreateScaled( aBmpEx,
commit 744213cca0377417ca7dabed238d184ffecbfc11
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Jun 22 13:57:39 2012 +0200

    make it possible to cache the resulting pixmap with a metafile
    
    If the metafile contains just one single bitmap, the drawing code
    optimizes by just using that one bitmap. It (=the resulting pixmap
    after scaling etc.) however has not been cached so far, which means
    smoothscaling (to be done) would be quite slow with every paint.
    
    Conflicts:
    	svtools/source/graphic/grfmgr2.cxx
    
    Change-Id: I30950c55fbadfddedc7df31283c66ed064b1a1a6

diff --git a/svtools/source/graphic/grfcache.cxx b/svtools/source/graphic/grfcache.cxx
index bfd9341..bfb39e4 100644
--- a/svtools/source/graphic/grfcache.cxx
+++ b/svtools/source/graphic/grfcache.cxx
@@ -29,6 +29,7 @@
 
 #include <salhelper/timer.hxx>
 #include <tools/debug.hxx>
+#include <vcl/metaact.hxx>
 #include <vcl/outdev.hxx>
 #include <tools/poly.hxx>
 #include <rtl/strbuf.hxx>
@@ -419,6 +420,8 @@ private:
     sal_uLong                       mnOutDevDrawMode;
     sal_uInt16                      mnOutDevBitCount;
 
+    static bool IsCacheableAsBitmap( const GDIMetaFile& rMtf, OutputDevice* pOut, const Size& rSz );
+
 public:
 
     static sal_uLong                GetNeededSize( OutputDevice* pOut, const Point& rPt, const Size& rSz,
@@ -486,14 +489,305 @@ public:
 
 // -----------------------------------------------------------------------------
 
+// This whole function is based on checkMetadataBitmap() from grfmgr2.cxx, see that one for details.
+// If you do changes here, change the original function too.
+static void checkMetadataBitmap( const BitmapEx& rBmpEx,
+                                 Point    /*rSrcPoint*/,
+                                 Size     rSrcSize,
+                                 const Point&    rDestPoint,
+                                 const Size&     rDestSize,
+                                 const Size&     rRefSize,
+                                 bool&           o_rbNonBitmapActionEncountered )
+{
+    if( rSrcSize == Size())
+        rSrcSize = rBmpEx.GetSizePixel();
+
+    if( rDestPoint != Point( 0, 0 ))
+    {
+        o_rbNonBitmapActionEncountered = true;
+        return;
+    }
+    if( rDestSize != rRefSize )
+    {    if( rBmpEx.GetSizePixel().Width() > 100 && rBmpEx.GetSizePixel().Height() > 100
+            && abs( rDestSize.Width() - rRefSize.Width()) < 5
+            && abs( rDestSize.Height() - rRefSize.Height()) < 5 )
+            ; // ok, assume it's close enough
+        else
+        {  // fall back to mtf rendering
+            o_rbNonBitmapActionEncountered = true;
+            return;
+        }
+    }
+}
+
+// This function is based on GraphicManager::ImplCreateOutput(), in fact it mostly copies
+// it, the difference is that this one does not create anything, it only checks if
+// ImplCreateOutput() would use the optimization of using the single bitmap.
+// If you do changes here, change the original function too.
+bool GraphicDisplayCacheEntry::IsCacheableAsBitmap( const GDIMetaFile& rMtf,
+    OutputDevice* pOut, const Size& rSz )
+{
+    const Size aNewSize( rMtf.GetPrefSize() );
+    GDIMetaFile rOutMtf = rMtf;
+
+    // Count bitmap actions, and flag actions that paint, but
+    // are no bitmaps.
+    sal_Int32   nNumBitmaps(0);
+    bool        bNonBitmapActionEncountered(false);
+    if( aNewSize.Width() && aNewSize.Height() && rSz.Width() && rSz.Height() )
+    {
+        const MapMode rPrefMapMode( rMtf.GetPrefMapMode() );
+        const Size rSizePix( pOut->LogicToPixel( aNewSize, rPrefMapMode ) );
+
+        sal_uInt32  nCurPos;
+        MetaAction* pAct;
+        for( nCurPos = 0, pAct = (MetaAction*)rOutMtf.FirstAction(); pAct;
+             pAct = (MetaAction*)rOutMtf.NextAction(), nCurPos++ )
+        {
+            switch( pAct->GetType() )
+            {
+                case META_FONT_ACTION:
+                    // FALLTHROUGH intended
+                case META_NULL_ACTION:
+                    // FALLTHROUGH intended
+
+                    // OutDev state changes (which don't affect bitmap
+                    // output)
+                case META_LINECOLOR_ACTION:
+                    // FALLTHROUGH intended
+                case META_FILLCOLOR_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTCOLOR_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTFILLCOLOR_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTALIGN_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTLINECOLOR_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTLINE_ACTION:
+                    // FALLTHROUGH intended
+                case META_PUSH_ACTION:
+                    // FALLTHROUGH intended
+                case META_POP_ACTION:
+                    // FALLTHROUGH intended
+                case META_LAYOUTMODE_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTLANGUAGE_ACTION:
+                    // FALLTHROUGH intended
+                case META_COMMENT_ACTION:
+                    break;
+
+                    // bitmap output methods
+                case META_BMP_ACTION:
+                    if( !nNumBitmaps && !bNonBitmapActionEncountered )
+                    {
+                        MetaBmpAction* pAction = (MetaBmpAction*)pAct;
+
+                        checkMetadataBitmap(
+                            BitmapEx( pAction->GetBitmap()),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pAction->GetBitmap().GetSizePixel(),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
+                    }
+                    ++nNumBitmaps;
+                    break;
+
+                case META_BMPSCALE_ACTION:
+                    if( !nNumBitmaps && !bNonBitmapActionEncountered )
+                    {
+                        MetaBmpScaleAction* pAction = (MetaBmpScaleAction*)pAct;
+
+                        checkMetadataBitmap(
+                            BitmapEx( pAction->GetBitmap()),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pOut->LogicToPixel( pAction->GetSize(),
+                                                rPrefMapMode ),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
+                    }
+                    ++nNumBitmaps;
+                    break;
+
+                case META_BMPSCALEPART_ACTION:
+                    if( !nNumBitmaps && !bNonBitmapActionEncountered )
+                    {
+                        MetaBmpScalePartAction* pAction = (MetaBmpScalePartAction*)pAct;
+
+                        checkMetadataBitmap(        BitmapEx( pAction->GetBitmap() ),
+                                                    pAction->GetSrcPoint(),
+                                                    pAction->GetSrcSize(),
+                                                    pOut->LogicToPixel( pAction->GetDestPoint(),
+                                                                        rPrefMapMode ),
+                                                    pOut->LogicToPixel( pAction->GetDestSize(),
+                                                                        rPrefMapMode ),
+                                                    rSizePix,
+                                                    bNonBitmapActionEncountered );
+                    }
+                    ++nNumBitmaps;
+                    break;
+
+                case META_BMPEX_ACTION:
+                    if( !nNumBitmaps && !bNonBitmapActionEncountered )
+                    {
+                        MetaBmpExAction* pAction = (MetaBmpExAction*)pAct;
+
+                        checkMetadataBitmap(
+                            pAction->GetBitmapEx(),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pAction->GetBitmapEx().GetSizePixel(),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
+                    }
+                    ++nNumBitmaps;
+                    break;
+
+                case META_BMPEXSCALE_ACTION:
+                    if( !nNumBitmaps && !bNonBitmapActionEncountered )
+                    {
+                        MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*)pAct;
+
+                        checkMetadataBitmap(
+                            pAction->GetBitmapEx(),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pOut->LogicToPixel( pAction->GetSize(),
+                                                rPrefMapMode ),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
+                    }
+                    ++nNumBitmaps;
+                    break;
+
+                case META_BMPEXSCALEPART_ACTION:
+                    if( !nNumBitmaps && !bNonBitmapActionEncountered )
+                    {
+                        MetaBmpExScalePartAction* pAction = (MetaBmpExScalePartAction*)pAct;
+
+                        checkMetadataBitmap( pAction->GetBitmapEx(),
+                                                    pAction->GetSrcPoint(),
+                                                    pAction->GetSrcSize(),
+                                                    pOut->LogicToPixel( pAction->GetDestPoint(),
+                                                                        rPrefMapMode ),
+                                                    pOut->LogicToPixel( pAction->GetDestSize(),
+                                                                        rPrefMapMode ),
+                                                    rSizePix,
+                                                    bNonBitmapActionEncountered );
+                    }
+                    ++nNumBitmaps;
+                    break;
+
+                    // these actions actually output something (that's
+                    // different from a bitmap)
+                case META_RASTEROP_ACTION:
+                    if( ((MetaRasterOpAction*)pAct)->GetRasterOp() == ROP_OVERPAINT )
+                        break;
+                    // FALLTHROUGH intended
+                case META_PIXEL_ACTION:
+                    // FALLTHROUGH intended
+                case META_POINT_ACTION:
+                    // FALLTHROUGH intended
+                case META_LINE_ACTION:
+                    // FALLTHROUGH intended
+                case META_RECT_ACTION:
+                    // FALLTHROUGH intended
+                case META_ROUNDRECT_ACTION:
+                    // FALLTHROUGH intended
+                case META_ELLIPSE_ACTION:
+                    // FALLTHROUGH intended
+                case META_ARC_ACTION:
+                    // FALLTHROUGH intended
+                case META_PIE_ACTION:
+                    // FALLTHROUGH intended
+                case META_CHORD_ACTION:
+                    // FALLTHROUGH intended
+                case META_POLYLINE_ACTION:
+                    // FALLTHROUGH intended
+                case META_POLYGON_ACTION:
+                    // FALLTHROUGH intended
+                case META_POLYPOLYGON_ACTION:
+                    // FALLTHROUGH intended
+
+                case META_TEXT_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTARRAY_ACTION:
+                    // FALLTHROUGH intended
+                case META_STRETCHTEXT_ACTION:
+                    // FALLTHROUGH intended
+                case META_TEXTRECT_ACTION:
+                    // FALLTHROUGH intended
+
+                case META_MASK_ACTION:
+                    // FALLTHROUGH intended
+                case META_MASKSCALE_ACTION:
+                    // FALLTHROUGH intended
+                case META_MASKSCALEPART_ACTION:
+                    // FALLTHROUGH intended
+
+                case META_GRADIENT_ACTION:
+                    // FALLTHROUGH intended
+                case META_HATCH_ACTION:
+                    // FALLTHROUGH intended
+                case META_WALLPAPER_ACTION:
+                    // FALLTHROUGH intended
+
+                case META_TRANSPARENT_ACTION:
+                    // FALLTHROUGH intended
+                case META_EPS_ACTION:
+                    // FALLTHROUGH intended
+                case META_FLOATTRANSPARENT_ACTION:
+                    // FALLTHROUGH intended
+                case META_GRADIENTEX_ACTION:
+                    // FALLTHROUGH intended
+                case META_RENDERGRAPHIC_ACTION:
+                    // FALLTHROUGH intended
+
+                    // OutDev state changes that _do_ affect bitmap
+                    // output
+                case META_CLIPREGION_ACTION:
+                    // FALLTHROUGH intended
+                case META_ISECTRECTCLIPREGION_ACTION:
+                    // FALLTHROUGH intended
+                case META_ISECTREGIONCLIPREGION_ACTION:
+                    // FALLTHROUGH intended
+                case META_MOVECLIPREGION_ACTION:
+                    // FALLTHROUGH intended
+
+                case META_MAPMODE_ACTION:
+                    // FALLTHROUGH intended
+                case META_REFPOINT_ACTION:
+                    // FALLTHROUGH intended
+                default:
+                    bNonBitmapActionEncountered = true;
+                    break;
+            }
+        }
+    }
+    return nNumBitmaps == 1 && !bNonBitmapActionEncountered;
+}
+
 sal_uLong GraphicDisplayCacheEntry::GetNeededSize( OutputDevice* pOut, const Point& /*rPt*/, const Size& rSz,
                                                const GraphicObject& rObj, const GraphicAttr& rAttr )
 {
     const Graphic&      rGraphic = rObj.GetGraphic();
     const GraphicType   eType = rGraphic.GetType();
-    sal_uLong               nNeededSize;
 
+    bool canCacheAsBitmap = false;
     if( GRAPHIC_BITMAP == eType )
+        canCacheAsBitmap = true;
+    else if( GRAPHIC_GDIMETAFILE == eType )
+        canCacheAsBitmap = IsCacheableAsBitmap( rGraphic.GetGDIMetaFile(), pOut, rSz );
+    else
+        return 0;
+    if( canCacheAsBitmap )
     {
         const Size aOutSizePix( pOut->LogicToPixel( rSz ) );
         const long nBitCount = pOut->GetBitCount();
@@ -501,27 +795,23 @@ sal_uLong GraphicDisplayCacheEntry::GetNeededSize( OutputDevice* pOut, const Poi
         if( ( aOutSizePix.Width() > MAX_BMP_EXTENT ) ||
             ( aOutSizePix.Height() > MAX_BMP_EXTENT ) )
         {
-            nNeededSize = ULONG_MAX;
+            return ULONG_MAX;
         }
         else if( nBitCount )
         {
-            nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8;
-
+            sal_uLong nNeededSize = aOutSizePix.Width() * aOutSizePix.Height() * nBitCount / 8;
             if( rObj.IsTransparent() || ( rAttr.GetRotation() % 3600 ) )
                 nNeededSize += nNeededSize / nBitCount;
+            return nNeededSize;
         }
         else
         {
-             OSL_FAIL( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" );
-            nNeededSize = 256000;
+            OSL_FAIL( "GraphicDisplayCacheEntry::GetNeededSize(): pOut->GetBitCount() == 0" );
+            return 256000;
         }
     }
-    else if( GRAPHIC_GDIMETAFILE == eType )
-        nNeededSize = rGraphic.GetSizeBytes();
     else
-        nNeededSize = 0;
-
-    return nNeededSize;
+        return rGraphic.GetSizeBytes();
 }
 
 // -----------------------------------------------------------------------------
diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index b792f3f..4e7da1b 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -538,6 +538,7 @@ static BitmapEx checkMetadataBitmap( const BitmapEx& rBmpEx,
                                      const Size&     rRefSize,
                                      bool&           o_rbNonBitmapActionEncountered )
 {
+// NOTE: If you do changes in this function, change checkMetadataBitmap() in grfcache.cxx too.
     BitmapEx aBmpEx;
     if( rSrcSize == Size())
         rSrcSize = rBmpEx.GetSizePixel();
@@ -612,9 +613,12 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
         const Size&    rSizePix( pOut->LogicToPixel( aNewSize,
                                                      rPrefMapMode ) );
 
-        // taking care of font width default if scaling metafile.
-        // #117889# use existing metafile scan, to determine whether
-        // the metafile basically displays a single bitmap. Note that
+// NOTE: If you do changes in this function, check GraphicDisplayCacheEntry::IsCacheableAsBitmap
+// in grfcache.cxx too.
+
+        // Determine whether the metafile basically displays
+        // a single bitmap (in which case that bitmap is simply used directly
+        // instead of playing the metafile). Note that
         // the solution, as implemented here, is quite suboptimal (the
         // cases where a mtf consisting basically of a single bitmap,
         // that fail to pass the test below, are probably frequent). A
commit 3fbf2af7211a77ac0d4fbe49403cec416caa1db6
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Fri Jun 22 11:50:38 2012 +0200

    fix counting of bitmaps in a metafile
    
    if( !number ) { ... ++number; } would never get beyond 1.
    
    Change-Id: Iac33df3a21280c76fcdd130b699b4ab6466b1f46

diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 1c2ea1a..b792f3f 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -685,8 +685,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                             pAction->GetBitmap().GetSizePixel(),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPSCALE_ACTION:
@@ -703,8 +703,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                 rPrefMapMode ),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPSCALEPART_ACTION:
@@ -722,8 +722,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                                         rPrefMapMode ),
                                                     rSizePix,
                                                     bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPEX_ACTION:
@@ -739,8 +739,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                             pAction->GetBitmapEx().GetSizePixel(),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPEXSCALE_ACTION:
@@ -757,8 +757,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                 rPrefMapMode ),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPEXSCALEPART_ACTION:
@@ -775,8 +775,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                                         rPrefMapMode ),
                                                     rSizePix,
                                                     bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                     // these actions actually output something (that's
commit c7610f13df9a5f944a2fceb94a7079d3f42fe381
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Jun 20 20:00:55 2012 +0200

    fix off-by-one when reading WMF/EMF
    
    According to docs http://msdn.microsoft.com/en-us/library/dd162589(v=vs.85),
    cxDest/cyDest are "Logical width/height of the destination rectangle.",
    so there should be no +1 as there would be if they were the top-bottom corner.
    
    Change-Id: Iefa6db8e6131abe785b7878d97df1c891b73011c

diff --git a/svtools/source/filter/wmf/enhwmf.cxx b/svtools/source/filter/wmf/enhwmf.cxx
index b81d973..cce3dca 100644
--- a/svtools/source/filter/wmf/enhwmf.cxx
+++ b/svtools/source/filter/wmf/enhwmf.cxx
@@ -950,7 +950,7 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
                     cxSrc = cySrc = 0;
 
                 Bitmap      aBitmap;
-                Rectangle   aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
+                Rectangle   aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
 
                 cxDest = abs( (int)cxDest );        // sj: i37894, size can be negative
                 cyDest = abs( (int)cyDest );        // and also 122889
@@ -1019,7 +1019,7 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
                       >> cyDest;
 
                 Bitmap      aBitmap;
-                Rectangle   aRect( Point( xDest, yDest ), Size( cxDest+1, cyDest+1 ) );
+                Rectangle   aRect( Point( xDest, yDest ), Size( cxDest, cyDest ) );
 
                 cxDest = abs( (int)cxDest );        // sj: i37894, size can be negative
                 cyDest = abs( (int)cyDest );        // and also 122889
commit dbe3b6afaddeb137632b8f6dda01c68835bb2c72
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Jun 20 19:34:36 2012 +0200

    fix off-by-one in WMF/EMF reading
    
    It's rather lame that Rectangle from tools primarily specifies
    the rectangle as topleft/bottomright, rather than topleft/size,
    as that easily leads to confusion such as here.
    
    Change-Id: Ice86fae90d9159b98e0896b6c875b99c3e1a3686

diff --git a/svtools/source/filter/wmf/winwmf.cxx b/svtools/source/filter/wmf/winwmf.cxx
index a568e3f..5b3d085 100644
--- a/svtools/source/filter/wmf/winwmf.cxx
+++ b/svtools/source/filter/wmf/winwmf.cxx
@@ -1229,7 +1229,7 @@ void WMFReader::ReadWMF()
                         if( bEMFAvailable )
                         {
                             pOut->AddFromGDIMetaFile( aMeta );
-                            pOut->SetrclFrame( Rectangle(0, 0, aMeta.GetPrefSize().Width(), aMeta.GetPrefSize().Height() ));
+                            pOut->SetrclFrame( Rectangle( Point(0, 0), aMeta.GetPrefSize()));
 
                             // the stream needs to be set to the wmf end position,
                             // otherwise the GfxLink that is created will be incorrect
commit b4a3a18e0df04d0ddd7735fb718593132bf401c4
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Jun 20 21:29:52 2012 +0200

    be somewhat lenient when doing the one-bitmap WMF optimization
    
    The document from bnc#765998 contains a rather huge WMF with poor
    quality. It could be smoothscaled to get a much better result,
    but doing that would be too slow with an image of this size,
    and it would be done every single time the image would need to be
    painted, because the resulting image would not be cached.
    
    One reason for this is that the WMF appears to be kinda broken (or let's
    say imprecise [which is no wonder after trying to read things like
    http://msdn.microsoft.com/en-us/library/dd162607(v=vs.85).aspx
    and trying to understand what exactly rlcFrames is supposed to be]).
    
    Change-Id: I017db36ec96f5405ff5965943003d5aa93018a37

diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 1967e44..1c2ea1a 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -48,64 +48,6 @@
 #define WATERMARK_LUM_OFFSET        50
 #define WATERMARK_CON_OFFSET        -70
 
-// -----------
-// - helpers -
-// -----------
-
-namespace {
-
-void muckWithBitmap( const Point&    rDestPoint,
-                     const Size&     rDestSize,
-                     const Size&     rRefSize,
-                     bool&           o_rbNonBitmapActionEncountered )
-{
-    const Point aEmptyPoint;
-
-    if( aEmptyPoint != rDestPoint ||
-        rDestSize != rRefSize )
-    {
-        // non-fullscale, or offsetted bmp -> fallback to mtf
-        // rendering
-        o_rbNonBitmapActionEncountered = true;
-    }
-}
-
-BitmapEx muckWithBitmap( const BitmapEx& rBmpEx,
-                         const Point&    rSrcPoint,
-                         const Size&     rSrcSize,
-                         const Point&    rDestPoint,
-                         const Size&     rDestSize,
-                         const Size&     rRefSize,
-                         bool&           o_rbNonBitmapActionEncountered )
-{
-    BitmapEx aBmpEx;
-
-    muckWithBitmap(rDestPoint,
-                   rDestSize,
-                   rRefSize,
-                   o_rbNonBitmapActionEncountered);
-
-    if( o_rbNonBitmapActionEncountered )
-        return aBmpEx;
-
-    aBmpEx = rBmpEx;
-
-    if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) ||
-        rSrcSize != rBmpEx.GetSizePixel() )
-    {
-        // crop bitmap to given source rectangle (no
-        // need to copy and convert the whole bitmap)
-        const Rectangle aCropRect( rSrcPoint,
-                                   rSrcSize );
-        aBmpEx.Crop( aCropRect );
-    }
-
-    return aBmpEx;
-}
-
-} // namespace {
-
-
 // ------------------
 // - GraphicManager -
 // ------------------
@@ -585,6 +527,66 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
 
 // -----------------------------------------------------------------------------
 
+// This function checks whether the bitmap is usable for skipping
+// mtf rendering by using just this one bitmap (i.e. in case the metafile
+// contains just this one pixmap that covers the entire metafile area).
+static BitmapEx checkMetadataBitmap( const BitmapEx& rBmpEx,
+                                     Point    rSrcPoint,
+                                     Size     rSrcSize,
+                                     const Point&    rDestPoint,
+                                     const Size&     rDestSize,
+                                     const Size&     rRefSize,
+                                     bool&           o_rbNonBitmapActionEncountered )
+{
+    BitmapEx aBmpEx;
+    if( rSrcSize == Size())
+        rSrcSize = rBmpEx.GetSizePixel();
+
+    if( rDestPoint != Point( 0, 0 ))
+    {   // The pixmap in the metafile has an offset (and so would not cover)
+        // the entire result -> fall back to mtf rendering.
+        o_rbNonBitmapActionEncountered = true;
+        return aBmpEx;
+    }
+    if( rDestSize != rRefSize )
+    {   // The pixmap is not fullscale (does not cover the entire metafile area).
+        // HACK: The code here should refuse to use the bitmap directly
+        // and fall back to mtf rendering, but there seem to be metafiles
+        // that do not specify exactly their area (the Windows API requires apps
+        // the specify it manually, the rectangle is specified as topleft/bottomright
+        // rather than topleft/size [which may be confusing], and the docs
+        // on the exact meaning are somewhat confusing as well), so if it turns
+        // out this metafile really contains just one bitmap and no other painting,
+        // and if the sizes almost match, just use the pixmap (which will be scaled
+        // to fit exactly the requested size, so there should not be any actual problem
+        // caused by this small difference). This will allow caching of the resulting
+        // (scaled) pixmap, which can make a noticeable performance difference.
+        if( rBmpEx.GetSizePixel().Width() > 100 && rBmpEx.GetSizePixel().Height() > 100
+            && abs( rDestSize.Width() - rRefSize.Width()) < 5
+            && abs( rDestSize.Height() - rRefSize.Height()) < 5 )
+            ; // ok, assume it's close enough
+        else
+        {  // fall back to mtf rendering
+            o_rbNonBitmapActionEncountered = true;
+            return aBmpEx;
+        }
+    }
+
+    aBmpEx = rBmpEx;
+
+    if( (rSrcPoint.X() != 0 && rSrcPoint.Y() != 0) ||
+        rSrcSize != rBmpEx.GetSizePixel() )
+    {
+        // crop bitmap to given source rectangle (no
+        // need to copy and convert the whole bitmap)
+        const Rectangle aCropRect( rSrcPoint,
+                                   rSrcSize );
+        aBmpEx.Crop( aCropRect );
+    }
+
+    return aBmpEx;
+}
+
 sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                        const Point& rPt, const Size& rSz,
                                        const GDIMetaFile& rMtf, const GraphicAttr& rAttr,
@@ -675,12 +677,14 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     {
                         MetaBmpAction* pAction = (MetaBmpAction*)pAct;
 
-                        rOutBmpEx = BitmapEx( pAction->GetBitmap() );
-                        muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
-                                                            rPrefMapMode ),
-                                        pAction->GetBitmap().GetSizePixel(),
-                                        rSizePix,
-                                        bNonBitmapActionEncountered );
+                        rOutBmpEx = checkMetadataBitmap(
+                            BitmapEx( pAction->GetBitmap()),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pAction->GetBitmap().GetSizePixel(),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
                         ++nNumBitmaps;
                     }
                     break;
@@ -690,13 +694,15 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     {
                         MetaBmpScaleAction* pAction = (MetaBmpScaleAction*)pAct;
 
-                        rOutBmpEx = BitmapEx( pAction->GetBitmap() );
-                        muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
-                                                            rPrefMapMode ),
-                                        pOut->LogicToPixel( pAction->GetSize(),
-                                                            rPrefMapMode ),
-                                        rSizePix,
-                                        bNonBitmapActionEncountered );
+                        rOutBmpEx = checkMetadataBitmap(
+                            BitmapEx( pAction->GetBitmap()),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pOut->LogicToPixel( pAction->GetSize(),
+                                                rPrefMapMode ),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
                         ++nNumBitmaps;
                     }
                     break;
@@ -706,7 +712,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     {
                         MetaBmpScalePartAction* pAction = (MetaBmpScalePartAction*)pAct;
 
-                        rOutBmpEx = muckWithBitmap( BitmapEx( pAction->GetBitmap() ),
+                        rOutBmpEx = checkMetadataBitmap(
+                                                    BitmapEx( pAction->GetBitmap() ),
                                                     pAction->GetSrcPoint(),
                                                     pAction->GetSrcSize(),
                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
@@ -724,12 +731,14 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     {
                         MetaBmpExAction* pAction = (MetaBmpExAction*)pAct;
 
-                        rOutBmpEx = pAction->GetBitmapEx();
-                        muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
-                                                            rPrefMapMode ),
-                                        pAction->GetBitmapEx().GetSizePixel(),
-                                        rSizePix,
-                                        bNonBitmapActionEncountered );
+                        rOutBmpEx = checkMetadataBitmap(
+                            pAction->GetBitmapEx(),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pAction->GetBitmapEx().GetSizePixel(),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
                         ++nNumBitmaps;
                     }
                     break;
@@ -739,13 +748,15 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     {
                         MetaBmpExScaleAction* pAction = (MetaBmpExScaleAction*)pAct;
 
-                        rOutBmpEx = pAction->GetBitmapEx();
-                        muckWithBitmap( pOut->LogicToPixel( pAction->GetPoint(),
-                                                            rPrefMapMode ),
-                                        pOut->LogicToPixel( pAction->GetSize(),
-                                                            rPrefMapMode ),
-                                        rSizePix,
-                                        bNonBitmapActionEncountered );
+                        rOutBmpEx = checkMetadataBitmap(
+                            pAction->GetBitmapEx(),
+                            Point(), Size(),
+                            pOut->LogicToPixel( pAction->GetPoint(),
+                                                rPrefMapMode ),
+                            pOut->LogicToPixel( pAction->GetSize(),
+                                                rPrefMapMode ),
+                            rSizePix,
+                            bNonBitmapActionEncountered );
                         ++nNumBitmaps;
                     }
                     break;
@@ -755,7 +766,7 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                     {
                         MetaBmpExScalePartAction* pAction = (MetaBmpExScalePartAction*)pAct;
 
-                        rOutBmpEx = muckWithBitmap( pAction->GetBitmapEx(),
+                        rOutBmpEx = checkMetadataBitmap( pAction->GetBitmapEx(),
                                                     pAction->GetSrcPoint(),
                                                     pAction->GetSrcSize(),
                                                     pOut->LogicToPixel( pAction->GetDestPoint(),
commit 622f7f9939aa7001bbf7b631bf5b4e23f8cf82e0
Author: Tomaž Vajngerl <quikee at gmail.com>
Date:   Fri Jun 15 07:17:36 2012 +0200

    Add new Scale modes, simplify convolution calculation.
    
    Convolution calculation now uses 2x transposing horizontal pass
    instead of horizontal and vertical which simplifies the code by
    reducing code duplication.
    
    Instead of more convolution methods, only one generic method is
    used and kernels are now a parameter to the method. For this
    Kernel class was introduced with responsibility to calculate
    kernel walues and hold kernel specific information.
    
    Besides Lanzcos resampling also Box, Bilinear and Bicubic resampling
    was introduced. Box is the simplest and fastest but with still
    good quality.

diff --git a/vcl/inc/vcl/bitmap.hxx b/vcl/inc/vcl/bitmap.hxx
index f1183ac..efc37a0 100644
--- a/vcl/inc/vcl/bitmap.hxx
+++ b/vcl/inc/vcl/bitmap.hxx
@@ -50,6 +50,9 @@
 #define BMP_SCALE_FAST              0x00000001UL
 #define BMP_SCALE_INTERPOLATE       0x00000002UL
 #define BMP_SCALE_LANCZOS           0x00000003UL
+#define BMP_SCALE_BICUBIC           0x00000004UL
+#define BMP_SCALE_BILINEAR          0x00000005UL
+#define BMP_SCALE_BOX               0x00000006UL
 
 // Aliases, try to use these two (or BMP_SCALE_FAST/BMP_SCALE_NONE),
 // use a specific algorithm only if you really need to.
@@ -163,7 +166,7 @@ class VCL_DLLPUBLIC BmpFilterParam
     friend class Animation;
 
 private:
-    BmpFilter   meFilter;
+    BmpFilter       meFilter;
     sal_uLong       mnProgressStart;
     sal_uLong       mnProgressEnd;
 
@@ -218,6 +221,89 @@ public:
         }
 };
 
+// --------------------
+// Resample Kernels
+// --------------------
+
+class Kernel
+{
+
+public:
+    Kernel () {}
+    virtual ~Kernel() {}
+
+    virtual double GetWidth() = 0;
+    virtual double Calculate( double x ) = 0;
+};
+
+class Lanczos3Kernel : public Kernel
+{
+
+public:
+    virtual double GetWidth() { return 3.0; }
+    virtual double Calculate (double x)
+    {
+        return (-3.0 <= x && x < 3.0) ? SincFilter(x) * SincFilter( x / 3.0 ) : 0.0;
+    }
+
+    inline double SincFilter(double x)
+    {
+        if (x == 0.0)
+        {
+            return 1.0;
+        }
+        x = x * M_PI;
+        return sin(x) / x;
+    }
+};
+
+class BicubicKernel : public Kernel {
+    virtual double GetWidth() { return 2.0; }
+    virtual double Calculate (double x)
+    {
+        if (x < 0.0)
+        {
+            x = -x;
+        }
+
+        if (x <= 1.0)
+        {
+            return (1.5 * x - 2.5) * x * x + 1.0;
+        }
+        else if (x < 2.0)
+        {
+            return ((-0.5 * x + 2.5) * x - 4) * x + 2;
+        }
+        return 0.0;
+    }
+};
+
+class BilinearKernel : public Kernel {
+    virtual double GetWidth() { return 1.0; }
+    virtual double Calculate (double x)
+    {
+        if (x < 0.0)
+        {
+            x = -x;
+        }
+        if (x < 1.0)
+        {
+            return 1.0-x;
+        }
+        return 0.0;
+    }
+};
+
+class BoxKernel : public Kernel {
+    virtual double GetWidth() { return 0.5; }
+    virtual double Calculate (double x)
+    {
+        if (-0.5 <= x && x < 0.5)
+            return 1.0;
+        return 0.0;
+    }
+};
+
 // ----------
 // - Bitmap -
 // ----------
@@ -282,17 +368,14 @@ public:
 
     SAL_DLLPRIVATE sal_Bool                 ImplScaleFast( const double& rScaleX, const double& rScaleY );
     SAL_DLLPRIVATE sal_Bool                 ImplScaleInterpolate( const double& rScaleX, const double& rScaleY );
-    SAL_DLLPRIVATE bool                     ImplScaleLanczos( const double& rScaleX, const double& rScaleY );
+    SAL_DLLPRIVATE bool                     ImplScaleConvolution( const double& rScaleX, const double& rScaleY, Kernel& aKernel);
 
-    SAL_DLLPRIVATE void                     ImplCalculateContributions( const int aSourceSize, const int aDestinationSize,
-                                                const double aSupport, const int aNumberOfContributions,
-                                                double* pWeights, int* pPixels, int* pCount );
-    SAL_DLLPRIVATE bool                     ImplHorizontalConvolution( Bitmap& aNewBitmap, BitmapReadAccess* pReadAcc,
-                                                int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount );
-    SAL_DLLPRIVATE bool                     ImplVerticalConvolution( Bitmap& aNewBitmap, BitmapReadAccess* pReadAcc,
-                                                int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount );
+    SAL_DLLPRIVATE static void              ImplCalculateContributions( const int aSourceSize, const int aDestinationSize,
+                                                int& aNumberOfContributions, double*& pWeights, int*& pPixels, int*& pCount,
+                                                Kernel& aKernel );
 
-    SAL_DLLPRIVATE static double            ImplLanczosKernel( const double aValue, const double aSupport );
+    SAL_DLLPRIVATE bool                     ImplConvolutionPass( Bitmap& aNewBitmap, const int nNewSize, BitmapReadAccess* pReadAcc,
+                                                int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount );
 
     SAL_DLLPRIVATE sal_Bool                 ImplMakeMono( sal_uInt8 cThreshold );
     SAL_DLLPRIVATE sal_Bool                 ImplMakeMonoDither();
@@ -310,7 +393,7 @@ public:
                                            long nR1, long nR2, long nG1, long nG2, long nB1, long nB2,
                                            long nColors, long nPixels, long& rIndex );
     SAL_DLLPRIVATE sal_Bool                 ImplConvolute3( const long* pMatrix, long nDivisor,
-                                            const BmpFilterParam* pFilterParam, const Link* pProgress );
+                                                            const BmpFilterParam* pFilterParam, const Link* pProgress );
     SAL_DLLPRIVATE sal_Bool                 ImplMedianFilter( const BmpFilterParam* pFilterParam, const Link* pProgress );
     SAL_DLLPRIVATE sal_Bool                 ImplSobelGrey( const BmpFilterParam* pFilterParam, const Link* pProgress );
     SAL_DLLPRIVATE sal_Bool                 ImplEmbossGrey( const BmpFilterParam* pFilterParam, const Link* pProgress );
diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx
index ec458d9..a469681 100644
--- a/vcl/source/gdi/bitmap3.cxx
+++ b/vcl/source/gdi/bitmap3.cxx
@@ -912,13 +912,37 @@ sal_Bool Bitmap::Scale( const double& rScaleX, const double& rScaleY, sal_uLong
     if( ( rScaleX != 1.0 ) || ( rScaleY != 1.0 ) )
     {
         if( BMP_SCALE_FAST == nScaleFlag )
+        {
             bRet = ImplScaleFast( rScaleX, rScaleY );
+        }
         else if( BMP_SCALE_INTERPOLATE == nScaleFlag )
+        {
             bRet = ImplScaleInterpolate( rScaleX, rScaleY );
+        }
         else if( BMP_SCALE_LANCZOS == nScaleFlag )
-            bRet = ImplScaleLanczos( rScaleX, rScaleY );
+        {
+            Lanczos3Kernel kernel;
+            bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel);
+        }
+        else if( BMP_SCALE_BICUBIC == nScaleFlag )
+        {
+            BicubicKernel kernel;
+            bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+        }
+        else if( BMP_SCALE_BILINEAR == nScaleFlag )
+        {
+            BilinearKernel kernel;
+            bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+        }
+        else if( BMP_SCALE_BOX == nScaleFlag )
+        {
+            BoxKernel kernel;
+            bRet = ImplScaleConvolution( rScaleX, rScaleY, kernel );
+        }
         else
-            bRet = sal_False;
+        {
+            return false;
+        }
     }
     else
         bRet = sal_True;
@@ -2208,33 +2232,28 @@ sal_Bool Bitmap::Adjust( short nLuminancePercent, short nContrastPercent,
     return bRet;
 }
 
-bool Bitmap::ImplScaleLanczos( const double& rScaleX, const double& rScaleY )
+bool Bitmap::ImplScaleConvolution( const double& rScaleX, const double& rScaleY, Kernel& aKernel )
 {
-    const Size  aSizePix( GetSizePixel() );
-    const long  nWidth = aSizePix.Width();
-    const long  nHeight = aSizePix.Height();
+    const long  nWidth = GetSizePixel().Width();
+    const long  nHeight = GetSizePixel().Height();
     const long  nNewWidth = FRound( nWidth * rScaleX );
     const long  nNewHeight = FRound( nHeight * rScaleY );
 
-    double aSupport = 3.0; // Sampling radius
-
-    // Do horizontal filtering
-    double aScale = nNewWidth / (double) nWidth;
-    double aScaledRadius = (aScale <= 1.0) ? aSupport / aScale : aSupport;
-
-    int aNumberOfContributions  = (int) ( 2 * aScaledRadius + 1 );
+    bool bResult;
+    BitmapReadAccess* pReadAcc;
+    Bitmap aNewBitmap;
 
-    double* pWeights = new double[ nNewWidth*aNumberOfContributions ];
-    int* pPixels = new int[ nNewWidth*aNumberOfContributions ];
-    int* pCount = new int[ nNewWidth ];
+    int aNumberOfContributions;
+    double* pWeights;
+    int* pPixels;
+    int* pCount;
 
-    ImplCalculateContributions( nWidth, nNewWidth, aSupport, aNumberOfContributions, pWeights, pPixels, pCount );
-
-    BitmapReadAccess* pReadAcc = AcquireReadAccess();
-    Bitmap aNewBitmap( Size( nNewWidth, nHeight ), 24);
-    bool bResult = ImplHorizontalConvolution( aNewBitmap, pReadAcc, aNumberOfContributions, pWeights, pPixels, pCount );
+    // Do horizontal filtering
+    ImplCalculateContributions( nWidth, nNewWidth, aNumberOfContributions, pWeights, pPixels, pCount, aKernel );
+    pReadAcc = AcquireReadAccess();
+    aNewBitmap = Bitmap( Size( nHeight, nNewWidth ), 24);
+    bResult = ImplConvolutionPass( aNewBitmap, nNewWidth, pReadAcc, aNumberOfContributions, pWeights, pPixels, pCount );
 
-    // Cleanup
     ReleaseAccess( pReadAcc );
     delete[] pWeights;
     delete[] pCount;
@@ -2243,26 +2262,15 @@ bool Bitmap::ImplScaleLanczos( const double& rScaleX, const double& rScaleY )
     if ( !bResult )
         return bResult;
 
-    // Swap current bitmap with new bitmap
+    // Swap Bitmaps
     ImplAssignWithSize( aNewBitmap );
 
     // Do vertical filtering
-    aScale = nNewHeight / (double) nHeight;
-    aScaledRadius = (aScale <= 1.0) ? aSupport / aScale : aSupport;
-
-    aNumberOfContributions  = (int) ( 2 * aScaledRadius + 1 );
-
-    pWeights = new double[ nNewHeight*aNumberOfContributions ];
-    pPixels = new int[ nNewHeight*aNumberOfContributions ];
-    pCount = new int[ nNewHeight ];
-
-    ImplCalculateContributions(nHeight, nNewHeight, aSupport, aNumberOfContributions, pWeights, pPixels, pCount );
-
+    ImplCalculateContributions( nHeight, nNewHeight, aNumberOfContributions, pWeights, pPixels, pCount, aKernel );
     pReadAcc = AcquireReadAccess();
     aNewBitmap = Bitmap( Size( nNewWidth, nNewHeight ), 24);
-    bResult = ImplVerticalConvolution( aNewBitmap, pReadAcc, aNumberOfContributions, pWeights, pPixels, pCount );
+    bResult = ImplConvolutionPass( aNewBitmap, nNewHeight, pReadAcc, aNumberOfContributions, pWeights, pPixels, pCount );
 
-    // Cleanup
     ReleaseAccess( pReadAcc );
     delete[] pWeights;
     delete[] pCount;
@@ -2271,19 +2279,24 @@ bool Bitmap::ImplScaleLanczos( const double& rScaleX, const double& rScaleY )
     if ( !bResult )
         return bResult;
 
-    // Swap current bitmap with new bitmap
     ImplAssignWithSize( aNewBitmap );
 
     return true;
 }
 
-void Bitmap::ImplCalculateContributions( const int aSourceSize, const int aDestinationSize, const double aSupport,
-                                         const int aNumberOfContributions, double* pWeights, int* pPixels,
-                                         int* pCount )
+void Bitmap::ImplCalculateContributions( const int aSourceSize, const int aDestinationSize, int& aNumberOfContributions,
+                                            double*& pWeights, int*& pPixels, int*& pCount, Kernel& aKernel)
 {
+    const double aSamplingRadius = aKernel.GetWidth();
     const double aScale = aDestinationSize / (double) aSourceSize;
-    const double aScaledRadius = (aScale <= 1.0) ? aSupport / aScale : aSupport;
-    const double aFilterFactor = (aScale <= 1.0) ? aScale : 1.0;
+    const double aScaledRadius = (aScale < 1.0) ? aSamplingRadius / aScale : aSamplingRadius;
+    const double aFilterFactor = (aScale < 1.0) ? aScale : 1.0;
+
+    aNumberOfContributions  = (int) ( 2 * ceil(aScaledRadius) + 1 );
+
+    pWeights = new double[ aDestinationSize*aNumberOfContributions ];
+    pPixels = new int[ aDestinationSize*aNumberOfContributions ];
+    pCount = new int[ aDestinationSize ];
 
     double aWeight, aCenter;
     int aIndex, aLeft, aRight;
@@ -2295,37 +2308,19 @@ void Bitmap::ImplCalculateContributions( const int aSourceSize, const int aDesti
         aCurrentCount = 0;
         aCenter = i / aScale;
 
-        aLeft = (int) ((aCenter + 0.5) - aScaledRadius );
-        aRight = (int) ( aLeft + 2 * aScaledRadius );
+        aLeft  = (int) floor(aCenter - aScaledRadius);
+        aRight = (int) ceil (aCenter + aScaledRadius);
 
         for ( int j = aLeft; j <= aRight; j++ )
         {
-            aWeight = ImplLanczosKernel( (aCenter - j) * aFilterFactor, aSupport );
+            aWeight = aKernel.Calculate( aFilterFactor * ( aCenter - (double) j ) );
 
-            if (aWeight == 0.0)
-            {
+            // Reduce calculations with ignoring weights of 0.0
+            if (fabs(aWeight < 0.0001))
                 continue;
-            }
-
-            // Mirror edges
-            if (j < 0)
-            {
-                aPixelIndex = -j;
-            }
-            else if ( j >= aSourceSize )
-            {
-                aPixelIndex = (aSourceSize - j) + aSourceSize - 1;
-            }
-            else
-            {
-                aPixelIndex = j;
-            }
 
-            // Edge case for small bitmaps
-            if ( aPixelIndex < 0 || aPixelIndex >= aSourceSize )
-            {
-                aWeight = 0.0;
-            }
+            // Handling on edges
+            aPixelIndex = MinMax( j, 0, aSourceSize - 1);
 
             pWeights[ aIndex + aCurrentCount ] = aWeight;
             pPixels[ aIndex + aCurrentCount ] = aPixelIndex;
@@ -2336,17 +2331,14 @@ void Bitmap::ImplCalculateContributions( const int aSourceSize, const int aDesti
     }
 }
 
-bool Bitmap::ImplHorizontalConvolution(Bitmap& aNewBitmap, BitmapReadAccess* pReadAcc, int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount)
+bool Bitmap::ImplConvolutionPass(Bitmap& aNewBitmap, const int nNewSize, BitmapReadAccess* pReadAcc, int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount)
 {
     BitmapWriteAccess* pWriteAcc = aNewBitmap.AcquireWriteAccess();
 
     if (!pReadAcc || !pWriteAcc)
-    {
         return false;
-    }
 
     const int nHeight = GetSizePixel().Height();
-    const int nNewWidth = aNewBitmap.GetSizePixel().Width();
 
     BitmapColor aColor;
     double aValueRed, aValueGreen, aValueBlue;
@@ -2355,79 +2347,20 @@ bool Bitmap::ImplHorizontalConvolution(Bitmap& aNewBitmap, BitmapReadAccess* pRe
 
     for ( int y = 0; y < nHeight; y++ )
     {
-        for ( int i = 0; i < nNewWidth; i++ )
+        for ( int x = 0; x < nNewSize; x++ )
         {
-            aBaseIndex = i * aNumberOfContributions;
-            aValueRed = aValueGreen = aValueBlue = 0.0;
-            aSum = 0.0;
+            aBaseIndex = x * aNumberOfContributions;
+            aSum = aValueRed = aValueGreen = aValueBlue = 0.0;
 
-            for ( int j=0; j < pCount[i]; j++ )
+            for ( int j=0; j < pCount[x]; j++ )
             {
                 aIndex = aBaseIndex + j;
-                aWeight = pWeights[ aIndex ];
-                aSum += aWeight;
-                if( pReadAcc->HasPalette() )
-                {
-                    aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( y , pPixels[ aIndex ] ) );
-                }
-                else
-                {
-                    aColor = pReadAcc->GetPixel( y , pPixels[ aIndex ] );
-                }
+                aSum += aWeight = pWeights[ aIndex ];
 
-                aValueRed   += aWeight * aColor.GetRed();
-                aValueGreen += aWeight * aColor.GetGreen();
-                aValueBlue  += aWeight * aColor.GetBlue();
-            }
-
-            BitmapColor aResultColor(
-                (sal_uInt8) MinMax( aValueRed   / aSum, 0, 255 ),
-                (sal_uInt8) MinMax( aValueGreen / aSum, 0, 255 ),
-                (sal_uInt8) MinMax( aValueBlue  / aSum, 0, 255 ) );
-            pWriteAcc->SetPixel( y, i, aResultColor );
-        }
-    }
-    aNewBitmap.ReleaseAccess( pWriteAcc );
-    return true;
-}
-
-bool Bitmap::ImplVerticalConvolution(Bitmap& aNewBitmap, BitmapReadAccess* pReadAcc, int aNumberOfContributions, double* pWeights, int* pPixels, int* pCount)
-{
-    BitmapWriteAccess* pWriteAcc = aNewBitmap.AcquireWriteAccess();
-
-    if (!pReadAcc || !pWriteAcc)
-    {
-        return false;
-    }
-
-    const int   nWidth = GetSizePixel().Width();
-    const int   nNewHeight = aNewBitmap.GetSizePixel().Height();
-
-    BitmapColor aColor;
-    double aValueRed, aValueGreen, aValueBlue;
-    double aSum, aWeight;
-    int aBaseIndex, aIndex;
-    for (int x = 0; x < nWidth; x++)
-    {
-        for (int i = 0; i < nNewHeight; i++)
-        {
-            aBaseIndex = i * aNumberOfContributions;
-            aSum = 0.0;
-            aValueRed = aValueGreen = aValueBlue = 0.0;
-
-            for (int j=0; j < pCount[i]; j++)
-            {
-                aIndex = aBaseIndex + j;
-                aWeight = pWeights[ aIndex ];
-                aSum += aWeight;
+                aColor = pReadAcc->GetPixel( y, pPixels[ aIndex ] );
                 if( pReadAcc->HasPalette() )
-                {
-                    aColor = pReadAcc->GetPaletteColor( pReadAcc->GetPixel( pPixels[ aIndex ] , x ) );
-                }
-                else
-                {
-                    aColor = pReadAcc->GetPixel( pPixels[ aIndex ] , x );
-                }
+                    aColor = pReadAcc->GetPaletteColor( aColor );
+
                 aValueRed   += aWeight * aColor.GetRed();
                 aValueGreen += aWeight * aColor.GetGreen();
                 aValueBlue  += aWeight * aColor.GetBlue();
@@ -2437,32 +2370,11 @@ bool Bitmap::ImplVerticalConvolution(Bitmap& aNewBitmap, BitmapReadAccess* pRead
                 (sal_uInt8) MinMax( aValueRed   / aSum, 0, 255 ),
                 (sal_uInt8) MinMax( aValueGreen / aSum, 0, 255 ),
                 (sal_uInt8) MinMax( aValueBlue  / aSum, 0, 255 ) );
-            pWriteAcc->SetPixel( i, x, aResultColor );
+            pWriteAcc->SetPixel( x, y, aResultColor );
         }
     }
-
     aNewBitmap.ReleaseAccess( pWriteAcc );
     return true;
 }
 
-double Bitmap::ImplLanczosKernel( const double aValue, const double aSupport ) {
-    double x = aValue;
-    if (x == 0.0)
-    {
-        return 1.0;
-    }
-    if (x < 0.0)
-    {
-        x = -x;
-    }
-
-    x *= M_PI;
-    if (x < aSupport)
-    {
-        double x3 = x / 3.0;
-        return (sin(x) / x) * sin(x3) / x3;
-    }
-    return 0.0;
-}
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list