filter/Library_pdffilter.mk | 2 filter/source/pdf/pdfdecomposer.cxx | 106 +++++++++++++++++++ filter/source/pdf/pdfdecomposer.hxx | 22 ++++ filter/source/pdf/pdffilter.component | 3 filter/source/pdf/pdfuno.cxx | 7 + include/svx/svdograf.hxx | 2 include/svx/xmlgrhlp.hxx | 1 include/vcl/graph.hxx | 4 include/vcl/pdfread.hxx | 11 -- include/vcl/vectorgraphicdata.hxx | 4 offapi/UnoApi_offapi.mk | 2 offapi/com/sun/star/graphic/PdfTools.idl | 27 ++++ offapi/com/sun/star/graphic/XPdfDecomposer.idl | 39 +++++++ sd/CppunitTest_sd_import_tests.mk | 1 sd/qa/unit/import-tests.cxx | 80 ++++++++++++++ svx/source/svdraw/svdedtv.cxx | 3 svx/source/svdraw/svdedtv2.cxx | 11 -- svx/source/svdraw/svdograf.cxx | 13 -- svx/source/xml/xmlgrhlp.cxx | 26 ---- svx/source/xoutdev/_xoutbmp.cxx | 21 --- sw/source/core/graphic/ndgrf.cxx | 3 vcl/inc/impgraph.hxx | 13 -- vcl/source/filter/ipdf/pdfread.cxx | 136 ++++++++----------------- vcl/source/gdi/graph.cxx | 17 --- vcl/source/gdi/impgraph.cxx | 93 ++--------------- vcl/source/gdi/pdfwriter_impl.cxx | 16 +- vcl/source/gdi/vectorgraphicdata.cxx | 67 +++++++++--- 27 files changed, 422 insertions(+), 308 deletions(-)
New commits: commit d5215e23e9f90792718b4462e5c565e9839e932a Author: Jan Holesovsky <ke...@collabora.com> AuthorDate: Fri Oct 18 11:19:04 2019 +0200 Commit: Tomaž Vajngerl <qui...@gmail.com> CommitDate: Mon Mar 23 17:17:11 2020 +0100 pdfium: Make Insert -> Image... use VectorGraphicData for PDF. In principle, the current Svg/Emf/Wmf and PDF handling is trying to achieve the same thing: Keep the original stream untouched, provide a replacement graphics, and a kind of rendering. To hold the data, the Svg/Emf/Wmf and PDF were using different structures though. This commit consolidatates that, and makes the Insert -> Image... (for PDF) actually using the VectorGraphicData to hold the original stream. This breaks loading the PDF as a document via PDFium - I'll fix it in the next commit(s). Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90561 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> (cherry picked from commit 6ac2d66c78d6c080aabfa46157113684c2f3a3b0) Change-Id: Iac102f32b757390a03438c165e430283851cc10b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/81062 Tested-by: Tomaž Vajngerl <qui...@gmail.com> Reviewed-by: Tomaž Vajngerl <qui...@gmail.com> diff --git a/filter/Library_pdffilter.mk b/filter/Library_pdffilter.mk index 21be2a1cd5ee..306728729895 100644 --- a/filter/Library_pdffilter.mk +++ b/filter/Library_pdffilter.mk @@ -48,10 +48,12 @@ $(eval $(call gb_Library_use_libraries,pdffilter,\ cppuhelper \ cppu \ sal \ + drawinglayer \ )) $(eval $(call gb_Library_add_exception_objects,pdffilter,\ filter/source/pdf/impdialog \ + filter/source/pdf/pdfdecomposer \ filter/source/pdf/pdfdialog \ filter/source/pdf/pdfexport \ filter/source/pdf/pdffilter \ diff --git a/filter/source/pdf/pdfdecomposer.cxx b/filter/source/pdf/pdfdecomposer.cxx new file mode 100644 index 000000000000..c926b1b35a9d --- /dev/null +++ b/filter/source/pdf/pdfdecomposer.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "pdfdecomposer.hxx" + +#include <vector> + +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx> +#include <vcl/bitmapex.hxx> +#include <vcl/pdfread.hxx> +#include <vcl/svapp.hxx> +#include <vcl/outdev.hxx> + +#include <com/sun/star/graphic/XPdfDecomposer.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +using namespace css; + +namespace +{ +/// Class to convert the PDF data into a XPrimitive2D (containing only a bitmap). +class XPdfDecomposer + : public ::cppu::WeakAggImplHelper2<graphic::XPdfDecomposer, lang::XServiceInfo> +{ +public: + explicit XPdfDecomposer(uno::Reference<uno::XComponentContext> const& context); + XPdfDecomposer(const XPdfDecomposer&) = delete; + XPdfDecomposer& operator=(const XPdfDecomposer&) = delete; + + // XPdfDecomposer + uno::Sequence<uno::Reference<graphic::XPrimitive2D>> + SAL_CALL getDecomposition(const uno::Sequence<sal_Int8>& xPdfData) override; + + // XServiceInfo + OUString SAL_CALL getImplementationName() override; + sal_Bool SAL_CALL supportsService(const OUString&) override; + uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; +}; + +XPdfDecomposer::XPdfDecomposer(uno::Reference<uno::XComponentContext> const&) {} + +uno::Sequence<uno::Reference<graphic::XPrimitive2D>> + SAL_CALL XPdfDecomposer::getDecomposition(const uno::Sequence<sal_Int8>& xPdfData) +{ + std::vector<Bitmap> aBitmaps; + vcl::RenderPDFBitmaps(xPdfData.getConstArray(), xPdfData.getLength(), aBitmaps, 0, + 1 /*, fResolutionDPI*/); + BitmapEx aReplacement(aBitmaps[0]); + + // short form for scale and translate transformation + const Size aDPI( + Application::GetDefaultDevice()->LogicToPixel(Size(1, 1), MapMode(MapUnit::MapInch))); + const Size aBitmapSize(aReplacement.GetSizePixel()); + const basegfx::B2DHomMatrix aBitmapTransform(basegfx::utils::createScaleTranslateB2DHomMatrix( + aBitmapSize.getWidth() * aDPI.getWidth(), aBitmapSize.getHeight() * aDPI.getHeight(), 0, + 0)); + + // create primitive + uno::Sequence<uno::Reference<graphic::XPrimitive2D>> aSequence(1); + aSequence[0] = new drawinglayer::primitive2d::BitmapPrimitive2D(aReplacement, aBitmapTransform); + + return aSequence; +} + +OUString SAL_CALL XPdfDecomposer::getImplementationName() +{ + return PDFDecomposer_getImplementationName(); +} + +sal_Bool SAL_CALL XPdfDecomposer::supportsService(const OUString& rServiceName) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence<OUString> SAL_CALL XPdfDecomposer::getSupportedServiceNames() +{ + return PDFDecomposer_getSupportedServiceNames(); +} +} + +OUString PDFDecomposer_getImplementationName() { return "com.sun.star.comp.PDF.PDFDecomposer"; } + +uno::Sequence<OUString> PDFDecomposer_getSupportedServiceNames() +{ + return uno::Sequence<OUString>{ "com.sun.star.graphic.PdfTools" }; +} + +uno::Reference<uno::XInterface> +PDFDecomposer_createInstance(const uno::Reference<lang::XMultiServiceFactory>& rSMgr) +{ + return static_cast<cppu::OWeakObject*>( + new XPdfDecomposer(comphelper::getComponentContext(rSMgr))); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/filter/source/pdf/pdfdecomposer.hxx b/filter/source/pdf/pdfdecomposer.hxx new file mode 100644 index 000000000000..7e1bd3954692 --- /dev/null +++ b/filter/source/pdf/pdfdecomposer.hxx @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_FILTER_SOURCE_PDF_PDFDECOMPOSER_HXX +#define INCLUDED_FILTER_SOURCE_PDF_PDFDECOMPOSER_HXX + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +OUString PDFDecomposer_getImplementationName(); +css::uno::Sequence<OUString> PDFDecomposer_getSupportedServiceNames(); +css::uno::Reference<css::uno::XInterface> +PDFDecomposer_createInstance(const css::uno::Reference<css::lang::XMultiServiceFactory>& rSMgr); + +#endif // INCLUDED_FILTER_SOURCE_PDF_PDFDECOMPOSER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/filter/source/pdf/pdffilter.component b/filter/source/pdf/pdffilter.component index 06cee2e4aa27..bc6d8006be24 100644 --- a/filter/source/pdf/pdffilter.component +++ b/filter/source/pdf/pdffilter.component @@ -28,4 +28,7 @@ <implementation name="com.sun.star.comp.PDF.PDFExportInteractionHandler"> <service name="com.sun.star.filter.pdfexport.PDFExportInteractionHandler"/> </implementation> + <implementation name="com.sun.star.comp.PDF.PDFDecomposer"> + <service name="com.sun.star.graphic.PdfTools"/> + </implementation> </component> diff --git a/filter/source/pdf/pdfuno.cxx b/filter/source/pdf/pdfuno.cxx index 8dad87097afa..01cbfef7c185 100644 --- a/filter/source/pdf/pdfuno.cxx +++ b/filter/source/pdf/pdfuno.cxx @@ -22,6 +22,7 @@ #include <cppuhelper/factory.hxx> #include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include "pdfdecomposer.hxx" #include "pdffilter.hxx" #include "pdfdialog.hxx" #include "pdfinteract.hxx" @@ -63,6 +64,12 @@ extern "C" PDFInteractionHandler_createInstance, PDFInteractionHandler_getSupportedServiceNames() ); } + else if (aImplName == PDFDecomposer_getImplementationName()) + { + xFactory = createSingleFactory(static_cast<XMultiServiceFactory*>(pServiceManager), + OUString::createFromAscii(pImplName), + PDFDecomposer_createInstance, PDFDecomposer_getSupportedServiceNames()); + } if( xFactory.is() ) { diff --git a/include/svx/svdograf.hxx b/include/svx/svdograf.hxx index 4309e65956a7..2ad6bceea246 100644 --- a/include/svx/svdograf.hxx +++ b/include/svx/svdograf.hxx @@ -198,8 +198,6 @@ public: bool isEmbeddedVectorGraphicData() const; GDIMetaFile getMetafileFromEmbeddedVectorGraphicData() const; - bool isEmbeddedPdfData() const; - std::shared_ptr<std::vector<sal_Int8>> const & getEmbeddedPdfData() const; /// Returns the page number of the embedded data (typically to re-render or import it). sal_Int32 getEmbeddedPageNumber() const; diff --git a/include/svx/xmlgrhlp.hxx b/include/svx/xmlgrhlp.hxx index 9acd14c1ee58..59eea65101a9 100644 --- a/include/svx/xmlgrhlp.hxx +++ b/include/svx/xmlgrhlp.hxx @@ -58,7 +58,6 @@ private: std::unordered_map<OUString, css::uno::Reference<css::graphic::XGraphic>> maGraphicObjects; std::unordered_map<Graphic, std::pair<OUString, OUString>> maExportGraphics; - std::unordered_map<void*, std::pair<OUString, OUString>> maExportPdf; SvXMLGraphicHelperMode meCreateMode; OUString maOutputMimeType; diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx index c8bbccd4574f..aff67351e3d9 100644 --- a/include/vcl/graph.hxx +++ b/include/vcl/graph.hxx @@ -227,10 +227,6 @@ public: const VectorGraphicDataPtr& getVectorGraphicData() const; - void setPdfData(const std::shared_ptr<std::vector<sal_Int8>>& rPdfData); - const std::shared_ptr<std::vector<sal_Int8>>& getPdfData() const; - bool hasPdfData() const; - /// Set the page number of the multi-page source this Graphic is rendered from. void setPageNumber(sal_Int32 nPageNumber); /// Get the page number of the multi-page source this Graphic is rendered from. diff --git a/include/vcl/pdfread.hxx b/include/vcl/pdfread.hxx index a088ed2c002b..986c208c25a5 100644 --- a/include/vcl/pdfread.hxx +++ b/include/vcl/pdfread.hxx @@ -37,16 +37,7 @@ VCL_DLLPUBLIC size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vecto const size_t nFirstPage = 0, int nPages = 1, const double fResolutionDPI = 96.); -/// Imports a PDF stream into rGraphic as a GDIMetaFile. -VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex, - std::vector<sal_Int8>& rPdfData, - sal_uInt64 nPos = STREAM_SEEK_TO_BEGIN, - sal_uInt64 nSize = STREAM_SEEK_TO_END, double fResolutionDPI = 96.); - -VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic, double fResolutionDPI = 96.); - -VCL_DLLPUBLIC size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps, - std::vector<sal_Int8>& rPdfData, const double fResolutionDPI = 96.); +VCL_DLLPUBLIC bool ImportPDF(SvStream& rStream, Graphic& rGraphic); /// Import PDF as Graphic images (1 per page), all unloaded. /// Since Graphic is unloaded, we need to return the page size (in pixels) separately. diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx index 159dc7afe286..ad402431181c 100644 --- a/include/vcl/vectorgraphicdata.hxx +++ b/include/vcl/vectorgraphicdata.hxx @@ -45,7 +45,8 @@ enum class VectorGraphicDataType { Svg = 0, Emf = 1, - Wmf = 2 + Wmf = 2, + Pdf = 3 }; class VCL_DLLPUBLIC VectorGraphicData @@ -69,6 +70,7 @@ private: std::unique_ptr<WmfExternal> mpExternalHeader; // on demand creators + void ensurePdfReplacement(); void ensureReplacement(); void ensureSequenceAndRange(); diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index 13a00192bd8c..3048b4e4658e 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -213,6 +213,7 @@ $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/graphic,\ Primitive2DTools \ SvgTools \ EmfTools \ + PdfTools \ )) $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,com/sun/star/inspection,\ DefaultHelpProvider \ @@ -2715,6 +2716,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/graphic,\ XPrimitiveFactory2D \ XSvgParser \ XEmfParser \ + XPdfDecomposer \ )) $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/i18n,\ AmPmValue \ diff --git a/offapi/com/sun/star/graphic/PdfTools.idl b/offapi/com/sun/star/graphic/PdfTools.idl new file mode 100644 index 000000000000..b9f2e562dbf2 --- /dev/null +++ b/offapi/com/sun/star/graphic/PdfTools.idl @@ -0,0 +1,27 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef com_sun_star_graphic_PdfTools_idl +#define com_sun_star_graphic_PdfTools_idl + +#include <com/sun/star/graphic/XPdfDecomposer.idl> + +module com { module sun { module star { module graphic +{ + +/** Service to convert a PDF stream into a bitmap primitive. + */ + +service PdfTools : XPdfDecomposer; + +} ; } ; } ; } ; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/offapi/com/sun/star/graphic/XPdfDecomposer.idl b/offapi/com/sun/star/graphic/XPdfDecomposer.idl new file mode 100644 index 000000000000..85b38c035c8c --- /dev/null +++ b/offapi/com/sun/star/graphic/XPdfDecomposer.idl @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef __com_sun_star_graphic_XPdfDecomposer_idl__ +#define __com_sun_star_graphic_XPdfDecomposer_idl__ + +#include <com/sun/star/uno/XInterface.idl> + +module com { module sun { module star { module graphic { + +interface XPrimitive2D; + +/** XPdfDecomposer interface + + This renders a PDF data into a bitmap and returns it as a primitive. + */ +interface XPdfDecomposer : ::com::sun::star::uno::XInterface +{ + /** Retrieve decomposed list - in this case a bitmap with the rendered PDF. + + @param xPdfData + The PDF data. + + @since LibreOffice 7.0 + */ + sequence<XPrimitive2D> getDecomposition([in] sequence<byte> xPdfData); +}; + +}; }; }; }; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/CppunitTest_sd_import_tests.mk b/sd/CppunitTest_sd_import_tests.mk index 20828e3bf380..c5afc500c2b2 100644 --- a/sd/CppunitTest_sd_import_tests.mk +++ b/sd/CppunitTest_sd_import_tests.mk @@ -79,6 +79,7 @@ $(eval $(call gb_CppunitTest_use_components,sd_import_tests,\ filter/source/config/cache/filterconfig1 \ filter/source/odfflatxml/odfflatxml \ filter/source/svg/svgfilter \ + filter/source/pdf/pdffilter \ filter/source/xmlfilteradaptor/xmlfa \ filter/source/xmlfilterdetect/xmlfd \ filter/source/storagefilterdetect/storagefd \ diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx index 2d58f73a7f73..fef49207d3ae 100644 --- a/sd/qa/unit/import-tests.cxx +++ b/sd/qa/unit/import-tests.cxx @@ -1219,7 +1219,84 @@ void SdImportTest::testBnc862510_7() xDocShRef->DoClose(); } -#if ENABLE_PDFIMPORT && defined(IMPORT_PDF_ELEMENTS) +#if ENABLE_PDFIMPORT +// These tests use the old PDF-importing logic, which imports PDF elements as +// SD elements. This suffered many issues, and therefore wasn't ideal. +// The old PDF importer relied on an open-source project (xpdf) with an +// incompatible license (gpl), which has to be interfaced via an out-of-process +// library wrapper process. The resulting imported document was inaccurate +// and often very slow and with large memory footprint. +// Instead, PDFium offers state-of-the-art PDF importing logic, +// which is well-maintained and renders PDFs into images with high accuracy. +// So, the idea is to import PDFs as images using PDFium, which has a very +// high quality (and is much faster) than importing individual editable elements. +// So that's the "new" way of importing. +// The user then breaks the image to editable elements (which is not perfect, +// but very close to the old way), only if they need editing ability. +// PDFium should overall be better, and where it isn't, we just need to improve it. +// So these tests aren't really useful anymore. They should be modified to do +// import+break and then check the results. But that isn't straight-forward and +// currently await volunteering time to implement. + +#if HAVE_FEATURE_PDFIUM +void SdImportTest::testPDFImportShared() +{ + comphelper::LibreOfficeKit::setActive(); + sd::DrawDocShellRef xDocShRef = loadURL(m_directories.getURLFromSrc("/sd/qa/unit/data/pdf/multipage.pdf"), PDF); + SdDrawDocument *pDoc = xDocShRef->GetDoc(); + CPPUNIT_ASSERT_MESSAGE( "no document", pDoc != nullptr ); + + // This test is to verify that we share the PDF stream linked to each + // Graphic instance in the imported document. + // Since we import PDFs as images, we support attaching the original + // PDF with each image to allow for advanced editing. + // Here we iterate over all Graphic instances embedded in the pages + // and verify that they all point to the same object in memory. + std::vector<Graphic> aGraphics; + + for (int nPageIndex = 0; nPageIndex < pDoc->GetPageCount(); ++nPageIndex) + { + const SdrPage* pPage = GetPage(nPageIndex, xDocShRef); + if (pPage == nullptr) + break; + + for (size_t nObjIndex = 0; nObjIndex < pPage->GetObjCount(); ++nObjIndex) + { + SdrObject* pObject = pPage->GetObj(nObjIndex); + if (pObject == nullptr) + continue; + + SdrGrafObj* pSdrGrafObj = dynamic_cast<SdrGrafObj*>(pObject); + if (pSdrGrafObj == nullptr) + continue; + + const GraphicObject& rGraphicObject = pSdrGrafObj->GetGraphicObject().GetGraphic(); + const Graphic& rGraphic = rGraphicObject.GetGraphic(); + aGraphics.push_back(rGraphic); + } + } + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected more than one page.", size_t(3), aGraphics.size()); + + Graphic aFirstGraphic = aGraphics[0]; + + for (size_t i = 1; i < aGraphics.size(); ++i) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected all PDF streams to be identical.", + aFirstGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray(), + aGraphics[i].getVectorGraphicData()->getVectorGraphicDataArray().getConstArray()); + + CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected all GfxLinks to be identical.", + aFirstGraphic.GetSharedGfxLink().get(), + aGraphics[i].GetSharedGfxLink().get()); + } + + xDocShRef->DoClose(); + comphelper::LibreOfficeKit::setActive(false); +} +#endif + +#if defined(IMPORT_PDF_ELEMENTS) void SdImportTest::testPDFImport() { @@ -1256,6 +1333,7 @@ void SdImportTest::testPDFImportSkipImages() xDocShRef->DoClose(); } +#endif #endif void SdImportTest::testBulletSuffix() diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx index dc84c10bfdc6..b8837ad19f51 100644 --- a/svx/source/svdraw/svdedtv.cxx +++ b/svx/source/svdraw/svdedtv.cxx @@ -610,8 +610,7 @@ void SdrEditView::CheckPossibilities() if (pSdrGrafObj != nullptr) { if ((pSdrGrafObj->HasGDIMetaFile() && !pSdrGrafObj->IsEPS()) || - pSdrGrafObj->isEmbeddedVectorGraphicData() || - pSdrGrafObj->isEmbeddedPdfData()) + pSdrGrafObj->isEmbeddedVectorGraphicData()) { m_bImportMtfPossible = true; } diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx index 4c9dc54612b8..d6ef069e9564 100644 --- a/svx/source/svdraw/svdedtv2.cxx +++ b/svx/source/svdraw/svdedtv2.cxx @@ -2053,17 +2053,6 @@ void SdrEditView::DoImportMarkedMtf(SvdProgressInfo *pProgrInfo) nInsAnz = aFilter.DoImport(aMetaFile, *pOL, nInsPos, pProgrInfo); } } - else if (pGraf->isEmbeddedPdfData()) - { -#if HAVE_FEATURE_PDFIUM - aLogicRect = pGraf->GetLogicRect(); - ImpSdrPdfImport aFilter(*mpModel, pObj->GetLayer(), aLogicRect, pGraf->getEmbeddedPdfData()); - if (pGraf->getEmbeddedPageNumber() < aFilter.GetPageCount()) - { - nInsAnz = aFilter.DoImport(*pOL, nInsPos, pGraf->getEmbeddedPageNumber(), pProgrInfo); - } -#endif // HAVE_FEATURE_PDFIUM - } } SdrOle2Obj* pOle2 = dynamic_cast<SdrOle2Obj*>(pObj); diff --git a/svx/source/svdraw/svdograf.cxx b/svx/source/svdraw/svdograf.cxx index ba87156b3769..155ea15252b0 100644 --- a/svx/source/svdraw/svdograf.cxx +++ b/svx/source/svdraw/svdograf.cxx @@ -295,8 +295,7 @@ const GraphicObject* SdrGrafObj::GetReplacementGraphicObject() const { const_cast< SdrGrafObj* >(this)->mpReplacementGraphicObject.reset(new GraphicObject(rVectorGraphicDataPtr->getReplacement())); } - else if (mpGraphicObject->GetGraphic().hasPdfData() || - mpGraphicObject->GetGraphic().GetType() == GraphicType::GdiMetafile) + else if (mpGraphicObject->GetGraphic().GetType() == GraphicType::GdiMetafile) { // Replacement graphic for PDF and metafiles is just the bitmap. const_cast<SdrGrafObj*>(this)->mpReplacementGraphicObject.reset(new GraphicObject(mpGraphicObject->GetGraphic().GetBitmapEx())); @@ -889,16 +888,6 @@ GDIMetaFile SdrGrafObj::GetMetaFile(GraphicType &rGraphicType) const return GDIMetaFile(); } -bool SdrGrafObj::isEmbeddedPdfData() const -{ - return mpGraphicObject->GetGraphic().hasPdfData(); -} - -std::shared_ptr<std::vector<sal_Int8>> const & SdrGrafObj::getEmbeddedPdfData() const -{ - return mpGraphicObject->GetGraphic().getPdfData(); -} - sal_Int32 SdrGrafObj::getEmbeddedPageNumber() const { return mpGraphicObject->GetGraphic().getPageNumber(); diff --git a/svx/source/xml/xmlgrhlp.cxx b/svx/source/xml/xmlgrhlp.cxx index b84a268f66bd..ad317872a36e 100644 --- a/svx/source/xml/xmlgrhlp.cxx +++ b/svx/source/xml/xmlgrhlp.cxx @@ -759,29 +759,7 @@ OUString SvXMLGraphicHelper::implSaveGraphic(css::uno::Reference<css::graphic::X std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(aStream.xStream)); if (bUseGfxLink && aGfxLink.GetDataSize() && aGfxLink.GetData()) { - const std::shared_ptr<std::vector<sal_Int8>>& rPdfData = aGraphic.getPdfData(); - if (rPdfData && !rPdfData->empty()) - { - // See if we have this PDF already, and avoid duplicate storage. - auto aIt = maExportPdf.find(rPdfData.get()); - if (aIt != maExportPdf.end()) - { - auto const& aURLAndMimePair = aIt->second; - rOutSavedMimeType = aURLAndMimePair.second; - return aURLAndMimePair.first; - } - - // The graphic has PDF data attached to it, use that. - // vcl::ImportPDF() possibly downgraded the PDF data from a - // higher PDF version, while aGfxLink still contains the - // original data provided by the user. - pStream->WriteBytes(rPdfData->data(), rPdfData->size()); - } - else - { - pStream->WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize()); - } - + pStream->WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize()); rOutSavedMimeType = aMimeType; bSuccess = (pStream->GetError() == ERRCODE_NONE); } @@ -848,8 +826,6 @@ OUString SvXMLGraphicHelper::implSaveGraphic(css::uno::Reference<css::graphic::X // put into cache maExportGraphics[aGraphic] = std::make_pair(aStoragePath, rOutSavedMimeType); - if (aGraphic.hasPdfData()) - maExportPdf[aGraphic.getPdfData().get()] = std::make_pair(aStoragePath, rOutSavedMimeType); return aStoragePath; } diff --git a/svx/source/xoutdev/_xoutbmp.cxx b/svx/source/xoutdev/_xoutbmp.cxx index 83f42f4df95d..d4395f4f8639 100644 --- a/svx/source/xoutdev/_xoutbmp.cxx +++ b/svx/source/xoutdev/_xoutbmp.cxx @@ -149,8 +149,9 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName, const bool bIsSvg(rFilterName.equalsIgnoreAsciiCase("svg") && VectorGraphicDataType::Svg == aVectorGraphicDataPtr->getVectorGraphicDataType()); const bool bIsWmf(rFilterName.equalsIgnoreAsciiCase("wmf") && VectorGraphicDataType::Wmf == aVectorGraphicDataPtr->getVectorGraphicDataType()); const bool bIsEmf(rFilterName.equalsIgnoreAsciiCase("emf") && VectorGraphicDataType::Emf == aVectorGraphicDataPtr->getVectorGraphicDataType()); + const bool bIsPdf(rFilterName.equalsIgnoreAsciiCase("pdf") && VectorGraphicDataType::Pdf == aVectorGraphicDataPtr->getVectorGraphicDataType()); - if (bIsSvg || bIsWmf || bIsEmf) + if (bIsSvg || bIsWmf || bIsEmf || bIsPdf) { if (!(nFlags & XOutFlags::DontAddExtension)) { @@ -174,24 +175,6 @@ ErrCode XOutBitmap::WriteGraphic( const Graphic& rGraphic, OUString& rFileName, } } - // Write PDF data in original form if possible. - if (rGraphic.hasPdfData() && rFilterName.equalsIgnoreAsciiCase("pdf")) - { - if (!(nFlags & XOutFlags::DontAddExtension)) - aURL.setExtension(rFilterName); - - rFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); - SfxMedium aMedium(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE), StreamMode::WRITE|StreamMode::SHARE_DENYNONE|StreamMode::TRUNC); - if (SvStream* pOutStream = aMedium.GetOutStream()) - { - const std::shared_ptr<std::vector<sal_Int8>>& rPdfData = rGraphic.getPdfData(); - pOutStream->WriteBytes(rPdfData->data(), rPdfData->size()); - aMedium.Commit(); - if (!aMedium.GetError()) - nErr = ERRCODE_NONE; - } - } - if( ERRCODE_NONE != nErr ) { if( ( nFlags & XOutFlags::UseNativeIfPossible ) && diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx index 867e533533e3..e8c237f10fb0 100644 --- a/sw/source/core/graphic/ndgrf.cxx +++ b/sw/source/core/graphic/ndgrf.cxx @@ -387,8 +387,7 @@ const GraphicObject* SwGrfNode::GetReplacementGrfObj() const { const_cast< SwGrfNode* >(this)->mpReplacementGraphic.reset( new GraphicObject(rVectorGraphicDataPtr->getReplacement()) ); } - else if (GetGrfObj().GetGraphic().hasPdfData() || - GetGrfObj().GetGraphic().GetType() == GraphicType::GdiMetafile) + else if (GetGrfObj().GetGraphic().GetType() == GraphicType::GdiMetafile) { // Replacement graphic for PDF and metafiles is just the bitmap. const_cast<SwGrfNode*>(this)->mpReplacementGraphic.reset( new GraphicObject(GetGrfObj().GetGraphic().GetBitmapEx()) ); diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index 10f144f4fc0c..6ced13bc71f4 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -86,10 +86,6 @@ private: // cache checksum computation mutable BitmapChecksum mnChecksum = 0; - /// The PDF stream from which this Graphic is rendered, - /// as converted (version downgraded) from the original, - /// which should be in GfxLink. - std::shared_ptr<std::vector<sal_Int8>> mpPdfData; std::unique_ptr<GraphicID> mpGraphicID; GraphicExternalLink maGraphicExternalLink; @@ -139,11 +135,6 @@ private: return mpGraphicID->getIDString(); } - bool hasPdfData() const - { - return mpPdfData && !mpPdfData->empty(); - } - void ImplCreateSwapInfo(); void ImplClearGraphics(); void ImplClear(); @@ -225,10 +216,6 @@ private: const VectorGraphicDataPtr& getVectorGraphicData() const; - const std::shared_ptr<std::vector<sal_Int8>>& getPdfData() const; - - void setPdfData(const std::shared_ptr<std::vector<sal_Int8>>& rPdfData); - bool ensureAvailable () const; bool loadPrepared(); diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 80557c1091e2..1ad0786b8a37 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -48,20 +48,6 @@ inline double pointToPixel(const double fPoint, const double fResolutionDPI) return fPoint * fResolutionDPI / 72.; } -/// Does PDF to bitmap conversion using pdfium. -size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, sal_uInt64 nPos, - sal_uInt64 nSize, const size_t nFirstPage = 0, int nPages = 1, - const double fResolutionDPI = 96.) -{ - // Read input into a buffer. - SvMemoryStream aInBuffer; - rStream.Seek(nPos); - aInBuffer.WriteStream(rStream, nSize); - - return vcl::RenderPDFBitmaps(aInBuffer.GetData(), aInBuffer.GetSize(), rBitmaps, nFirstPage, - nPages, fResolutionDPI); -} - /// Decide if PDF data is old enough to be compatible. bool isCompatible(SvStream& rInStream, sal_uInt64 nPos, sal_uInt64 nSize) { @@ -132,12 +118,6 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 n return rOutStream.good(); } #else -size_t generatePreview(SvStream&, std::vector<Bitmap>&, sal_uInt64, sal_uInt64, size_t, int, - const double) -{ - return 0; -} - bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 nPos, sal_uInt64 nSize) { @@ -146,8 +126,28 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, sal_uInt64 n return rOutStream.good(); } #endif // HAVE_FEATURE_PDFIUM + +VectorGraphicDataArray createVectorGraphicDataArray(SvStream& rStream) +{ + // Save the original PDF stream for later use. + SvMemoryStream aMemoryStream; + if (!getCompatibleStream(rStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END)) + return VectorGraphicDataArray(); + + const sal_uInt32 nStreamLength = aMemoryStream.TellEnd(); + + VectorGraphicDataArray aPdfData(nStreamLength); + + aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); + aMemoryStream.ReadBytes(aPdfData.begin(), nStreamLength); + if (aMemoryStream.GetError()) + return VectorGraphicDataArray(); + + return aPdfData; } +} // end anonymous namespace + namespace vcl { size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBitmaps, @@ -223,63 +223,24 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi #endif // HAVE_FEATURE_PDFIUM } -bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, size_t nPageIndex, - std::vector<sal_Int8>& rPdfData, sal_uInt64 nPos, sal_uInt64 nSize, - const double fResolutionDPI) +bool ImportPDF(SvStream& rStream, Graphic& rGraphic) { - // Get the preview of the first page. - std::vector<Bitmap> aBitmaps; - if (generatePreview(rStream, aBitmaps, nPos, nSize, nPageIndex, 1, fResolutionDPI) != 1 - || aBitmaps.empty()) - return false; - - rBitmap = aBitmaps[0]; - // Save the original PDF stream for later use. SvMemoryStream aMemoryStream; - if (!getCompatibleStream(rStream, aMemoryStream, nPos, nSize)) + if (!getCompatibleStream(rStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END)) return false; - - rPdfData = std::vector<sal_Int8>(aMemoryStream.TellEnd()); + const sal_uInt32 nStreamLength = aMemoryStream.TellEnd(); + VectorGraphicDataArray aPdfData(nStreamLength); aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); - aMemoryStream.ReadBytes(rPdfData.data(), rPdfData.size()); - - return true; -} - -bool ImportPDF(SvStream& rStream, Graphic& rGraphic, const double fResolutionDPI) -{ - std::vector<sal_Int8> aPdfData; - Bitmap aBitmap; - const bool bRet = ImportPDF(rStream, aBitmap, 0, aPdfData, STREAM_SEEK_TO_BEGIN, - STREAM_SEEK_TO_END, fResolutionDPI); - rGraphic = aBitmap; - rGraphic.setPdfData(std::make_shared<std::vector<sal_Int8>>(aPdfData)); - rGraphic.setPageNumber(0); // We currently import only the first page. - return bRet; -} - -size_t ImportPDF(const OUString& rURL, std::vector<Bitmap>& rBitmaps, - std::vector<sal_Int8>& rPdfData, const double fResolutionDPI) -{ - std::unique_ptr<SvStream> xStream( - ::utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ | StreamMode::SHARE_DENYNONE)); - - if (generatePreview(*xStream, rBitmaps, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END, 0, -1, - fResolutionDPI) - == 0) - return 0; - - // Save the original PDF stream for later use. - SvMemoryStream aMemoryStream; - if (!getCompatibleStream(*xStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END)) - return 0; + aMemoryStream.ReadBytes(aPdfData.begin(), nStreamLength); + if (aMemoryStream.GetError()) + return false; - rPdfData = std::vector<sal_Int8>(aMemoryStream.TellEnd()); - aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); - aMemoryStream.ReadBytes(rPdfData.data(), rPdfData.size()); + auto aVectorGraphicDataPtr + = std::make_shared<VectorGraphicData>(aPdfData, OUString(), VectorGraphicDataType::Pdf); - return rBitmaps.size(); + rGraphic = Graphic(aVectorGraphicDataPtr); + return true; } size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Size>>& rGraphics, @@ -290,22 +251,18 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si ::utl::UcbStreamHelper::CreateStream(rURL, StreamMode::READ | StreamMode::SHARE_DENYNONE)); // Save the original PDF stream for later use. - SvMemoryStream aMemoryStream; - if (!getCompatibleStream(*xStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END)) + VectorGraphicDataArray aPdfDataArray = createVectorGraphicDataArray(*xStream); + if (!aPdfDataArray.hasElements()) return 0; - // Copy into PdfData - aMemoryStream.Seek(STREAM_SEEK_TO_END); - auto pPdfData = std::make_shared<std::vector<sal_Int8>>(aMemoryStream.Tell()); - aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN); - aMemoryStream.ReadBytes(pPdfData->data(), pPdfData->size()); - // Prepare the link with the PDF stream. - const size_t nGraphicContentSize = pPdfData->size(); + const size_t nGraphicContentSize = aPdfDataArray.getLength(); std::unique_ptr<sal_uInt8[]> pGraphicContent(new sal_uInt8[nGraphicContentSize]); - memcpy(pGraphicContent.get(), pPdfData->data(), nGraphicContentSize); - std::shared_ptr<GfxLink> pGfxLink(std::make_shared<GfxLink>( - std::move(pGraphicContent), nGraphicContentSize, GfxLinkType::NativePdf)); + + std::copy(aPdfDataArray.begin(), aPdfDataArray.end(), pGraphicContent.get()); + + auto pGfxLink = std::make_shared<GfxLink>(std::move(pGraphicContent), nGraphicContentSize, + GfxLinkType::NativePdf); FPDF_LIBRARY_CONFIG aConfig; aConfig.version = 2; @@ -316,7 +273,7 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si // Load the buffer using pdfium. FPDF_DOCUMENT pPdfDocument - = FPDF_LoadMemDocument(pPdfData->data(), pPdfData->size(), /*password=*/nullptr); + = FPDF_LoadMemDocument(pGfxLink->GetData(), pGfxLink->GetDataSize(), /*password=*/nullptr); if (!pPdfDocument) return 0; @@ -324,10 +281,7 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si if (nPageCount <= 0) return 0; - // dummy Bitmap - Bitmap aBitmap(Size(1, 1), 24); - - for (size_t nPageIndex = 0; nPageIndex < static_cast<size_t>(nPageCount); ++nPageIndex) + for (int nPageIndex = 0; nPageIndex < nPageCount; ++nPageIndex) { double fPageWidth = 0; double fPageHeight = 0; @@ -338,11 +292,13 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si const size_t nPageWidth = pointToPixel(fPageWidth, fResolutionDPI); const size_t nPageHeight = pointToPixel(fPageHeight, fResolutionDPI); - // Create the Graphic with a dummy Bitmap and link the original PDF stream. + auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>( + aPdfDataArray, OUString(), VectorGraphicDataType::Pdf); + + // Create the Graphic with the VectorGraphicDataPtr and link the original PDF stream. // We swap out this Graphic as soon as possible, and a later swap in // actually renders the correct Bitmap on demand. - Graphic aGraphic(aBitmap); - aGraphic.setPdfData(pPdfData); + Graphic aGraphic(aVectorGraphicDataPtr); aGraphic.setPageNumber(nPageIndex); aGraphic.SetGfxLink(pGfxLink); diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx index 18f7fd385dd2..d097b9c3a870 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -570,23 +570,6 @@ const VectorGraphicDataPtr& Graphic::getVectorGraphicData() const return mxImpGraphic->getVectorGraphicData(); } -void Graphic::setPdfData(const std::shared_ptr<std::vector<sal_Int8>>& rPdfData) -{ - ImplTestRefCount(); - mxImpGraphic->setPdfData(rPdfData); -} - -const std::shared_ptr<std::vector<sal_Int8>>& Graphic::getPdfData() const -{ - return mxImpGraphic->getPdfData(); -} - -bool Graphic::hasPdfData() const -{ - std::shared_ptr<std::vector<sal_Int8>> pPdfData = getPdfData(); - return pPdfData && !pPdfData->empty(); -} - void Graphic::setPageNumber(sal_Int32 nPageNumber) { mxImpGraphic->mnPageNumber = nPageNumber; diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx index c1b58b69acba..49eaa2589801 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -59,8 +59,6 @@ #define GRAPHIC_FORMAT_50 COMPAT_FORMAT( 'G', 'R', 'F', '5' ) #define NATIVE_FORMAT_50 COMPAT_FORMAT( 'N', 'A', 'T', '5' ) -const sal_uInt32 nPdfMagic((sal_uInt32('p') << 24) | (sal_uInt32('d') << 16) | (sal_uInt32('f') << 8) | sal_uInt32('0')); - using namespace com::sun::star; struct ImpSwapFile @@ -124,16 +122,6 @@ GraphicID::GraphicID(ImpGraphic const & rGraphic) mnID3 = basegfx::fround(rRange.getHeight()); mnID4 = vcl_get_checksum(0, rVectorGraphicDataPtr->getVectorGraphicDataArray().getConstArray(), rVectorGraphicDataPtr->getVectorGraphicDataArrayLength()); } - else if (rGraphic.hasPdfData()) - { - std::shared_ptr<std::vector<sal_Int8>> pPdfData = rGraphic.getPdfData(); - const BitmapEx& rBmpEx = rGraphic.ImplGetBitmapExRef(); - - mnID1 |= (rGraphic.mnPageNumber & 0x0fffffff); - mnID2 = rBmpEx.GetSizePixel().Width(); - mnID3 = rBmpEx.GetSizePixel().Height(); - mnID4 = vcl_get_checksum(0, pPdfData->data(), pPdfData->size()); - } else if (rGraphic.ImplIsAnimated()) { const Animation aAnimation(rGraphic.ImplGetAnimation()); @@ -210,7 +198,6 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic) , mbSwapOut(rImpGraphic.mbSwapOut) , mbDummyContext(rImpGraphic.mbDummyContext) , maVectorGraphicData(rImpGraphic.maVectorGraphicData) - , mpPdfData(rImpGraphic.mpPdfData) , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) , maLastUsed (std::chrono::high_resolution_clock::now()) , mbPrepared (rImpGraphic.mbPrepared) @@ -236,7 +223,6 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) , mbSwapOut(rImpGraphic.mbSwapOut) , mbDummyContext(rImpGraphic.mbDummyContext) , maVectorGraphicData(std::move(rImpGraphic.maVectorGraphicData)) - , mpPdfData(std::move(rImpGraphic.mpPdfData)) , maGraphicExternalLink(rImpGraphic.maGraphicExternalLink) , maLastUsed (std::chrono::high_resolution_clock::now()) , mbPrepared (rImpGraphic.mbPrepared) @@ -359,7 +345,6 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic ) mpGfxLink = rImpGraphic.mpGfxLink; maVectorGraphicData = rImpGraphic.maVectorGraphicData; - mpPdfData = rImpGraphic.mpPdfData; maLastUsed = std::chrono::high_resolution_clock::now(); vcl::graphic::Manager::get().changeExisting(this, aOldSizeBytes); @@ -385,7 +370,6 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic) mpSwapFile = std::move(rImpGraphic.mpSwapFile); mpGfxLink = std::move(rImpGraphic.mpGfxLink); maVectorGraphicData = std::move(rImpGraphic.maVectorGraphicData); - mpPdfData = std::move(rImpGraphic.mpPdfData); maGraphicExternalLink = rImpGraphic.maGraphicExternalLink; mbPrepared = rImpGraphic.mbPrepared; @@ -440,10 +424,6 @@ bool ImpGraphic::operator==( const ImpGraphic& rImpGraphic ) const bRet = (*maVectorGraphicData) == (*rImpGraphic.maVectorGraphicData); } } - else if (mpPdfData && !mpPdfData->empty()) - { - bRet = (rImpGraphic.mpPdfData && *mpPdfData == *rImpGraphic.mpPdfData); - } else if( mpAnimation ) { if( rImpGraphic.mpAnimation && ( *rImpGraphic.mpAnimation == *mpAnimation ) ) @@ -471,20 +451,6 @@ const VectorGraphicDataPtr& ImpGraphic::getVectorGraphicData() const return maVectorGraphicData; } -void ImpGraphic::setPdfData(const std::shared_ptr<std::vector<sal_Int8>>& rPdfData) -{ - ensureAvailable(); - - mpPdfData = rPdfData; -} - -const std::shared_ptr<std::vector<sal_Int8>>& ImpGraphic::getPdfData() const -{ - ensureAvailable(); - - return mpPdfData; -} - void ImpGraphic::ImplCreateSwapInfo() { if (!ImplIsSwapOut()) @@ -506,7 +472,6 @@ void ImpGraphic::ImplClearGraphics() mpAnimation.reset(); mpGfxLink.reset(); maVectorGraphicData.reset(); - mpPdfData.reset(); } ImpSwapFile::~ImpSwapFile() @@ -1698,12 +1663,8 @@ BitmapChecksum ImpGraphic::ImplGetChecksum() const case GraphicType::Bitmap: { - if (maVectorGraphicData) + if(maVectorGraphicData) nRet = maVectorGraphicData->GetChecksum(); - else if (mpPdfData && !mpPdfData->empty()) - // Include the PDF data in the checksum, so a metafile with - // and without PDF data is considered to be different. - nRet = vcl_get_checksum(nRet, mpPdfData->data(), mpPdfData->size()); else if( mpAnimation ) nRet = mpAnimation->GetChecksum(); else @@ -1857,12 +1818,13 @@ void ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic ) const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); const sal_uInt32 nWmfMagic((sal_uInt32('w') << 24) | (sal_uInt32('m') << 16) | (sal_uInt32('f') << 8) | sal_uInt32('0')); const sal_uInt32 nEmfMagic((sal_uInt32('e') << 24) | (sal_uInt32('m') << 16) | (sal_uInt32('f') << 8) | sal_uInt32('0')); + const sal_uInt32 nPdfMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); sal_uInt32 nMagic; rIStm.Seek(nStmPos1); rIStm.ResetError(); rIStm.ReadUInt32( nMagic ); - if (nSvgMagic == nMagic || nWmfMagic == nMagic || nEmfMagic == nMagic) + if (nSvgMagic == nMagic || nWmfMagic == nMagic || nEmfMagic == nMagic || nPdfMagic == nMagic) { sal_uInt32 nVectorGraphicDataArrayLength(0); rIStm.ReadUInt32(nVectorGraphicDataArrayLength); @@ -1886,35 +1848,16 @@ void ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic ) { aDataType = VectorGraphicDataType::Emf; } + else if (nPdfMagic == nMagic) + { + aDataType = VectorGraphicDataType::Pdf; + } VectorGraphicDataPtr aVectorGraphicDataPtr(new VectorGraphicData(aNewData, aPath, aDataType)); rImpGraphic = aVectorGraphicDataPtr; } } } - else if (nMagic == nPdfMagic) - { - // Stream in PDF data. - BitmapChecksum nPdfId = 0; - rIStm.ReadUInt64(nPdfId); - - rImpGraphic.mnPageNumber = 0; - rIStm.ReadInt32(rImpGraphic.mnPageNumber); - - auto it = sPdfDataCache.find(nPdfId); - assert(it != sPdfDataCache.end()); - - rImpGraphic.mpPdfData = it->second; - - Bitmap aBitmap; - rImpGraphic.maEx = aBitmap; - - std::vector<Bitmap> aBitmaps; - if (vcl::RenderPDFBitmaps(rImpGraphic.mpPdfData->data(), rImpGraphic.mpPdfData->size(), aBitmaps, rImpGraphic.mnPageNumber, 1) == 1) - rImpGraphic.maEx = aBitmaps[0]; - - rImpGraphic.meType = GraphicType::Bitmap; - } else { rIStm.SetError(nOrigError); @@ -1942,8 +1885,7 @@ void WriteImpGraphic(SvStream& rOStm, const ImpGraphic& rImpGraphic) if( ( rOStm.GetVersion() >= SOFFICE_FILEFORMAT_50 ) && ( rOStm.GetCompressMode() & SvStreamCompressFlags::NATIVE ) && - rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative() && - !rImpGraphic.hasPdfData()) + rImpGraphic.mpGfxLink && rImpGraphic.mpGfxLink->IsNative()) { // native format rOStm.WriteUInt32( NATIVE_FORMAT_50 ); @@ -1990,12 +1932,18 @@ void WriteImpGraphic(SvStream& rOStm, const ImpGraphic& rImpGraphic) rOStm.WriteUInt32(nEmfMagic); break; } - default: // case VectorGraphicDataType::Svg: + case VectorGraphicDataType::Svg: { const sal_uInt32 nSvgMagic((sal_uInt32('s') << 24) | (sal_uInt32('v') << 16) | (sal_uInt32('g') << 8) | sal_uInt32('0')); rOStm.WriteUInt32(nSvgMagic); break; } + case VectorGraphicDataType::Pdf: + { + const sal_uInt32 nSvgMagic((sal_uInt32('p') << 24) | (sal_uInt32('d') << 16) | (sal_uInt32('f') << 8) | sal_uInt32('0')); + rOStm.WriteUInt32(nSvgMagic); + break; + } } rOStm.WriteUInt32( rImpGraphic.getVectorGraphicData()->getVectorGraphicDataArrayLength() ); @@ -2004,17 +1952,6 @@ void WriteImpGraphic(SvStream& rOStm, const ImpGraphic& rImpGraphic) rOStm.WriteUniOrByteString(rImpGraphic.getVectorGraphicData()->getPath(), rOStm.GetStreamCharSet()); } - else if (rImpGraphic.hasPdfData()) - { - BitmapChecksum nPdfId = vcl_get_checksum(0, rImpGraphic.mpPdfData->data(), rImpGraphic.mpPdfData->size()); - if (sPdfDataCache.find(nPdfId) == sPdfDataCache.end()) - sPdfDataCache.emplace(nPdfId, rImpGraphic.mpPdfData); - - // Stream out PDF data. - rOStm.WriteUInt32(nPdfMagic); - rOStm.WriteUInt64(nPdfId); - rOStm.WriteInt32(rImpGraphic.mnPageNumber); - } else if( rImpGraphic.ImplIsAnimated()) { WriteAnimation( rOStm, *rImpGraphic.mpAnimation ); diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 39a0e2004d3f..4557100b957e 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -9682,20 +9682,24 @@ void PDFWriterImpl::createEmbeddedFile(const Graphic& rGraphic, ReferenceXObject // no pdf data. rEmit.m_nBitmapObject = nBitmapObject; - if (!rGraphic.hasPdfData()) + if (!rGraphic.getVectorGraphicData().get() || rGraphic.getVectorGraphicData()->getVectorGraphicDataType() != VectorGraphicDataType::Pdf) return; + sal_uInt32 nLength = rGraphic.getVectorGraphicData()->getVectorGraphicDataArrayLength(); + auto const & rArray = rGraphic.getVectorGraphicData()->getVectorGraphicDataArray(); + + std::vector<sal_Int8> aPDFData(rArray.getConstArray(), rArray.getConstArray() + nLength); + if (m_aContext.UseReferenceXObject) { // Store the original PDF data as an embedded file. m_aEmbeddedFiles.emplace_back(); m_aEmbeddedFiles.back().m_nObject = createObject(); - m_aEmbeddedFiles.back().m_aData = *rGraphic.getPdfData(); - + m_aEmbeddedFiles.back().m_aData = aPDFData; rEmit.m_nEmbeddedObject = m_aEmbeddedFiles.back().m_nObject; } else - rEmit.m_aPDFData = *rGraphic.getPdfData(); + rEmit.m_aPDFData = aPDFData; rEmit.m_nFormObject = createObject(); rEmit.m_aPixelSize = rGraphic.GetPrefSize(); @@ -9750,7 +9754,7 @@ void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const { m_aJPGs.emplace( m_aJPGs.begin() ); JPGEmit& rEmit = m_aJPGs.front(); - if (!rGraphic.hasPdfData() || m_aContext.UseReferenceXObject) + if (!rGraphic.getVectorGraphicData().get() || rGraphic.getVectorGraphicData()->getVectorGraphicDataType() != VectorGraphicDataType::Pdf || m_aContext.UseReferenceXObject) rEmit.m_nObject = createObject(); rEmit.m_aID = aID; rEmit.m_pStream.reset( pStream ); @@ -9858,7 +9862,7 @@ const PDFWriterImpl::BitmapEmit& PDFWriterImpl::createBitmapEmit( const BitmapEx m_aBitmaps.push_front( BitmapEmit() ); m_aBitmaps.front().m_aID = aID; m_aBitmaps.front().m_aBitmap = aBitmap; - if (!rGraphic.hasPdfData() || m_aContext.UseReferenceXObject) + if (!rGraphic.getVectorGraphicData().get() || rGraphic.getVectorGraphicData()->getVectorGraphicDataType() != VectorGraphicDataType::Pdf || m_aContext.UseReferenceXObject) m_aBitmaps.front().m_nObject = createObject(); createEmbeddedFile(rGraphic, m_aBitmaps.front().m_aReferenceXObject, m_aBitmaps.front().m_nObject); it = m_aBitmaps.begin(); diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx index 892f2864a1ab..6b3debe7b589 100644 --- a/vcl/source/gdi/vectorgraphicdata.cxx +++ b/vcl/source/gdi/vectorgraphicdata.cxx @@ -22,16 +22,20 @@ #include <vcl/vectorgraphicdata.hxx> #include <comphelper/processfactory.hxx> #include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/graphic/PdfTools.hpp> #include <com/sun/star/graphic/SvgTools.hpp> #include <com/sun/star/graphic/EmfTools.hpp> #include <com/sun/star/graphic/Primitive2DTools.hpp> #include <com/sun/star/rendering/XIntegerReadOnlyBitmap.hpp> #include <com/sun/star/util/XAccounting.hpp> +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <vcl/canvastools.hxx> #include <comphelper/seqstream.hxx> #include <comphelper/sequence.hxx> #include <vcl/svapp.hxx> #include <vcl/outdev.hxx> +#include <vcl/wmfexternal.hxx> +#include <vcl/pdfread.hxx> using namespace ::com::sun::star; @@ -132,11 +136,35 @@ void VectorGraphicData::setWmfExternalHeader(const WmfExternal& aExtHeader) *mpExternalHeader = aExtHeader; } +void VectorGraphicData::ensurePdfReplacement() +{ + assert(getVectorGraphicDataType() == VectorGraphicDataType::Pdf); + + if (!maReplacement.IsEmpty()) + return; // nothing to do + + // use PDFium directly + std::vector<Bitmap> aBitmaps; + vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength(), aBitmaps, 0, 1/*, fResolutionDPI*/); + maReplacement = aBitmaps[0]; +} + void VectorGraphicData::ensureReplacement() { + if (!maReplacement.IsEmpty()) + return; // nothing to do + + // shortcut for PDF - PDFium can generate the replacement bitmap for us + // directly + if (getVectorGraphicDataType() == VectorGraphicDataType::Pdf) + { + ensurePdfReplacement(); + return; + } + ensureSequenceAndRange(); - if(maReplacement.IsEmpty() && !maSequence.empty()) + if (!maSequence.empty()) { maReplacement = convertPrimitive2DSequenceToBitmapEx(maSequence, getRange()); } @@ -149,32 +177,43 @@ void VectorGraphicData::ensureSequenceAndRange() // import SVG to maSequence, also set maRange maRange.reset(); - // create stream - const uno::Reference< io::XInputStream > myInputStream(new comphelper::SequenceInputStream(maVectorGraphicDataArray)); + // create Vector Graphic Data interpreter + uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); - if(myInputStream.is()) + switch (getVectorGraphicDataType()) { - // create Vector Graphic Data interpreter - uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); + case VectorGraphicDataType::Svg: + { + const uno::Reference< graphic::XSvgParser > xSvgParser = graphic::SvgTools::create(xContext); + const uno::Reference< io::XInputStream > myInputStream(new comphelper::SequenceInputStream(maVectorGraphicDataArray)); - if (VectorGraphicDataType::Emf == getVectorGraphicDataType() - || VectorGraphicDataType::Wmf == getVectorGraphicDataType()) + if (myInputStream.is()) + maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xSvgParser->getDecomposition(myInputStream, maPath)); + + break; + } + case VectorGraphicDataType::Emf: + case VectorGraphicDataType::Wmf: { const uno::Reference< graphic::XEmfParser > xEmfParser = graphic::EmfTools::create(xContext); + const uno::Reference< io::XInputStream > myInputStream(new comphelper::SequenceInputStream(maVectorGraphicDataArray)); uno::Sequence< ::beans::PropertyValue > aSequence; if (mpExternalHeader) - { aSequence = mpExternalHeader->getSequence(); - } - maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence)); + if (myInputStream.is()) + maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence)); + + break; } - else + case VectorGraphicDataType::Pdf: { - const uno::Reference< graphic::XSvgParser > xSvgParser = graphic::SvgTools::create(xContext); + const uno::Reference<graphic::XPdfDecomposer> xPdfDecomposer = graphic::PdfTools::create(xContext); + auto xPrimitive2D = xPdfDecomposer->getDecomposition(maVectorGraphicDataArray); + maSequence = comphelper::sequenceToContainer<std::deque<uno::Reference<graphic::XPrimitive2D>>>(xPrimitive2D); - maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xSvgParser->getDecomposition(myInputStream, maPath)); + break; } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits