summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-10-09 13:21:34 +0200
committerLuboš Luňák <l.lunak@collabora.com>2020-10-12 15:13:17 +0200
commit59cca1a28df4cdc94450d68cc1e247a8fb5ff6f3 (patch)
tree84d6aebfb103a2fe33b6601d66c6fd4e5fbb6510
parent1e78b576cdbe4d938ef8eeabd9083f62f92416be (diff)
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@collabora.com>
-rw-r--r--include/sfx2/objsh.hxx8
-rw-r--r--sfx2/source/appl/sfxpicklist.cxx5
-rw-r--r--sfx2/source/doc/objcont.cxx83
-rw-r--r--sfx2/source/doc/sfxbasemodel.cxx2
4 files changed, 77 insertions, 21 deletions
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)
{