12 #include <config_features.h>
14 #if HAVE_FEATURE_PDFIUM
16 #include <fpdf_edit.h>
32 #if HAVE_FEATURE_PDFIUM
35 inline double pointToPixel(
const double fPoint,
const double fResolutionDPI)
37 return fPoint * fResolutionDPI / 72.;
41 bool isCompatible(
SvStream& rInStream, sal_uInt64 nPos, sal_uInt64 nSize)
53 if (aFirstBytes[0] !=
'%' || aFirstBytes[1] !=
'P' || aFirstBytes[2] !=
'D'
54 || aFirstBytes[3] !=
'F' || aFirstBytes[4] !=
'-')
57 sal_Int32 nMajor = OString(
char(aFirstBytes[5])).toInt32();
58 sal_Int32 nMinor = OString(
char(aFirstBytes[7])).toInt32();
59 return !(nMajor > 1 || (nMajor == 1 && nMinor > 6));
68 bool bCompatible = isCompatible(rInStream, nPos, nSize);
76 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
85 std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
91 if (!pPdfDocument->saveWithVersion(aSaved, 16))
95 aSaved.
Seek(STREAM_SEEK_TO_BEGIN);
99 return rOutStream.
good();
104 rInStream.
Seek(STREAM_SEEK_TO_BEGIN);
105 rOutStream.
WriteStream(rInStream, STREAM_SEEK_TO_END);
106 return rOutStream.
good();
108 #endif // HAVE_FEATURE_PDFIUM
114 if (!getCompatibleStream(rStream, aMemoryStream))
117 const sal_uInt32 nStreamLength = aMemoryStream.
TellEnd();
121 aMemoryStream.
Seek(STREAM_SEEK_TO_BEGIN);
122 aMemoryStream.
ReadBytes(aPdfData.begin(), nStreamLength);
136 #if HAVE_FEATURE_PDFIUM
137 const double fResolutionDPI = 96;
138 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
141 std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = pPdfium->openDocument(pBuffer, nSize);
145 const int nPageCount = pPdfDocument->getPageCount();
148 const size_t nLastPage = std::min<int>(nPageCount, nFirstPage + nPages) - 1;
149 for (
size_t nPageIndex = nFirstPage; nPageIndex <= nLastPage; ++nPageIndex)
152 std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(nPageIndex);
157 size_t nPageWidthPoints = pPdfPage->getWidth();
158 size_t nPageHeightPoints = pPdfPage->getHeight();
159 if (pSizeHint && pSizeHint->
getX() && pSizeHint->
getY())
167 const size_t nPageWidth = pointToPixel(nPageWidthPoints, fResolutionDPI);
168 const size_t nPageHeight = pointToPixel(nPageHeightPoints, fResolutionDPI);
169 std::unique_ptr<vcl::pdf::PDFiumBitmap> pPdfBitmap
170 = pPdfium->createBitmap(nPageWidth, nPageHeight, 1);
174 bool bTransparent = pPdfPage->hasTransparency();
181 const sal_uInt32 nColor = bTransparent ? 0x00000000 : 0xFFFFFFFF;
182 pPdfBitmap->fillRect(0, 0, nPageWidth, nPageHeight, nColor);
183 pPdfBitmap->renderPageBitmap(pPdfPage.get(), 0,
184 0, nPageWidth, nPageHeight);
187 Bitmap aBitmap(
Size(nPageWidth, nPageHeight), 24);
193 const int nStride = pPdfBitmap->getStride();
194 std::vector<sal_uInt8> aScanlineAlpha(nPageWidth);
195 for (
size_t nRow = 0; nRow < nPageHeight; ++nRow)
200 for (
size_t nCol = 0; nCol < nPageWidth; ++nCol)
203 aScanlineAlpha[nCol] = ~pPdfLine[3];
213 rBitmaps.emplace_back(aBitmap, aMask);
217 rBitmaps.emplace_back(std::move(aBitmap));
221 return rBitmaps.size();
230 #endif // HAVE_FEATURE_PDFIUM
234 std::shared_ptr<VectorGraphicData>& rVectorGraphicData)
237 if (!aPdfDataArray.hasElements())
239 SAL_WARN(
"vcl.filter",
"ImportPDF: empty PDF data array");
251 std::shared_ptr<VectorGraphicData> pVectorGraphicData;
254 rGraphic =
Graphic(pVectorGraphicData);
258 #if HAVE_FEATURE_PDFIUM
269 std::vector<PDFGraphicAnnotation>
270 findAnnotations(
const std::unique_ptr<vcl::pdf::PDFiumPage>& pPage,
basegfx::B2DSize aPageSize)
272 std::vector<PDFGraphicAnnotation> aPDFGraphicAnnotations;
273 for (
int nAnnotation = 0; nAnnotation < pPage->getAnnotationCount(); nAnnotation++)
275 auto pAnnotation = pPage->getAnnotation(nAnnotation);
278 auto eSubtype = pAnnotation->getSubType();
288 OUString sAuthor = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
289 OUString sText = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
298 OUString sDateTimeString
299 = pAnnotation->getString(vcl::pdf::constDictionaryKeyModificationDate);
300 OUString sISO8601String = vcl::pdf::convertPdfDateToISO8601(sDateTimeString);
302 css::util::DateTime aDateTime;
303 if (!sISO8601String.isEmpty())
308 Color aColor = pAnnotation->getColor();
310 aPDFGraphicAnnotations.emplace_back();
312 auto& rPDFGraphicAnnotation = aPDFGraphicAnnotations.back();
313 rPDFGraphicAnnotation.maRectangle = rRectangleHMM;
314 rPDFGraphicAnnotation.maAuthor = sAuthor;
315 rPDFGraphicAnnotation.maText = sText;
316 rPDFGraphicAnnotation.maDateTime = aDateTime;
317 rPDFGraphicAnnotation.meSubType = eSubtype;
318 rPDFGraphicAnnotation.maColor = aColor;
322 auto const& rVertices = pAnnotation->getVertices();
323 if (!rVertices.empty())
325 auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerPolygon>();
326 rPDFGraphicAnnotation.mpMarker = pMarker;
327 for (
auto const& rVertex : rVertices)
329 auto aPoint = convertFromPDFInternalToHMM(rVertex, aPageSize);
330 pMarker->maPolygon.append(aPoint);
332 pMarker->maPolygon.setClosed(
true);
334 if (pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor))
335 pMarker->maFillColor = pAnnotation->getInteriorColor();
340 auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerSquare>();
341 rPDFGraphicAnnotation.mpMarker = pMarker;
343 if (pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor))
344 pMarker->maFillColor = pAnnotation->getInteriorColor();
348 auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerCircle>();
349 rPDFGraphicAnnotation.mpMarker = pMarker;
351 if (pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor))
352 pMarker->maFillColor = pAnnotation->getInteriorColor();
356 auto const& rStrokesList = pAnnotation->getInkStrokes();
357 if (!rStrokesList.empty())
359 auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerInk>();
360 rPDFGraphicAnnotation.mpMarker = pMarker;
361 for (
auto const& rStrokes : rStrokesList)
364 for (
auto const& rVertex : rStrokes)
366 auto aPoint = convertFromPDFInternalToHMM(rVertex, aPageSize);
369 pMarker->maStrokes.push_back(aPolygon);
371 float fWidth = pAnnotation->getBorderWidth();
373 if (pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor))
374 pMarker->maFillColor = pAnnotation->getInteriorColor();
379 size_t nCount = pAnnotation->getAttachmentPointsCount();
382 auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerHighlight>(
384 rPDFGraphicAnnotation.mpMarker = pMarker;
385 for (
size_t i = 0;
i < nCount; ++
i)
387 auto aAttachmentPoints = pAnnotation->getAttachmentPoints(i);
388 if (!aAttachmentPoints.empty())
394 = convertFromPDFInternalToHMM(aAttachmentPoints[0], aPageSize);
397 = convertFromPDFInternalToHMM(aAttachmentPoints[1], aPageSize);
400 = convertFromPDFInternalToHMM(aAttachmentPoints[3], aPageSize);
403 = convertFromPDFInternalToHMM(aAttachmentPoints[2], aPageSize);
406 pMarker->maQuads.push_back(aPolygon);
413 auto const& rLineGeometry = pAnnotation->getLineGeometry();
414 if (!rLineGeometry.empty())
416 auto pMarker = std::make_shared<vcl::pdf::PDFAnnotationMarkerLine>();
417 rPDFGraphicAnnotation.mpMarker = pMarker;
419 auto aPoint1 = convertFromPDFInternalToHMM(rLineGeometry[0], aPageSize);
420 pMarker->maLineStart = aPoint1;
422 auto aPoint2 = convertFromPDFInternalToHMM(rLineGeometry[1], aPageSize);
423 pMarker->maLineEnd = aPoint2;
425 float fWidth = pAnnotation->getBorderWidth();
432 return aPDFGraphicAnnotations;
440 #if HAVE_FEATURE_PDFIUM
441 std::unique_ptr<SvStream>
xStream(
448 if (!aPdfDataArray.hasElements())
457 auto pPdfium = vcl::pdf::PDFiumLibrary::get();
460 auto pPdfDocument = pPdfium->openDocument(pGfxLink->GetData(), pGfxLink->GetDataSize());
465 const int nPageCount = pPdfDocument->getPageCount();
469 for (
int nPageIndex = 0; nPageIndex < nPageCount; ++nPageIndex)
472 if (aPageSize.
getX() <= 0.0 || aPageSize.
getY() <= 0.0)
477 constexpr
double pointToTwipconversionRatio = 20;
482 auto aVectorGraphicDataPtr = std::make_shared<VectorGraphicData>(
488 Graphic aGraphic(aVectorGraphicDataPtr);
489 aGraphic.SetGfxLink(pGfxLink);
491 auto pPage = pPdfDocument->openPage(nPageIndex);
493 std::vector<PDFGraphicAnnotation> aPDFGraphicAnnotations
494 = findAnnotations(pPage, aPageSize);
496 rGraphics.emplace_back(std::move(aGraphic),
Size(nPageWidth, nPageHeight),
497 aPDFGraphicAnnotations);
500 return rGraphics.size();
505 #endif // HAVE_FEATURE_PDFIUM
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
size_t RenderPDFBitmaps(const void *pBuffer, int nSize, std::vector< BitmapEx > &rBitmaps, const size_t nFirstPage, int nPages, const basegfx::B2DTuple *pSizeHint)
Fills the rBitmaps vector with rendered pages.
std::unique_ptr< ContentProperties > pData
bool importPdfVectorGraphicData(SvStream &rStream, std::shared_ptr< VectorGraphicData > &rVectorGraphicData)
Imports a PDF stream as a VectorGraphicData.
#define STREAM_SEEK_TO_END
sal_uInt64 Seek(sal_uInt64 nPos)
virtual sal_uInt64 TellEnd() override
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
constexpr sal_Int64 convertPointToMm100(sal_Int64 nNumber)
#define STREAM_SEEK_TO_BEGIN
SvStream & WriteStream(SvStream &rStream)
const sal_uInt8 * ConstScanline
std::size_t ReadBytes(void *pData, std::size_t nSize)
void setClosed(bool bNew)
css::uno::Sequence< sal_Int8 > VectorGraphicDataArray
constexpr sal_Int64 convertTwipToMm100(sal_Int64 n)
void CopyScanline(tools::Long nY, const BitmapReadAccess &rReadAcc)
constexpr sal_Int64 convertMm100ToTwip(sal_Int64 n)
size_t ImportPDFUnloaded(const OUString &rURL, std::vector< PDFGraphicResult > &rGraphics)
Import PDF as Graphic images (1 per page), but not loaded yet.
#define SAL_WARN(area, stream)
bool ISO8601parseDateTime(const OUString &rString, css::util::DateTime &rDateTime)
bool ImportPDF(SvStream &rStream, Graphic &rGraphic)
Imports a PDF stream into rGraphic.