summaryrefslogtreecommitdiff
path: root/sfx2
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-10-09 13:21:34 +0200
committerAndras Timar <andras.timar@collabora.com>2020-10-13 22:52:26 +0200
commitf43a202ec1d9ed37cc894c31ff3f2ad4c5a1d2ad (patch)
tree91c859b14121fd453b119e0eb13e6df23f8dd8d9 /sfx2
parent68a4433598057e69c30263da94b3d3ca20a1481e (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. Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104114 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com> (cherry picked from commit 59cca1a28df4cdc94450d68cc1e247a8fb5ff6f3) Change-Id: Ib1643eddfc2b75a3d7be60138fb5226352805826 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104156 Tested-by: Andras Timar <andras.timar@collabora.com> Reviewed-by: Andras Timar <andras.timar@collabora.com>
Diffstat (limited to 'sfx2')
-rw-r--r--sfx2/source/appl/sfxpicklist.cxx5
-rw-r--r--sfx2/source/doc/objcont.cxx83
-rw-r--r--sfx2/source/doc/sfxbasemodel.cxx2
3 files changed, 70 insertions, 20 deletions
diff --git a/sfx2/source/appl/sfxpicklist.cxx b/sfx2/source/appl/sfxpicklist.cxx
index 2284c8b16e16..02b9b6a2a217 100644
--- a/sfx2/source/appl/sfxpicklist.cxx
+++ b/sfx2/source/appl/sfxpicklist.cxx
@@ -133,9 +133,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 8837e9fb82a7..b99439e7eb76 100644
--- a/sfx2/source/doc/objcont.cxx
+++ b/sfx2/source/doc/objcont.cxx
@@ -41,6 +41,7 @@
#include <svtools/ehdl.hxx>
#include <tools/datetime.hxx>
#include <tools/diagnose_ex.h>
+#include <tools/helpers.hxx>
#include <rtl/uri.hxx>
#include <math.h>
#include <sal/log.hxx>
@@ -116,11 +117,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::EnableB2dDraw | 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
@@ -128,17 +150,9 @@ SfxObjectShell::CreatePreviewMetaFile_Impl( bool bFullContent ) const
if ( pFrame && pFrame->GetViewShell() &&
pFrame->GetViewShell()->GetPrinter() &&
pFrame->GetViewShell()->GetPrinter()->IsPrinting() )
- return std::shared_ptr<GDIMetaFile>();
-
- std::shared_ptr<GDIMetaFile> xFile(new 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 )
@@ -152,11 +166,47 @@ SfxObjectShell::CreatePreviewMetaFile_Impl( bool bFullContent ) const
aTmpSize = GetFirstPageSize();
}
- xFile->SetPrefSize( aTmpSize );
DBG_ASSERT( aTmpSize.Height() != 0 && aTmpSize.Width() != 0,
"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;
@@ -171,9 +221,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 0f2a44e176e3..a297faad0ec8 100644
--- a/sfx2/source/doc/sfxbasemodel.cxx
+++ b/sfx2/source/doc/sfxbasemodel.cxx
@@ -2035,7 +2035,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)
{