[Libreoffice-commits] .: 9 commits - svtools/inc svtools/source

Lubos Lunak llunak at kemper.freedesktop.org
Fri Jun 22 07:50:46 PDT 2012


 svtools/inc/svtools/grfmgr.hxx       |    4 
 svtools/source/filter/wmf/enhwmf.cxx |    8 
 svtools/source/filter/wmf/winwmf.cxx |    2 
 svtools/source/graphic/grfcache.cxx  |  312 +++++++++++++++++++++++++++++++++--
 svtools/source/graphic/grfmgr2.cxx   |  271 +++++++++++++++---------------
 5 files changed, 448 insertions(+), 149 deletions(-)

New commits:
commit baca49fdda5e350b7b0f122d50739ee98cc6fe25
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 a03c668..f4ab6ca 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -342,34 +342,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;
@@ -451,7 +424,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
                 {
@@ -477,6 +465,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 0c10b8ff9fa115ec2c315bd75a9eddc1cd4c0ac2
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.
    
    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 bd77e25..a03c668 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -536,6 +536,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();
@@ -609,6 +610,9 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
         const MapMode rPrefMapMode( rMtf.GetPrefMapMode() );
         const Size rSizePix( pOut->LogicToPixel( aNewSize, rPrefMapMode ) );
 
+// 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
commit a83bf946d6e1f315a19ce6e6c9b5ddcb30926a22
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 d0cf55b..bd77e25 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -683,8 +683,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                             pAction->GetBitmap().GetSizePixel(),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPSCALE_ACTION:
@@ -701,8 +701,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                 rPrefMapMode ),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPSCALEPART_ACTION:
@@ -720,8 +720,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                                         rPrefMapMode ),
                                                     rSizePix,
                                                     bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPEX_ACTION:
@@ -737,8 +737,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                             pAction->GetBitmapEx().GetSizePixel(),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPEXSCALE_ACTION:
@@ -755,8 +755,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                 rPrefMapMode ),
                             rSizePix,
                             bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                 case META_BMPEXSCALEPART_ACTION:
@@ -773,8 +773,8 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
                                                                         rPrefMapMode ),
                                                     rSizePix,
                                                     bNonBitmapActionEncountered );
-                        ++nNumBitmaps;
                     }
+                    ++nNumBitmaps;
                     break;
 
                     // these actions actually output something (that's
commit 77987eacff20dec40caf29aae61d262239d441e9
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 a9f357c..d0cf55b 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 -
 // ------------------
@@ -583,6 +525,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,
@@ -673,12 +675,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;
@@ -688,13 +692,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;
@@ -704,7 +710,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(),
@@ -722,12 +729,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;
@@ -737,13 +746,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;
@@ -753,7 +764,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 43cd955d4052d9ffa4de5444d0900fba0d7ef3b1
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Jun 20 20:59:47 2012 +0200

    improve/fix comments
    
    Change-Id: Ie3c017eb9c6ceadd4b7982eb2a28c74bf6767631

diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 4565a67..a9f357c 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -317,9 +317,8 @@ sal_Bool GraphicManager::ImplDraw( OutputDevice* pOut, const Point& rPt,
                 {
                     if( !!aContainedBmpEx )
                     {
-                        // #117889# Use bitmap output method, if
-                        // metafile basically contains only a single
-                        // bitmap
+                        // Use bitmap output method, if metafile basically contains only a single
+                        // bitmap (allows caching the resulting pixmap).
                         BitmapEx aDstBmpEx;
 
                         if( ImplCreateOutput( pOut, rPt, rSz, aContainedBmpEx, rAttr, nFlags, &aDstBmpEx ) )
@@ -593,7 +592,7 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
 
     rOutMtf = rMtf;
 
-    // #117889# count bitmap actions, and flag actions that paint, but
+    // Count bitmap actions, and flag actions that paint, but
     // are no bitmaps.
     sal_Int32   nNumBitmaps(0);
     bool        bNonBitmapActionEncountered(false);
@@ -608,9 +607,9 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
         const MapMode rPrefMapMode( rMtf.GetPrefMapMode() );
         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
+        // 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
@@ -627,6 +626,7 @@ sal_Bool GraphicManager::ImplCreateOutput( OutputDevice* pOut,
             {
                 case META_FONT_ACTION:
                 {
+                    // taking care of font width default if scaling metafile.
                     MetaFontAction* pA = (MetaFontAction*)pAct;
                     Font aFont( pA->GetFont() );
                     if ( !aFont.GetWidth() )
commit 00285a7de24019f9c9eaf9a165a4bed21938eb21
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 2043afa..7d04d3d 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
@@ -1016,7 +1016,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 bf5d91d495efc24c50fbb6783f0b59e66a783e23
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 d9daf2a..af15126 100644
--- a/svtools/source/filter/wmf/winwmf.cxx
+++ b/svtools/source/filter/wmf/winwmf.cxx
@@ -1201,7 +1201,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 a6b68e0d23d137f93d7c1d06fd17624d4e09aa4f
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Jun 20 19:25:04 2012 +0200

    remove useless comments
    
    Change-Id: I8702f8e4b76731ab167533478ba754c94114f419

diff --git a/svtools/source/filter/wmf/enhwmf.cxx b/svtools/source/filter/wmf/enhwmf.cxx
index f19c8f1..2043afa 100644
--- a/svtools/source/filter/wmf/enhwmf.cxx
+++ b/svtools/source/filter/wmf/enhwmf.cxx
@@ -987,9 +987,6 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
                             Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
                             aBitmap.Crop( aCropRect );
                         }
-                    /* Pseudocomment to add more context so that make patch.unapply
-                     * works better. Ha!
-                     */
                     aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
                     }
                 }
@@ -1060,7 +1057,6 @@ sal_Bool EnhWMFReader::ReadEnhWMF()
                             Rectangle aCropRect( Point( xSrc, ySrc ), Size( cxSrc, cySrc ) );
                             aBitmap.Crop( aCropRect );
                         }
-                    /* Another pseudocomment to make make patch.unapply work better */
                     aBmpSaveList.push_back( new BSaveStruct( aBitmap, aRect, dwRop, pOut->GetFillStyle () ) );
                     }
                 }
commit e9ebca75897f150b2e6f09f9e6153ff9ef3c5906
Author: Luboš Luňák <l.lunak at suse.cz>
Date:   Wed Jun 20 17:06:43 2012 +0200

    remove unused variable
    
    Change-Id: I284bc45abab57127ea972ed4d4b8164b54bfa18b

diff --git a/svtools/source/graphic/grfmgr2.cxx b/svtools/source/graphic/grfmgr2.cxx
index 1a43fe8..4565a67 100644
--- a/svtools/source/graphic/grfmgr2.cxx
+++ b/svtools/source/graphic/grfmgr2.cxx
@@ -177,7 +177,6 @@ sal_Bool GraphicManager::DrawObj( OutputDevice* pOut, const Point& rPt, const Si
     if( ( rObj.GetType() == GRAPHIC_BITMAP ) || ( rObj.GetType() == GRAPHIC_GDIMETAFILE ) )
     {
         // create output and fill cache
-        const Size aOutSize( pOut->GetOutputSizePixel() );
 
         if( rObj.IsAnimated() || ( pOut->GetOutDevType() == OUTDEV_PRINTER ) ||
             ( !( nFlags & GRFMGR_DRAW_NO_SUBSTITUTE ) &&


More information about the Libreoffice-commits mailing list