summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--include/vcl/pdfread.hxx2
-rw-r--r--include/vcl/vectorgraphicdata.hxx10
-rw-r--r--offapi/com/sun/star/graphic/XEmfParser.idl8
-rw-r--r--svx/source/sdr/properties/defaultproperties.cxx16
-rw-r--r--vcl/source/filter/ipdf/pdfread.cxx21
-rw-r--r--vcl/source/gdi/vectorgraphicdata.cxx12
12 files changed, 140 insertions, 22 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();
diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx
index f60ae8ef243f..bffdb104da42 100644
--- a/include/vcl/pdfread.hxx
+++ b/include/vcl/pdfread.hxx
@@ -30,7 +30,7 @@ namespace vcl
/// Fills the rBitmaps vector with rendered pages.
VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps,
size_t nFirstPage = 0, int nPages = 1,
- double fResolutionDPI = 96.);
+ const basegfx::B2DTuple* pSizeHint = nullptr);
/// Imports a PDF stream into rGraphic as VectorGraphicData.
VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic);
diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx
index 3d30c03d683d..0fdc9abbba42 100644
--- a/include/vcl/vectorgraphicdata.hxx
+++ b/include/vcl/vectorgraphicdata.hxx
@@ -74,6 +74,9 @@ private:
// If the vector format has more pages this denotes which page to render
sal_Int32 mnPageIndex;
+ /// Useful for PDF, which is vector-based, but still rendered to a bitmap.
+ basegfx::B2DTuple maSizeHint;
+
// on demand creators
void ensurePdfReplacement();
void ensureReplacement();
@@ -118,6 +121,13 @@ public:
mnPageIndex = nPageIndex;
}
+ void setSizeHint(const basegfx::B2DTuple& rSizeHint)
+ {
+ maSizeHint = rSizeHint;
+ }
+
+ const basegfx::B2DTuple& getSizeHint() const { return maSizeHint; }
+
bool isPrimitiveSequenceCreated() const { return mbSequenceCreated; }
};
diff --git a/offapi/com/sun/star/graphic/XEmfParser.idl b/offapi/com/sun/star/graphic/XEmfParser.idl
index 1c2fd10d7fff..234d70bc1937 100644
--- a/offapi/com/sun/star/graphic/XEmfParser.idl
+++ b/offapi/com/sun/star/graphic/XEmfParser.idl
@@ -20,6 +20,7 @@
#ifndef __com_sun_star_graphic_XEmfParser_idl__
#define __com_sun_star_graphic_XEmfParser_idl__
+#include <com/sun/star/geometry/RealPoint2D.idl>
#include <com/sun/star/uno/XInterface.idl>
#include <com/sun/star/io/XInputStream.idl>
@@ -51,6 +52,13 @@ interface XEmfParser : ::com::sun::star::uno::XInterface
[in] io::XInputStream xEmfStream,
[in] string aAbsolutePath,
[in] ::com::sun::star::beans::PropertyValues Properties);
+
+ /** Sets a size hint on this object.
+
+ @param Size
+ the size in 100/th mm
+ */
+ void setSizeHint([in] com::sun::star::geometry::RealPoint2D Size);
};
}; }; }; };
diff --git a/svx/source/sdr/properties/defaultproperties.cxx b/svx/source/sdr/properties/defaultproperties.cxx
index fb0c4c59369f..e9a9934a9973 100644
--- a/svx/source/sdr/properties/defaultproperties.cxx
+++ b/svx/source/sdr/properties/defaultproperties.cxx
@@ -30,6 +30,7 @@
#include <libxml/xmlwriter.h>
#include <svx/svdmodel.hxx>
#include <svx/svdtrans.hxx>
+#include <svx/xbtmpit.hxx>
namespace sdr::properties
{
@@ -155,6 +156,21 @@ namespace sdr::properties
void DefaultProperties::SetObjectItemSet(const SfxItemSet& rSet)
{
+ if (rSet.HasItem(XATTR_FILLBITMAP))
+ {
+ const XFillBitmapItem* pItem = rSet.GetItem(XATTR_FILLBITMAP);
+ const std::shared_ptr<VectorGraphicData>& pVectorData
+ = pItem->GetGraphicObject().GetGraphic().getVectorGraphicData();
+ if (pVectorData)
+ {
+ // Shape is filled by a vector graphic: tell it our size as a hint.
+ basegfx::B2DTuple aSizeHint;
+ aSizeHint.setX(GetSdrObject().GetSnapRect().getWidth());
+ aSizeHint.setY(GetSdrObject().GetSnapRect().getHeight());
+ pVectorData->setSizeHint(aSizeHint);
+ }
+ }
+
SfxWhichIter aWhichIter(rSet);
sal_uInt16 nWhich(aWhichIter.FirstWhich());
const SfxPoolItem *pPoolItem;
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index d89283e902ac..39c2933be8d5 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -24,6 +24,7 @@
#include <unotools/datetime.hxx>
#include <vcl/filter/PDFiumLibrary.hxx>
+#include <sal/log.hxx>
using namespace com::sun::star;
@@ -147,9 +148,10 @@ VectorGraphicDataArray createVectorGraphicDataArray(SvStream& rStream)
namespace vcl
{
size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps,
- const size_t nFirstPage, int nPages, const double fResolutionDPI)
+ const size_t nFirstPage, int nPages, const basegfx::B2DTuple* pSizeHint)
{
#if HAVE_FEATURE_PDFIUM
+ const double fResolutionDPI = 96;
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
// Load the buffer using pdfium.
@@ -168,9 +170,19 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi
if (!pPdfPage)
break;
+ // Calculate the bitmap size in points.
+ size_t nPageWidthPoints = FPDF_GetPageWidth(pPdfPage);
+ size_t nPageHeightPoints = FPDF_GetPageHeight(pPdfPage);
+ if (pSizeHint && pSizeHint->getX() && pSizeHint->getY())
+ {
+ // Have a size hint, prefer that over the logic size from the PDF.
+ nPageWidthPoints = convertMm100ToTwip(pSizeHint->getX()) / 20;
+ nPageHeightPoints = convertMm100ToTwip(pSizeHint->getY()) / 20;
+ }
+
// Returned unit is points, convert that to pixel.
- const size_t nPageWidth = pointToPixel(FPDF_GetPageWidth(pPdfPage), fResolutionDPI);
- const size_t nPageHeight = pointToPixel(FPDF_GetPageHeight(pPdfPage), fResolutionDPI);
+ const size_t nPageWidth = pointToPixel(nPageWidthPoints, fResolutionDPI);
+ const size_t nPageHeight = pointToPixel(nPageHeightPoints, fResolutionDPI);
FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1);
if (!pPdfBitmap)
break;
@@ -217,7 +229,10 @@ bool ImportPDF(SvStream& rStream, Graphic& rGraphic)
{
VectorGraphicDataArray aPdfDataArray = createVectorGraphicDataArray(rStream);
if (!aPdfDataArray.hasElements())
+ {
+ SAL_WARN("vcl.filter", "ImportPDF: empty PDF data array");
return false;
+ }
auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aPdfDataArray, OUString(),
VectorGraphicDataType::Pdf);
diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx
index bfaa544bc7d4..d0d1e3ca6412 100644
--- a/vcl/source/gdi/vectorgraphicdata.cxx
+++ b/vcl/source/gdi/vectorgraphicdata.cxx
@@ -150,7 +150,9 @@ void VectorGraphicData::ensurePdfReplacement()
sal_Int32 nUsePageIndex = 0;
if (mnPageIndex >= 0)
nUsePageIndex = mnPageIndex;
- vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength(), aBitmaps, nUsePageIndex, 1/*, fResolutionDPI*/);
+ vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(),
+ maVectorGraphicDataArray.getLength(), aBitmaps, nUsePageIndex, 1,
+ &maSizeHint);
if (!aBitmaps.empty())
maReplacement = aBitmaps[0];
}
@@ -212,7 +214,15 @@ void VectorGraphicData::ensureSequenceAndRange()
}
if (myInputStream.is())
+ {
+ // Pass the size hint of the graphic to the EMF parser.
+ geometry::RealPoint2D aSizeHint;
+ aSizeHint.X = maSizeHint.getX();
+ aSizeHint.Y = maSizeHint.getY();
+ xEmfParser->setSizeHint(aSizeHint);
+
maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence));
+ }
break;
}