diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2020-09-17 13:21:52 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2020-09-17 17:21:44 +0200 |
commit | d75c5b38911557173c54a78f42ff220ab3918573 (patch) | |
tree | ee1d3b2a7c9a280f71a5a6bb65f4ea088555a467 /emfio | |
parent | 007e6063931bd87d6ce15deb65b9adc823f74ce0 (diff) |
tdf#136836 emfio: speed up import of EMF import when the orig PDF is available
The PPTX bugdoc has a 17MB EMF file, which has enough instructions to
keep Impress busy for minutes during import.
Take advantage of the detail that this EMF has a
EMR_COMMENT_MULTIFORMATS record that contains the original PDF, which
can be rendered much faster:
- old cost: 122.153 seconds
- new cost: 1.952 seconds (1.6% of baseline)
Change-Id: I38efc1c24e21a7622377b9e1c1938ebee826bae9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102918
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
Diffstat (limited to 'emfio')
-rw-r--r-- | emfio/inc/emfreader.hxx | 4 | ||||
-rw-r--r-- | emfio/source/reader/emfreader.cxx | 86 |
2 files changed, 82 insertions, 8 deletions
diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx index 90d8969ae70c..75a77211ea61 100644 --- a/emfio/inc/emfreader.hxx +++ b/emfio/inc/emfreader.hxx @@ -32,6 +32,8 @@ namespace emfio bool mbRecordPath : 1; bool mbEMFPlus : 1; bool mbEMFPlusDualMode : 1; + /// An other format is read already, can ignore actual EMF data. + bool mbReadOtherGraphicFormat = false; bool ReadHeader(); // reads and converts the rectangle @@ -43,6 +45,8 @@ namespace emfio bool ReadEnhWMF(); void ReadGDIComment(sal_uInt32 nCommentId); + /// Parses EMR_COMMENT_MULTIFORMATS. + void ReadMultiformatsComment(); private: template <class T> void ReadAndDrawPolyPolygon(sal_uInt32 nNextPos); diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx index 8c128d2965c6..7bb4d408203a 100644 --- a/emfio/source/reader/emfreader.cxx +++ b/emfio/source/reader/emfreader.cxx @@ -24,6 +24,8 @@ #include <o3tl/safeint.hxx> #include <tools/stream.hxx> #include <memory> +#include <vcl/graph.hxx> +#include <vcl/pdfread.hxx> #ifdef DBG_UTIL #include <vcl/pngwrite.hxx> @@ -163,6 +165,8 @@ using namespace std; #define EMR_SETLINKEDUFIS 119 #define EMR_SETTEXTJUSTIFICATION 120 +#define PDF_SIGNATURE 0x50444620 // "PDF " + namespace { @@ -381,16 +385,13 @@ namespace emfio { } -#if OSL_DEBUG_LEVEL > 0 const sal_uInt32 EMR_COMMENT_BEGINGROUP = 0x00000002; const sal_uInt32 EMR_COMMENT_ENDGROUP = 0x00000003; const sal_uInt32 EMR_COMMENT_MULTIFORMATS = 0x40000004; const sal_uInt32 EMR_COMMENT_WINDOWS_METAFILE = 0x80000001; -#endif void EmfReader::ReadGDIComment(sal_uInt32 nCommentId) { -#if OSL_DEBUG_LEVEL > 0 sal_uInt32 nPublicCommentIdentifier; mpInputStream->ReadUInt32(nPublicCommentIdentifier); @@ -433,7 +434,7 @@ namespace emfio break; case EMR_COMMENT_MULTIFORMATS: - SAL_WARN("emfio", "\t\tEMR_COMMENT_MULTIFORMATS not implemented"); + ReadMultiformatsComment(); break; case EMR_COMMENT_WINDOWS_METAFILE: @@ -444,9 +445,78 @@ namespace emfio SAL_WARN("emfio", "\t\tEMR_COMMENT_PUBLIC not implemented, id: 0x" << std::hex << nCommentId << std::dec); break; } -#else - (void) nCommentId; -#endif + } + + void EmfReader::ReadMultiformatsComment() + { + tools::Rectangle aOutputRect = EmfReader::ReadRectangle(); + + sal_uInt32 nCountFormats; + mpInputStream->ReadUInt32(nCountFormats); + if (nCountFormats < 1) + { + return; + } + + // Read the first EmrFormat. + sal_uInt32 nSignature; + mpInputStream->ReadUInt32(nSignature); + if (nSignature != PDF_SIGNATURE) + { + return; + } + + sal_uInt32 nVersion; + mpInputStream->ReadUInt32(nVersion); + if (nVersion != 1) + { + return; + } + + sal_uInt32 nSizeData; + mpInputStream->ReadUInt32(nSizeData); + if (!nSizeData || nSizeData > mpInputStream->remainingSize()) + { + return; + } + + sal_uInt32 nOffData; + mpInputStream->ReadUInt32(nOffData); + if (!nOffData) + { + return; + } + + std::vector<char> aPdfData(nSizeData); + mpInputStream->ReadBytes(aPdfData.data(), aPdfData.size()); + if (!mpInputStream->good()) + { + return; + } + + SvMemoryStream aPdfStream; + aPdfStream.WriteBytes(aPdfData.data(), aPdfData.size()); + aPdfStream.Seek(0); + Graphic aGraphic; + if (!vcl::ImportPDF(aPdfStream, aGraphic)) + { + return; + } + + maBmpSaveList.emplace_back(new BSaveStruct(aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY)); + const std::shared_ptr<VectorGraphicData> pVectorGraphicData + = aGraphic.getVectorGraphicData(); + if (!pVectorGraphicData) + { + return; + } + + if (pVectorGraphicData->getVectorGraphicDataType() != VectorGraphicDataType::Pdf) + { + return; + } + + mbReadOtherGraphicFormat = true; } void EmfReader::ReadEMFPlusComment(sal_uInt32 length, bool& bHaveDC) @@ -728,7 +798,7 @@ namespace emfio SAL_INFO("emfio", "EMF_PLUS_DISABLE is " << (bEnableEMFPlus ? "enabled" : "disabled")); - while( bStatus && mnRecordCount-- && mpInputStream->good()) + while (bStatus && mnRecordCount-- && mpInputStream->good() && !mbReadOtherGraphicFormat) { sal_uInt32 nRecType(0), nRecSize(0); mpInputStream->ReadUInt32(nRecType).ReadUInt32(nRecSize); |