summaryrefslogtreecommitdiffstats
path: root/emfio
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2020-09-17 13:21:52 +0200
committerMiklos Vajna <vmiklos@collabora.com>2020-09-17 17:21:44 +0200
commitd75c5b38911557173c54a78f42ff220ab3918573 (patch)
treeee1d3b2a7c9a280f71a5a6bb65f4ea088555a467 /emfio
parentqt5: Pass QStyleOption by reference instead of pointer (diff)
downloadcore-d75c5b38911557173c54a78f42ff220ab3918573.tar.gz
core-d75c5b38911557173c54a78f42ff220ab3918573.zip
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.hxx4
-rw-r--r--emfio/source/reader/emfreader.cxx86
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);