summaryrefslogtreecommitdiff
path: root/emfio
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2020-09-18 17:52:41 +0200
committerMiklos Vajna <vmiklos@collabora.com>2020-09-18 21:24:38 +0200
commit01024ee24c6e89044c68051f6fd5f1264905e90c (patch)
tree4fbfc06d643f72cab1cf5525c921565d2fb90c65 /emfio
parentccf35ce98771cac805aafa58a1bcfaba17c59a12 (diff)
[API CHANGE] tdf#136836 emfio: set size hint on inner PDF if used as shape fill
The bugdoc has a shape, its bitmap fill is an EMF, which is actually a PDF. The PDF is has a height of 5cm, but the shape has a height of 14 cm. Inform vcl::RenderPDFBitmaps() about the size of the shape, so the result won't be blurry. This approach makes sure that we don't unconditionally render at higher resolution, i.e. the "load a PDF of 100 pages into Online" use-case won't use more memory than before. API CHANGE, because the EMF reader is only available via UNO, though it's likely that no actual external code would ever invoke it directly. Change-Id: If1d8def0136d408a31a0cc54777a7f26430a0ff3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102996 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'emfio')
-rw-r--r--emfio/CppunitTest_emfio_emf_test.mk15
-rw-r--r--emfio/inc/emfreader.hxx2
-rw-r--r--emfio/qa/cppunit/emf/EmfImportTest.cxx57
-rw-r--r--emfio/qa/cppunit/emf/data/pdf-in-emf.pptxbin0 -> 35443 bytes
-rw-r--r--emfio/source/emfuno/xemfparser.cxx15
-rw-r--r--emfio/source/reader/emfreader.cxx4
6 files changed, 76 insertions, 17 deletions
diff --git a/emfio/CppunitTest_emfio_emf_test.mk b/emfio/CppunitTest_emfio_emf_test.mk
index 123e4b3549bd..5b32187b7ea8 100644
--- a/emfio/CppunitTest_emfio_emf_test.mk
+++ b/emfio/CppunitTest_emfio_emf_test.mk
@@ -38,20 +38,7 @@ $(eval $(call gb_CppunitTest_use_libraries,emfio_emf,\
$(eval $(call gb_CppunitTest_use_ure,emfio_emf))
$(eval $(call gb_CppunitTest_use_vcl,emfio_emf))
-$(eval $(call gb_CppunitTest_use_components,emfio_emf,\
- configmgr/source/configmgr \
- dtrans/util/mcnttype \
- emfio/emfio \
- framework/util/fwk \
- i18npool/util/i18npool \
- package/source/xstor/xstor \
- package/util/package2 \
- toolkit/util/tk \
- sfx2/util/sfx \
- ucb/source/core/ucb1 \
- ucb/source/ucp/file/ucpfile1 \
- unotools/util/utl \
-))
+$(eval $(call gb_CppunitTest_use_rdb,emfio_emf,services))
$(eval $(call gb_CppunitTest_use_configuration,emfio_emf))
diff --git a/emfio/inc/emfreader.hxx b/emfio/inc/emfreader.hxx
index ec2c5273f650..39d576b64aed 100644
--- a/emfio/inc/emfreader.hxx
+++ b/emfio/inc/emfreader.hxx
@@ -34,6 +34,7 @@ namespace emfio
bool mbEMFPlusDualMode : 1;
/// Another format is read already, can ignore actual EMF data.
bool mbReadOtherGraphicFormat = false;
+ basegfx::B2DTuple maSizeHint;
bool ReadHeader();
// reads and converts the rectangle
@@ -47,6 +48,7 @@ namespace emfio
void ReadGDIComment(sal_uInt32 nCommentId);
/// Parses EMR_COMMENT_MULTIFORMATS.
void ReadMultiformatsComment();
+ void SetSizeHint(const basegfx::B2DTuple& rSizeHint) { maSizeHint = rSizeHint; }
private:
template <class T> void ReadAndDrawPolyPolygon(sal_uInt32 nNextPos);
diff --git a/emfio/qa/cppunit/emf/EmfImportTest.cxx b/emfio/qa/cppunit/emf/EmfImportTest.cxx
index ca42b307211b..9d3364693530 100644
--- a/emfio/qa/cppunit/emf/EmfImportTest.cxx
+++ b/emfio/qa/cppunit/emf/EmfImportTest.cxx
@@ -12,6 +12,12 @@
#include <test/bootstrapfixture.hxx>
#include <test/xmltesttools.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
#include <comphelper/seqstream.hxx>
#include <comphelper/sequence.hxx>
@@ -26,14 +32,17 @@
namespace
{
+using namespace css;
using namespace css::uno;
using namespace css::io;
using namespace css::graphic;
using drawinglayer::primitive2d::Primitive2DSequence;
using drawinglayer::primitive2d::Primitive2DContainer;
-class Test : public test::BootstrapFixture, public XmlTestTools
+class Test : public test::BootstrapFixture, public XmlTestTools, public unotest::MacrosTest
{
+ uno::Reference<lang::XComponent> mxComponent;
+
void checkRectPrimitive(Primitive2DSequence const & rPrimitive);
void testWorking();
@@ -41,19 +50,40 @@ class Test : public test::BootstrapFixture, public XmlTestTools
void TestDrawStringTransparent();
void TestDrawLine();
void TestLinearGradient();
+ void TestPdfInEmf();
Primitive2DSequence parseEmf(const OUString& aSource);
public:
+ void setUp() override;
+ void tearDown() override;
+ uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
+
CPPUNIT_TEST_SUITE(Test);
CPPUNIT_TEST(testWorking);
CPPUNIT_TEST(TestDrawString);
CPPUNIT_TEST(TestDrawStringTransparent);
CPPUNIT_TEST(TestDrawLine);
CPPUNIT_TEST(TestLinearGradient);
+ CPPUNIT_TEST(TestPdfInEmf);
CPPUNIT_TEST_SUITE_END();
};
+void Test::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void Test::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ test::BootstrapFixture::tearDown();
+}
+
Primitive2DSequence Test::parseEmf(const OUString& aSource)
{
const Reference<XEmfParser> xEmfParser = EmfTools::create(m_xContext);
@@ -190,6 +220,31 @@ void Test::TestLinearGradient()
assertXPath(pDocument, "/primitive2D/metafile/transform/mask/svglineargradient[2]/polypolygon", "path", "m7615.75822989746 0.216110019646294h7615.75822989746v7610.21611001965h-7615.75822989746z");
}
+void Test::TestPdfInEmf()
+{
+ // Load a PPTX file, which has a shape, with a bitmap fill, which is an EMF, containing a PDF.
+ OUString aURL = m_directories.getURLFromSrc("emfio/qa/cppunit/emf/data/pdf-in-emf.pptx");
+ getComponent() = loadFromDesktop(aURL);
+
+ // Get the EMF.
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<graphic::XGraphic> xGraphic;
+ xShape->getPropertyValue("FillBitmap") >>= xGraphic;
+ Graphic aGraphic(xGraphic);
+
+ // Check the size hint of the EMF, which influences the bitmap generated from the PDF.
+ const std::shared_ptr<VectorGraphicData>& pVectorGraphicData = aGraphic.getVectorGraphicData();
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 14321
+ // - Actual : 0
+ // i.e. there was no size hint, the shape with 14cm height had a bitmap-from-PDF fill, the PDF
+ // height was only 5cm, so it looked blurry.
+ CPPUNIT_ASSERT_EQUAL(14321.0, pVectorGraphicData->getSizeHint().getY());
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
}
diff --git a/emfio/qa/cppunit/emf/data/pdf-in-emf.pptx b/emfio/qa/cppunit/emf/data/pdf-in-emf.pptx
new file mode 100644
index 000000000000..61b2af28c8b3
--- /dev/null
+++ b/emfio/qa/cppunit/emf/data/pdf-in-emf.pptx
Binary files differ
diff --git a/emfio/source/emfuno/xemfparser.cxx b/emfio/source/emfuno/xemfparser.cxx
index 717f2dad7cfb..0c623d7659aa 100644
--- a/emfio/source/emfuno/xemfparser.cxx
+++ b/emfio/source/emfuno/xemfparser.cxx
@@ -32,6 +32,7 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
+#include <sal/log.hxx>
#include <wmfreader.hxx>
#include <emfreader.hxx>
@@ -46,6 +47,7 @@ namespace emfio::emfreader
{
private:
uno::Reference< uno::XComponentContext > context_;
+ basegfx::B2DTuple maSizeHint;
public:
explicit XEmfParser(
@@ -58,6 +60,7 @@ namespace emfio::emfreader
const uno::Reference< ::io::XInputStream >& xEmfStream,
const OUString& aAbsolutePath,
const uno::Sequence< ::beans::PropertyValue >& rProperties) override;
+ void SAL_CALL setSizeHint(const geometry::RealPoint2D& rSize) override;
// XServiceInfo
virtual OUString SAL_CALL getImplementationName() override;
@@ -105,7 +108,9 @@ namespace emfio::emfreader
if (nMetaType == 0x464d4520)
{
// read and get possible failure/error, ReadEnhWMF returns success
- bReadError = !emfio::EmfReader(*pStream, aMtf).ReadEnhWMF();
+ emfio::EmfReader aReader(*pStream, aMtf);
+ aReader.SetSizeHint(maSizeHint);
+ bReadError = !aReader.ReadEnhWMF();
}
else
{
@@ -175,12 +180,18 @@ namespace emfio::emfreader
}
else
{
- OSL_ENSURE(false, "Invalid stream (!)");
+ SAL_WARN("emfio", "Invalid stream (!)");
}
return comphelper::containerToSequence(aRetval);
}
+ void XEmfParser::setSizeHint(const geometry::RealPoint2D& rSize)
+ {
+ maSizeHint.setX(rSize.X);
+ maSizeHint.setY(rSize.Y);
+ }
+
OUString SAL_CALL XEmfParser::getImplementationName()
{
return "emfio::emfreader::XEmfParser";
diff --git a/emfio/source/reader/emfreader.cxx b/emfio/source/reader/emfreader.cxx
index 7bb4d408203a..2c932a440eeb 100644
--- a/emfio/source/reader/emfreader.cxx
+++ b/emfio/source/reader/emfreader.cxx
@@ -503,6 +503,10 @@ namespace emfio
return;
}
+ // aGraphic will be the only output of the EMF parser, so its size hint can be the same as
+ // ours.
+ aGraphic.getVectorGraphicData()->setSizeHint(maSizeHint);
+
maBmpSaveList.emplace_back(new BSaveStruct(aGraphic.GetBitmapEx(), aOutputRect, SRCCOPY));
const std::shared_ptr<VectorGraphicData> pVectorGraphicData
= aGraphic.getVectorGraphicData();