summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2020-03-13 20:04:45 +0100
committerTomaž Vajngerl <quikee@gmail.com>2020-03-18 09:23:15 +0100
commit27ee05f860e8225a41e15e0853fcef00a9d7a621 (patch)
tree277ae811da1551accde88468607d513d411be05e
parent9054c36d4ea3bee25fb9a47a96a0ea2cd07148c3 (diff)
pdfium: support for pages when using PDF import with pdfium
Moving PDF to use VectorGraphicData in Graphic has temporary removed the support for showing different PDF pages when opening the PDF using pdfium (LO_IMPORT_USE_PDFIUM=1). This adds the support for back by specifying whcih PDF page to render when creating the VectorGraphicData (and can't be changd afterwards), which is used to create a Graphic and contains the PDF source data array. Change-Id: Ib915216b8d4c0c063d0fead44ff156b1915a35d2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90562 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--filter/source/pdf/pdfdecomposer.cxx28
-rw-r--r--include/vcl/graph.hxx2
-rw-r--r--include/vcl/vectorgraphicdata.hxx12
-rw-r--r--offapi/com/sun/star/graphic/XPdfDecomposer.idl8
-rw-r--r--sd/qa/unit/import-tests.cxx15
-rw-r--r--vcl/inc/impgraph.hxx7
-rw-r--r--vcl/source/filter/ipdf/pdfread.cxx18
-rw-r--r--vcl/source/gdi/graph.cxx7
-rw-r--r--vcl/source/gdi/impgraph.cxx34
-rw-r--r--vcl/source/gdi/vectorgraphicdata.cxx22
10 files changed, 85 insertions, 68 deletions
diff --git a/filter/source/pdf/pdfdecomposer.cxx b/filter/source/pdf/pdfdecomposer.cxx
index c926b1b35a9d..a03e70bd5d1a 100644
--- a/filter/source/pdf/pdfdecomposer.cxx
+++ b/filter/source/pdf/pdfdecomposer.cxx
@@ -39,8 +39,9 @@ public:
XPdfDecomposer& operator=(const XPdfDecomposer&) = delete;
// XPdfDecomposer
- uno::Sequence<uno::Reference<graphic::XPrimitive2D>>
- SAL_CALL getDecomposition(const uno::Sequence<sal_Int8>& xPdfData) override;
+ uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL
+ getDecomposition(const uno::Sequence<sal_Int8>& xPdfData,
+ const uno::Sequence<beans::PropertyValue>& xDecompositionParameters) override;
// XServiceInfo
OUString SAL_CALL getImplementationName() override;
@@ -50,12 +51,27 @@ public:
XPdfDecomposer::XPdfDecomposer(uno::Reference<uno::XComponentContext> const&) {}
-uno::Sequence<uno::Reference<graphic::XPrimitive2D>>
- SAL_CALL XPdfDecomposer::getDecomposition(const uno::Sequence<sal_Int8>& xPdfData)
+uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL XPdfDecomposer::getDecomposition(
+ const uno::Sequence<sal_Int8>& xPdfData, const uno::Sequence<beans::PropertyValue>& xParameters)
{
+ sal_Int32 nPageIndex = -1;
+
+ for (sal_Int32 index = 0; index < xParameters.getLength(); index++)
+ {
+ const beans::PropertyValue& rProperty = xParameters[index];
+
+ if (rProperty.Name == "PageIndex")
+ {
+ rProperty.Value >>= nPageIndex;
+ }
+ }
+
+ if (nPageIndex < 0)
+ nPageIndex = 0;
+
std::vector<Bitmap> aBitmaps;
- vcl::RenderPDFBitmaps(xPdfData.getConstArray(), xPdfData.getLength(), aBitmaps, 0,
- 1 /*, fResolutionDPI*/);
+ vcl::RenderPDFBitmaps(xPdfData.getConstArray(), xPdfData.getLength(), aBitmaps, nPageIndex, 1);
+
BitmapEx aReplacement(aBitmaps[0]);
// short form for scale and translate transformation
diff --git a/include/vcl/graph.hxx b/include/vcl/graph.hxx
index 271de60d1605..6e70f66731ac 100644
--- a/include/vcl/graph.hxx
+++ b/include/vcl/graph.hxx
@@ -204,8 +204,6 @@ public:
const VectorGraphicDataPtr& getVectorGraphicData() 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.
sal_Int32 getPageNumber() const;
diff --git a/include/vcl/vectorgraphicdata.hxx b/include/vcl/vectorgraphicdata.hxx
index 096c89e1aa56..8ccf45b51e5d 100644
--- a/include/vcl/vectorgraphicdata.hxx
+++ b/include/vcl/vectorgraphicdata.hxx
@@ -70,6 +70,9 @@ private:
// extra:
std::unique_ptr<WmfExternal> mpExternalHeader;
+ // If the vector format has more pages this denotes which page to render
+ sal_Int32 mnPageIndex;
+
// on demand creators
void ensurePdfReplacement();
void ensureReplacement();
@@ -82,10 +85,9 @@ public:
VectorGraphicData(
const VectorGraphicDataArray& rVectorGraphicDataArray,
const OUString& rPath,
- VectorGraphicDataType eVectorDataType);
- VectorGraphicData(
- const OUString& rPath,
- VectorGraphicDataType eVectorDataType);
+ VectorGraphicDataType eVectorDataType,
+ sal_Int32 nPageIndex = -1);
+ VectorGraphicData(const OUString& rPath, VectorGraphicDataType eVectorDataType);
~VectorGraphicData();
/// compare op
@@ -107,6 +109,8 @@ public:
const std::deque< css::uno::Reference< css::graphic::XPrimitive2D > >& getPrimitive2DSequence() const;
const BitmapEx& getReplacement() const;
BitmapChecksum GetChecksum() const;
+
+ sal_Int32 getPageIndex() const { return mnPageIndex; }
};
typedef std::shared_ptr< VectorGraphicData > VectorGraphicDataPtr;
diff --git a/offapi/com/sun/star/graphic/XPdfDecomposer.idl b/offapi/com/sun/star/graphic/XPdfDecomposer.idl
index 85b38c035c8c..aae6eda55347 100644
--- a/offapi/com/sun/star/graphic/XPdfDecomposer.idl
+++ b/offapi/com/sun/star/graphic/XPdfDecomposer.idl
@@ -27,9 +27,15 @@ interface XPdfDecomposer : ::com::sun::star::uno::XInterface
@param xPdfData
The PDF data.
+ @param xDecompositionParameters
+ Parameters for decomposition. Parameters include:
+
+ sal_Int32 Page - which page to use
+
@since LibreOffice 7.0
*/
- sequence<XPrimitive2D> getDecomposition([in] sequence<byte> xPdfData);
+ sequence<XPrimitive2D> getDecomposition([in] sequence<byte> xPdfData,
+ [in] sequence<com::sun::star::beans::PropertyValue> xDecompositionParameters);
};
}; }; }; };
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index addf393630a1..954ef5b187ba 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -1327,17 +1327,20 @@ void SdImportTest::testPDFImportShared()
CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected more than one page.", size_t(3), aGraphics.size());
- Graphic aFirstGraphic = aGraphics[0];
+ Graphic const & rFirstGraphic = aGraphics[0];
- for (size_t i = 1; i < aGraphics.size(); ++i)
+ for (size_t i = 0; i < aGraphics.size(); ++i)
{
+ Graphic const & rGraphic = aGraphics[i];
CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected all PDF streams to be identical.",
- aFirstGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray(),
- aGraphics[i].getVectorGraphicData()->getVectorGraphicDataArray().getConstArray());
+ rFirstGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray(),
+ rGraphic.getVectorGraphicData()->getVectorGraphicDataArray().getConstArray());
CPPUNIT_ASSERT_EQUAL_MESSAGE("Expected all GfxLinks to be identical.",
- aFirstGraphic.GetSharedGfxLink().get(),
- aGraphics[i].GetSharedGfxLink().get());
+ rFirstGraphic.GetSharedGfxLink().get(),
+ rGraphic.GetSharedGfxLink().get());
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("Page number doesn't match expected", sal_Int32(i), rGraphic.getPageNumber());
}
xDocShRef->DoClose();
diff --git a/vcl/inc/impgraph.hxx b/vcl/inc/impgraph.hxx
index 965c41a4392e..a5435ee73b39 100644
--- a/vcl/inc/impgraph.hxx
+++ b/vcl/inc/impgraph.hxx
@@ -75,11 +75,6 @@ private:
std::chrono::high_resolution_clock::time_point maLastUsed;
bool mbPrepared;
- /// Used with GfxLink and/or PdfData when they store original media
- /// which might be multi-page (PDF, f.e.) and we need to re-render
- /// this Graphic (a page) from the source in GfxLink or PdfData.
- sal_Int32 mnPageNumber;
-
public:
ImpGraphic();
ImpGraphic( const ImpGraphic& rImpGraphic );
@@ -203,6 +198,8 @@ private:
bool ensureAvailable () const;
bool loadPrepared();
+
+ sal_Int32 getPageNumber() const;
};
#endif // INCLUDED_VCL_INC_IMPGRAPH_HXX
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx
index 0dbb0fe455cb..b85a79d86e4a 100644
--- a/vcl/source/filter/ipdf/pdfread.cxx
+++ b/vcl/source/filter/ipdf/pdfread.cxx
@@ -223,19 +223,12 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<Bitmap>& rBi
bool ImportPDF(SvStream& rStream, Graphic& rGraphic)
{
- // Save the original PDF stream for later use.
- SvMemoryStream aMemoryStream;
- if (!getCompatibleStream(rStream, aMemoryStream, STREAM_SEEK_TO_BEGIN, STREAM_SEEK_TO_END))
- return false;
- const sal_uInt32 nStreamLength = aMemoryStream.TellEnd();
- VectorGraphicDataArray aPdfData(nStreamLength);
- aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
- aMemoryStream.ReadBytes(aPdfData.begin(), nStreamLength);
- if (aMemoryStream.GetError())
+ VectorGraphicDataArray aPdfDataArray = createVectorGraphicDataArray(rStream);
+ if (!aPdfDataArray.hasElements())
return false;
- auto aVectorGraphicDataPtr
- = std::make_shared<VectorGraphicData>(aPdfData, OUString(), VectorGraphicDataType::Pdf);
+ auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(aPdfDataArray, OUString(),
+ VectorGraphicDataType::Pdf);
rGraphic = Graphic(aVectorGraphicDataPtr);
return true;
@@ -291,13 +284,12 @@ size_t ImportPDFUnloaded(const OUString& rURL, std::vector<std::pair<Graphic, Si
const size_t nPageHeight = pointToPixel(fPageHeight, fResolutionDPI);
auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(
- aPdfDataArray, OUString(), VectorGraphicDataType::Pdf);
+ aPdfDataArray, OUString(), VectorGraphicDataType::Pdf, nPageIndex);
// 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(aVectorGraphicDataPtr);
- aGraphic.setPageNumber(nPageIndex);
aGraphic.SetGfxLink(pGfxLink);
rGraphics.emplace_back(std::move(aGraphic), Size(nPageWidth, nPageHeight));
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index c98212ad5c67..96414b43ad3a 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -560,14 +560,9 @@ const VectorGraphicDataPtr& Graphic::getVectorGraphicData() const
return mxImpGraphic->getVectorGraphicData();
}
-void Graphic::setPageNumber(sal_Int32 nPageNumber)
-{
- mxImpGraphic->mnPageNumber = nPageNumber;
-}
-
sal_Int32 Graphic::getPageNumber() const
{
- return mxImpGraphic->mnPageNumber;
+ return mxImpGraphic->getPageNumber();
}
OUString Graphic::getOriginURL() const
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 9361aef3951d..90a1e4e58ed8 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -73,8 +73,7 @@ ImpGraphic::ImpGraphic() :
mbSwapOut ( false ),
mbDummyContext ( false ),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared ( false ),
- mnPageNumber(-1)
+ mbPrepared ( false )
{
}
@@ -93,7 +92,6 @@ ImpGraphic::ImpGraphic(const ImpGraphic& rImpGraphic)
, maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
, maLastUsed (std::chrono::high_resolution_clock::now())
, mbPrepared (rImpGraphic.mbPrepared)
- , mnPageNumber(rImpGraphic.mnPageNumber)
{
if( rImpGraphic.mpAnimation )
{
@@ -118,7 +116,6 @@ ImpGraphic::ImpGraphic(ImpGraphic&& rImpGraphic) noexcept
, maGraphicExternalLink(rImpGraphic.maGraphicExternalLink)
, maLastUsed (std::chrono::high_resolution_clock::now())
, mbPrepared (rImpGraphic.mbPrepared)
- , mnPageNumber(rImpGraphic.mnPageNumber)
{
rImpGraphic.ImplClear();
rImpGraphic.mbDummyContext = false;
@@ -131,8 +128,7 @@ ImpGraphic::ImpGraphic(GraphicExternalLink const & rGraphicExternalLink) :
mbDummyContext ( false ),
maGraphicExternalLink(rGraphicExternalLink),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared (false),
- mnPageNumber(-1)
+ mbPrepared (false)
{
}
@@ -143,8 +139,7 @@ ImpGraphic::ImpGraphic( const Bitmap& rBitmap ) :
mbSwapOut ( false ),
mbDummyContext ( false ),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared (false),
- mnPageNumber(-1)
+ mbPrepared (false)
{
}
@@ -155,8 +150,7 @@ ImpGraphic::ImpGraphic( const BitmapEx& rBitmapEx ) :
mbSwapOut ( false ),
mbDummyContext ( false ),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared (false),
- mnPageNumber(-1)
+ mbPrepared (false)
{
}
@@ -167,8 +161,7 @@ ImpGraphic::ImpGraphic(const VectorGraphicDataPtr& rVectorGraphicDataPtr)
mbDummyContext ( false ),
maVectorGraphicData(rVectorGraphicDataPtr),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared (false),
- mnPageNumber(-1)
+ mbPrepared (false)
{
}
@@ -180,8 +173,7 @@ ImpGraphic::ImpGraphic( const Animation& rAnimation ) :
mbSwapOut ( false ),
mbDummyContext ( false ),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared (false),
- mnPageNumber(-1)
+ mbPrepared (false)
{
}
@@ -192,8 +184,7 @@ ImpGraphic::ImpGraphic( const GDIMetaFile& rMtf ) :
mbSwapOut ( false ),
mbDummyContext ( false ),
maLastUsed (std::chrono::high_resolution_clock::now()),
- mbPrepared (false),
- mnPageNumber(-1)
+ mbPrepared (false)
{
}
@@ -215,7 +206,6 @@ ImpGraphic& ImpGraphic::operator=( const ImpGraphic& rImpGraphic )
maSwapInfo = rImpGraphic.maSwapInfo;
mpContext = rImpGraphic.mpContext;
mbDummyContext = rImpGraphic.mbDummyContext;
- mnPageNumber = rImpGraphic.mnPageNumber;
maGraphicExternalLink = rImpGraphic.maGraphicExternalLink;
mpAnimation.reset();
@@ -255,7 +245,6 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic)
maSwapInfo = std::move(rImpGraphic.maSwapInfo);
mpContext = std::move(rImpGraphic.mpContext);
mbDummyContext = rImpGraphic.mbDummyContext;
- mnPageNumber = rImpGraphic.mnPageNumber;
mpAnimation = std::move(rImpGraphic.mpAnimation);
maEx = std::move(rImpGraphic.maEx);
mbSwapOut = rImpGraphic.mbSwapOut;
@@ -271,8 +260,6 @@ ImpGraphic& ImpGraphic::operator=(ImpGraphic&& rImpGraphic)
vcl::graphic::Manager::get().changeExisting(this, aOldSizeBytes);
- rImpGraphic.mnPageNumber = -1;
-
return *this;
}
@@ -1618,6 +1605,13 @@ bool ImpGraphic::ImplExportNative( SvStream& rOStm ) const
return bResult;
}
+sal_Int32 ImpGraphic::getPageNumber() const
+{
+ if (maVectorGraphicData)
+ return maVectorGraphicData->getPageIndex();
+ return -1;
+}
+
static std::map<BitmapChecksum, std::shared_ptr<std::vector<sal_Int8>>> sPdfDataCache;
void ReadImpGraphic( SvStream& rIStm, ImpGraphic& rImpGraphic )
diff --git a/vcl/source/gdi/vectorgraphicdata.cxx b/vcl/source/gdi/vectorgraphicdata.cxx
index 9d877b35a73a..99e51f65cc71 100644
--- a/vcl/source/gdi/vectorgraphicdata.cxx
+++ b/vcl/source/gdi/vectorgraphicdata.cxx
@@ -33,6 +33,7 @@
#include <vcl/canvastools.hxx>
#include <comphelper/seqstream.hxx>
#include <comphelper/sequence.hxx>
+#include <comphelper/propertysequence.hxx>
#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>
#include <vcl/wmfexternal.hxx>
@@ -146,7 +147,10 @@ void VectorGraphicData::ensurePdfReplacement()
// use PDFium directly
std::vector<Bitmap> aBitmaps;
- vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength(), aBitmaps, 0, 1/*, fResolutionDPI*/);
+ sal_Int32 nUsePageIndex = 0;
+ if (mnPageIndex >= 0)
+ nUsePageIndex = mnPageIndex;
+ vcl::RenderPDFBitmaps(maVectorGraphicDataArray.getConstArray(), maVectorGraphicDataArray.getLength(), aBitmaps, nUsePageIndex, 1/*, fResolutionDPI*/);
maReplacement = aBitmaps[0];
}
@@ -201,7 +205,9 @@ void VectorGraphicData::ensureSequenceAndRange()
uno::Sequence< ::beans::PropertyValue > aSequence;
if (mpExternalHeader)
+ {
aSequence = mpExternalHeader->getSequence();
+ }
if (myInputStream.is())
maSequence = comphelper::sequenceToContainer<std::deque<css::uno::Reference< css::graphic::XPrimitive2D >>>(xEmfParser->getDecomposition(myInputStream, maPath, aSequence));
@@ -211,7 +217,10 @@ void VectorGraphicData::ensureSequenceAndRange()
case VectorGraphicDataType::Pdf:
{
const uno::Reference<graphic::XPdfDecomposer> xPdfDecomposer = graphic::PdfTools::create(xContext);
- auto xPrimitive2D = xPdfDecomposer->getDecomposition(maVectorGraphicDataArray);
+ uno::Sequence<beans::PropertyValue> aDecompositionParameters = comphelper::InitPropertySequence({
+ {"PageIndex", uno::makeAny<sal_Int32>(mnPageIndex)},
+ });
+ auto xPrimitive2D = xPdfDecomposer->getDecomposition(maVectorGraphicDataArray, aDecompositionParameters);
maSequence = comphelper::sequenceToContainer<std::deque<uno::Reference<graphic::XPrimitive2D>>>(xPrimitive2D);
break;
@@ -262,7 +271,8 @@ auto VectorGraphicData::getSizeBytes() const -> std::pair<State, size_t>
VectorGraphicData::VectorGraphicData(
const VectorGraphicDataArray& rVectorGraphicDataArray,
const OUString& rPath,
- VectorGraphicDataType eVectorDataType)
+ VectorGraphicDataType eVectorDataType,
+ sal_Int32 nPageIndex)
: maVectorGraphicDataArray(rVectorGraphicDataArray),
maPath(rPath),
mbSequenceCreated(false),
@@ -270,7 +280,8 @@ VectorGraphicData::VectorGraphicData(
maSequence(),
maReplacement(),
mNestedBitmapSize(0),
- meVectorGraphicDataType(eVectorDataType)
+ meVectorGraphicDataType(eVectorDataType),
+ mnPageIndex(nPageIndex)
{
}
@@ -284,7 +295,8 @@ VectorGraphicData::VectorGraphicData(
maSequence(),
maReplacement(),
mNestedBitmapSize(0),
- meVectorGraphicDataType(eVectorDataType)
+ meVectorGraphicDataType(eVectorDataType),
+ mnPageIndex(-1)
{
SvFileStream rIStm(rPath, StreamMode::STD_READ);
if(rIStm.GetError())