diff options
author | Jan Holesovsky <kendy@collabora.com> | 2019-10-18 11:19:04 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2020-06-06 19:23:54 +0200 |
commit | 15834ad4dee944374f4b6298f2d384d185a49815 (patch) | |
tree | bb52eb53d8e48fbab826374bb982b18341a373cd /vcl | |
parent | 3862929efcc5e9275d878bbe64cb034796e4012d (diff) |
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).
Change-Id: Iac102f32b757390a03438c165e430283851cc10b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90561
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95618
Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/impgraph.hxx | 13 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 134 | ||||
-rw-r--r-- | vcl/source/gdi/graph.cxx | 17 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 81 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 16 | ||||
-rw-r--r-- | vcl/source/gdi/vectorgraphicdata.cxx | 67 | ||||
-rw-r--r-- | vcl/source/graphic/GraphicID.cxx | 10 |
7 files changed, 122 insertions, 216 deletions
diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx index 62a44b7e17a9..d49856011996 100644 --- a/vcl/inc/impgraph.hxx +++ b/vcl/inc/impgraph.hxx @@ -71,10 +71,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; @@ -124,11 +120,6 @@ private: return mpGraphicID->getIDString(); } - bool hasPdfData() const - { - return mpPdfData && !mpPdfData->empty(); - } - void ImplCreateSwapInfo(); void ImplClearGraphics(); void ImplClear(); @@ -211,10 +202,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); - /// Gets the bitmap replacement for a vector graphic. BitmapEx getVectorGraphicReplacement() const; diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 1d253d023424..b960c41483ec 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -46,20 +46,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) { @@ -130,12 +116,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) { @@ -144,8 +124,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, @@ -221,63 +221,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, @@ -288,22 +249,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; @@ -314,7 +271,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; @@ -322,9 +279,6 @@ 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 (int nPageIndex = 0; nPageIndex < nPageCount; ++nPageIndex) { double fPageWidth = 0; @@ -336,11 +290,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 ec2de64a74fe..250c01f674d0 100644 --- a/vcl/source/gdi/graph.cxx +++ b/vcl/source/gdi/graph.cxx @@ -560,23 +560,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 e55fb7f12395..f60b165d0084 100644 --- a/vcl/source/gdi/impgraph.cxx +++ b/vcl/source/gdi/impgraph.cxx @@ -58,8 +58,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 @@ -92,7 +90,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) @@ -118,7 +115,6 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) noexcept , 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) @@ -241,7 +237,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); @@ -267,7 +262,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; @@ -322,10 +316,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 ) ) @@ -353,20 +343,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()) @@ -388,7 +364,6 @@ void ImpGraphic::ImplClearGraphics() mpAnimation.reset(); mpGfxLink.reset(); maVectorGraphicData.reset(); - mpPdfData.reset(); } ImpSwapFile::~ImpSwapFile() @@ -1623,10 +1598,6 @@ BitmapChecksum ImpGraphic::ImplGetChecksum() const { 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 @@ -1780,12 +1751,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); @@ -1809,35 +1781,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); @@ -1865,8 +1818,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 ); @@ -1913,12 +1865,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() ); @@ -1927,17 +1885,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 35ac2e7dc6e0..807c2b5a60d8 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -9423,20 +9423,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(); + + auto pPDFData = std::make_shared<std::vector<sal_Int8>>(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_pData = rGraphic.getPdfData(); - + m_aEmbeddedFiles.back().m_pData = pPDFData; rEmit.m_nEmbeddedObject = m_aEmbeddedFiles.back().m_nObject; } else - rEmit.m_aPDFData = *rGraphic.getPdfData(); + rEmit.m_aPDFData = *pPDFData; rEmit.m_nFormObject = createObject(); rEmit.m_aPixelSize = rGraphic.GetPrefSize(); @@ -9491,7 +9495,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 = std::move( pStream ); @@ -9595,7 +9599,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 09e1d45974c5..9d877b35a73a 100644 --- a/vcl/source/gdi/vectorgraphicdata.cxx +++ b/vcl/source/gdi/vectorgraphicdata.cxx @@ -22,17 +22,21 @@ #include <sal/log.hxx> #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; @@ -133,11 +137,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()); } @@ -150,32 +178,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; } } diff --git a/vcl/source/graphic/GraphicID.cxx b/vcl/source/graphic/GraphicID.cxx index 7220853b998b..15de2a0d6f0f 100644 --- a/vcl/source/graphic/GraphicID.cxx +++ b/vcl/source/graphic/GraphicID.cxx @@ -42,16 +42,6 @@ GraphicID::GraphicID(ImpGraphic const& rGraphic) 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()); |