[Libreoffice-commits] core.git: include/sfx2 sfx2/source

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Mon Oct 12 13:13:53 UTC 2020


 include/sfx2/objsh.hxx           |    8 +++
 sfx2/source/appl/sfxpicklist.cxx |    5 --
 sfx2/source/doc/objcont.cxx      |   83 +++++++++++++++++++++++++++++++--------
 sfx2/source/doc/sfxbasemodel.cxx |    2 
 4 files changed, 77 insertions(+), 21 deletions(-)

New commits:
commit 59cca1a28df4cdc94450d68cc1e247a8fb5ff6f3
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Fri Oct 9 13:21:34 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Mon Oct 12 15:13:17 2020 +0200

    render document thumbnail directly to bitmap, without metafile
    
    I don't see the point of taking the detour via GDIMetaFile and
    then immediately drawing using it to a bitmap. Simply draw directly
    to a bitmap. Especially given that when drawing to a metafile
    some fast cases are skipped, e.g. DrawTransformedBitmapEx()
    avoids DrawTransformBitmapExDirect() and resorts to using the slow
    BitmapEx::getTransformed(). E.g. with tdf#136223. this makes
    SfxPickListImpl::AddDocumentToPickList() go from 30% to 13%
    of the total document loading time.
    
    Change-Id: Ib1643eddfc2b75a3d7be60138fb5226352805826
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104114
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index 78a1f3eb22e6..e106d7f3a367 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -26,6 +26,7 @@
 #include <vcl/errcode.hxx>
 #include <com/sun/star/uno/Reference.h>
 #include <com/sun/star/uno/Sequence.hxx>
+#include <vcl/bitmapex.hxx>
 
 #include <svl/poolitem.hxx>
 #include <sot/formats.hxx>
@@ -64,6 +65,7 @@ class Color;
 class Fraction;
 class SvGlobalName;
 class InfobarData;
+class VirtualDevice;
 
 enum class SfxModelFlags;
 enum class SfxEventHintId;
@@ -445,6 +447,10 @@ public:
     Size                        GetFirstPageSize() const;
     bool                        DoClose();
     std::shared_ptr<GDIMetaFile> GetPreviewMetaFile( bool bFullContent = false ) const;
+    BitmapEx                    GetPreviewBitmap(
+                                    bool bFullContent = false,
+                                    BmpConversion nColorConversion = BmpConversion::N24Bit,
+                                    BmpScaleFlag nScaleFlag = BmpScaleFlag::BestQuality) const;
     virtual void                CancelTransfers();
 
     bool                        GenerateAndStoreThumbnail(
@@ -681,7 +687,7 @@ public:
                                 bool bShowCloseButton = true);
     std::vector<InfobarData>& getPendingInfobars();
 
-    SAL_DLLPRIVATE std::shared_ptr<GDIMetaFile> CreatePreviewMetaFile_Impl(bool bFullContent) const;
+    SAL_DLLPRIVATE bool CreatePreview_Impl(bool bFullContent, VirtualDevice* pDevice, GDIMetaFile* pFile) const;
 
     SAL_DLLPRIVATE static bool IsPackageStorageFormat_Impl(const SfxMedium &);
 
diff --git a/sfx2/source/appl/sfxpicklist.cxx b/sfx2/source/appl/sfxpicklist.cxx
index ec32dd038d3d..82775fd9a328 100644
--- a/sfx2/source/appl/sfxpicklist.cxx
+++ b/sfx2/source/appl/sfxpicklist.cxx
@@ -118,9 +118,8 @@ void SfxPickListImpl::AddDocumentToPickList( const SfxObjectShell* pDocSh )
         }
         else
         {
-            std::shared_ptr<GDIMetaFile> xMetaFile = pDocSh->GetPreviewMetaFile();
-            BitmapEx aResultBitmap;
-            if (xMetaFile->CreateThumbnail(aResultBitmap))
+            BitmapEx aResultBitmap = pDocSh->GetPreviewBitmap();
+            if (!aResultBitmap.IsEmpty())
             {
                 SvMemoryStream aStream(65535, 65535);
                 vcl::PNGWriter aWriter(aResultBitmap);
diff --git a/sfx2/source/doc/objcont.cxx b/sfx2/source/doc/objcont.cxx
index 0a98bab1263d..3159f6d7ac84 100644
--- a/sfx2/source/doc/objcont.cxx
+++ b/sfx2/source/doc/objcont.cxx
@@ -35,6 +35,7 @@
 #include <unotools/securityoptions.hxx>
 #include <tools/datetime.hxx>
 #include <tools/diagnose_ex.h>
+#include <tools/helpers.hxx>
 #include <rtl/uri.hxx>
 
 #include <unotools/useroptions.hxx>
@@ -94,11 +95,32 @@ bool operator> (const util::DateTime& i_rLeft, const util::DateTime& i_rRight)
 std::shared_ptr<GDIMetaFile>
 SfxObjectShell::GetPreviewMetaFile( bool bFullContent ) const
 {
-    return CreatePreviewMetaFile_Impl( bFullContent );
+    auto xFile = std::make_shared<GDIMetaFile>();
+    ScopedVclPtrInstance< VirtualDevice > pDevice;
+    pDevice->EnableOutput( false );
+    if(!CreatePreview_Impl(bFullContent, pDevice, xFile.get()))
+        return std::shared_ptr<GDIMetaFile>();
+    return xFile;
 }
 
-std::shared_ptr<GDIMetaFile>
-SfxObjectShell::CreatePreviewMetaFile_Impl( bool bFullContent ) const
+BitmapEx SfxObjectShell::GetPreviewBitmap( bool bFullContent, BmpConversion nColorConversion,
+    BmpScaleFlag nScaleFlag) const
+{
+    ScopedVclPtrInstance< VirtualDevice > pDevice;
+    pDevice->SetAntialiasing(AntialiasingFlags::Enable | pDevice->GetAntialiasing());
+    if(!CreatePreview_Impl(bFullContent, pDevice, nullptr))
+        return BitmapEx();
+    Size size = pDevice->GetOutputSizePixel();
+    BitmapEx aBitmap = pDevice->GetBitmapEx( Point(), size);
+    // Scale down the image to the desired size from the 4*size from CreatePreview_Impl().
+    size = Size( size.Width() / 4, size.Height() / 4 );
+    aBitmap.Scale(size, nScaleFlag);
+    if (!aBitmap.IsEmpty())
+        aBitmap.Convert(nColorConversion);
+    return aBitmap;
+}
+
+bool SfxObjectShell::CreatePreview_Impl( bool bFullContent, VirtualDevice* pDevice, GDIMetaFile* pFile) const
 {
     // DoDraw can only be called when no printing is done, otherwise
     // the printer may be turned off
@@ -106,17 +128,9 @@ SfxObjectShell::CreatePreviewMetaFile_Impl( bool bFullContent ) const
     if ( pFrame && pFrame->GetViewShell() &&
          pFrame->GetViewShell()->GetPrinter() &&
          pFrame->GetViewShell()->GetPrinter()->IsPrinting() )
-         return std::shared_ptr<GDIMetaFile>();
-
-    auto xFile = std::make_shared<GDIMetaFile>();
-
-    ScopedVclPtrInstance< VirtualDevice > pDevice;
-    pDevice->EnableOutput( false );
+         return false;
 
     MapMode aMode( GetMapUnit() );
-    pDevice->SetMapMode( aMode );
-    xFile->SetPrefMapMode( aMode );
-
     Size aTmpSize;
     sal_Int8 nAspect;
     if ( bFullContent )
@@ -130,11 +144,47 @@ SfxObjectShell::CreatePreviewMetaFile_Impl( bool bFullContent ) const
         aTmpSize = GetFirstPageSize();
     }
 
-    xFile->SetPrefSize( aTmpSize );
     DBG_ASSERT( !aTmpSize.IsEmpty(),
         "size of first page is 0, override GetFirstPageSize or set visible-area!" );
 
-    xFile->Record( pDevice );
+    if(pFile)
+    {
+        pDevice->SetMapMode( aMode );
+        pFile->SetPrefMapMode( aMode );
+        pFile->SetPrefSize( aTmpSize );
+        pFile->Record( pDevice );
+    }
+    else
+    {
+        // Use pixel size, that's also what DoDraw() requires in this case,
+        // despite the metafile case (needlessly?) setting mapmode.
+        Size aSizePix = pDevice->LogicToPixel( aTmpSize, aMode );
+        // Code based on GDIMetaFile::CreateThumbnail().
+        sal_uInt32      nMaximumExtent = 256;
+        // determine size that has the same aspect ratio as image size and
+        // fits into the rectangle determined by nMaximumExtent
+        if ( aSizePix.Width() && aSizePix.Height()
+          && ( sal::static_int_cast< unsigned long >(aSizePix.Width()) >
+                   nMaximumExtent ||
+               sal::static_int_cast< unsigned long >(aSizePix.Height()) >
+                   nMaximumExtent ) )
+        {
+            double      fWH = static_cast< double >( aSizePix.Width() ) / aSizePix.Height();
+            if ( fWH <= 1.0 )
+            {
+                aSizePix.setWidth( FRound( nMaximumExtent * fWH ) );
+                aSizePix.setHeight( nMaximumExtent );
+            }
+            else
+            {
+                aSizePix.setWidth( nMaximumExtent );
+                aSizePix.setHeight( FRound(  nMaximumExtent / fWH ) );
+            }
+        }
+        // do it 4x larger to be able to scale it down & get beautiful antialias
+        aTmpSize = Size( aSizePix.Width() * 4, aSizePix.Height() * 4 );
+        pDevice->SetOutputSizePixel( aTmpSize );
+    }
 
     LanguageType eLang;
     SvtCTLOptions aCTLOptions;
@@ -149,9 +199,10 @@ SfxObjectShell::CreatePreviewMetaFile_Impl( bool bFullContent ) const
 
     const_cast<SfxObjectShell*>(this)->DoDraw( pDevice, Point(0,0), aTmpSize, JobSetup(), nAspect );
 
-    xFile->Stop();
+    if(pFile)
+        pFile->Stop();
 
-    return xFile;
+    return true;
 }
 
 
diff --git a/sfx2/source/doc/sfxbasemodel.cxx b/sfx2/source/doc/sfxbasemodel.cxx
index d1390a74bc6a..dcd5fd6a6aaa 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -2042,7 +2042,7 @@ Any SAL_CALL SfxBaseModel::getTransferData( const datatransfer::DataFlavor& aFla
                 throw datatransfer::UnsupportedFlavorException();
 
             std::shared_ptr<GDIMetaFile> xMetaFile =
-                m_pData->m_pObjectShell->CreatePreviewMetaFile_Impl( true );
+                m_pData->m_pObjectShell->GetPreviewMetaFile( true );
 
             if (xMetaFile)
             {


More information about the Libreoffice-commits mailing list