nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / pdf / PDFiumLibrary.cxx
blob76a70ad107b1d0ecedb5b6aa10d6189eb3392c46
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #include <config_features.h>
13 #if HAVE_FEATURE_PDFIUM
15 #include <cassert>
17 #include <vcl/filter/PDFiumLibrary.hxx>
18 #include <fpdf_annot.h>
19 #include <fpdf_edit.h>
20 #include <fpdf_text.h>
21 #include <fpdf_save.h>
22 #include <fpdf_signature.h>
23 #include <fpdf_formfill.h>
25 #include <osl/endian.h>
26 #include <vcl/bitmap.hxx>
27 #include <tools/stream.hxx>
29 #include <bitmapwriteaccess.hxx>
31 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Unknown) == FPDF_PAGEOBJ_UNKNOWN,
32 "PDFPageObjectType::Unknown value mismatch");
33 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Text) == FPDF_PAGEOBJ_TEXT,
34 "PDFPageObjectType::Text value mismatch");
35 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Path) == FPDF_PAGEOBJ_PATH,
36 "PDFPageObjectType::Path value mismatch");
37 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Image) == FPDF_PAGEOBJ_IMAGE,
38 "PDFPageObjectType::Image value mismatch");
39 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Shading) == FPDF_PAGEOBJ_SHADING,
40 "PDFPageObjectType::Shading value mismatch");
41 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Form) == FPDF_PAGEOBJ_FORM,
42 "PDFPageObjectType::Form value mismatch");
44 namespace
46 /// Callback class to be used with FPDF_SaveWithVersion().
47 struct CompatibleWriter : public FPDF_FILEWRITE
49 CompatibleWriter(SvMemoryStream& rStream)
50 : m_rStream(rStream)
54 SvMemoryStream& m_rStream;
57 int CompatibleWriterCallback(FPDF_FILEWRITE* pFileWrite, const void* pData, unsigned long nSize)
59 auto pImpl = static_cast<CompatibleWriter*>(pFileWrite);
60 pImpl->m_rStream.WriteBytes(pData, nSize);
61 return 1;
65 namespace vcl::pdf
67 OUString convertPdfDateToISO8601(OUString const& rInput)
69 if (rInput.getLength() < 6)
70 return OUString();
72 OUString prefix = rInput.copy(0, 2);
73 if (prefix != "D:")
74 return OUString();
76 OUString sYear = rInput.copy(2, 4);
78 OUString sMonth("01");
79 if (rInput.getLength() >= 8)
80 sMonth = rInput.copy(6, 2);
82 OUString sDay("01");
83 if (rInput.getLength() >= 10)
84 sDay = rInput.copy(8, 2);
86 OUString sHours("00");
87 if (rInput.getLength() >= 12)
88 sHours = rInput.copy(10, 2);
90 OUString sMinutes("00");
91 if (rInput.getLength() >= 14)
92 sMinutes = rInput.copy(12, 2);
94 OUString sSeconds("00");
95 if (rInput.getLength() >= 16)
96 sSeconds = rInput.copy(14, 2);
98 OUString sTimeZoneMark("Z");
99 if (rInput.getLength() >= 17)
100 sTimeZoneMark = rInput.copy(16, 1);
102 OUString sTimeZoneHours("00");
103 OUString sTimeZoneMinutes("00");
104 if ((sTimeZoneMark == "+" || sTimeZoneMark == "-") && rInput.getLength() >= 22)
106 OUString sTimeZoneSeparator = rInput.copy(19, 1);
107 if (sTimeZoneSeparator == "'")
109 sTimeZoneHours = rInput.copy(17, 2);
110 sTimeZoneMinutes = rInput.copy(20, 2);
114 OUString sTimeZoneString;
115 if (sTimeZoneMark == "+" || sTimeZoneString == "-")
116 sTimeZoneString = sTimeZoneMark + sTimeZoneHours + ":" + sTimeZoneMinutes;
117 else if (sTimeZoneMark == "Z")
118 sTimeZoneString = sTimeZoneMark;
120 return sYear + "-" + sMonth + "-" + sDay + "T" + sHours + ":" + sMinutes + ":" + sSeconds
121 + sTimeZoneString;
124 PDFium::PDFium()
126 FPDF_LIBRARY_CONFIG aConfig;
127 aConfig.version = 2;
128 aConfig.m_pUserFontPaths = nullptr;
129 aConfig.m_pIsolate = nullptr;
130 aConfig.m_v8EmbedderSlot = 0;
131 FPDF_InitLibraryWithConfig(&aConfig);
134 PDFium::~PDFium() { FPDF_DestroyLibrary(); }
136 std::unique_ptr<PDFiumDocument> PDFium::openDocument(const void* pData, int nSize)
138 maLastError = OUString();
139 std::unique_ptr<PDFiumDocument> pPDFiumDocument;
141 FPDF_DOCUMENT pDocument = FPDF_LoadMemDocument(pData, nSize, /*password=*/nullptr);
143 if (!pDocument)
145 switch (FPDF_GetLastError())
147 case FPDF_ERR_SUCCESS:
148 maLastError = "Success";
149 break;
150 case FPDF_ERR_UNKNOWN:
151 maLastError = "Unknown error";
152 break;
153 case FPDF_ERR_FILE:
154 maLastError = "File not found";
155 break;
156 case FPDF_ERR_FORMAT:
157 maLastError = "Input is not a PDF format";
158 break;
159 case FPDF_ERR_PASSWORD:
160 maLastError = "Incorrect password or password is required";
161 break;
162 case FPDF_ERR_SECURITY:
163 maLastError = "Security error";
164 break;
165 case FPDF_ERR_PAGE:
166 maLastError = "Content error";
167 break;
168 default:
169 break;
172 else
174 pPDFiumDocument = std::make_unique<PDFiumDocument>(pDocument);
177 return pPDFiumDocument;
180 std::unique_ptr<PDFiumBitmap> PDFium::createBitmap(int nWidth, int nHeight, int nAlpha)
182 std::unique_ptr<PDFiumBitmap> pPDFiumBitmap;
183 FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nWidth, nHeight, nAlpha);
184 if (!pPdfBitmap)
186 maLastError = "Failed to create bitmap";
188 else
190 pPDFiumBitmap = std::make_unique<PDFiumBitmap>(pPdfBitmap);
192 return pPDFiumBitmap;
195 PDFiumSignature::PDFiumSignature(FPDF_SIGNATURE pSignature)
196 : mpSignature(pSignature)
200 PDFiumDocument::PDFiumDocument(FPDF_DOCUMENT pPdfDocument)
201 : mpPdfDocument(pPdfDocument)
202 , m_aFormCallbacks()
204 m_aFormCallbacks.version = 1;
205 m_pFormHandle = std::make_unique<PDFiumFormHandle>(
206 FPDFDOC_InitFormFillEnvironment(pPdfDocument, &m_aFormCallbacks));
209 PDFiumDocument::~PDFiumDocument()
211 m_pFormHandle.reset();
212 if (mpPdfDocument)
213 FPDF_CloseDocument(mpPdfDocument);
216 FPDF_FORMHANDLE PDFiumDocument::getFormHandlePointer() { return m_pFormHandle->getPointer(); }
218 std::unique_ptr<PDFiumPage> PDFiumDocument::openPage(int nIndex)
220 std::unique_ptr<PDFiumPage> pPDFiumPage;
221 FPDF_PAGE pPage = FPDF_LoadPage(mpPdfDocument, nIndex);
222 if (pPage)
224 pPDFiumPage = std::make_unique<PDFiumPage>(pPage);
226 return pPDFiumPage;
229 std::unique_ptr<PDFiumSignature> PDFiumDocument::getSignature(int nIndex)
231 std::unique_ptr<PDFiumSignature> pPDFiumSignature;
232 FPDF_SIGNATURE pSignature = FPDF_GetSignatureObject(mpPdfDocument, nIndex);
233 if (pSignature)
235 pPDFiumSignature = std::make_unique<PDFiumSignature>(pSignature);
237 return pPDFiumSignature;
240 std::vector<unsigned int> PDFiumDocument::getTrailerEnds()
242 int nNumTrailers = FPDF_GetTrailerEnds(mpPdfDocument, nullptr, 0);
243 std::vector<unsigned int> aTrailerEnds(nNumTrailers);
244 FPDF_GetTrailerEnds(mpPdfDocument, aTrailerEnds.data(), aTrailerEnds.size());
245 return aTrailerEnds;
248 basegfx::B2DSize PDFiumDocument::getPageSize(int nIndex)
250 basegfx::B2DSize aSize;
251 FS_SIZEF aPDFSize;
252 if (FPDF_GetPageSizeByIndexF(mpPdfDocument, nIndex, &aPDFSize))
254 aSize = basegfx::B2DSize(aPDFSize.width, aPDFSize.height);
256 return aSize;
259 int PDFiumDocument::getPageCount() { return FPDF_GetPageCount(mpPdfDocument); }
261 int PDFiumDocument::getSignatureCount() { return FPDF_GetSignatureCount(mpPdfDocument); }
263 int PDFiumDocument::getFileVersion()
265 int nFileVersion = 0;
266 FPDF_GetFileVersion(mpPdfDocument, &nFileVersion);
267 return nFileVersion;
270 bool PDFiumDocument::saveWithVersion(SvMemoryStream& rStream, int nFileVersion)
272 CompatibleWriter aWriter(rStream);
273 aWriter.version = 1;
274 aWriter.WriteBlock = &CompatibleWriterCallback;
275 if (!FPDF_SaveWithVersion(mpPdfDocument, &aWriter, 0, nFileVersion))
277 return false;
280 return true;
283 int PDFiumPage::getObjectCount() { return FPDFPage_CountObjects(mpPage); }
285 std::unique_ptr<PDFiumPageObject> PDFiumPage::getObject(int nIndex)
287 std::unique_ptr<PDFiumPageObject> pPDFiumPageObject;
288 FPDF_PAGEOBJECT pPageObject = FPDFPage_GetObject(mpPage, nIndex);
289 if (pPageObject)
291 pPDFiumPageObject = std::make_unique<PDFiumPageObject>(pPageObject);
293 return pPDFiumPageObject;
296 int PDFiumPage::getAnnotationCount() { return FPDFPage_GetAnnotCount(mpPage); }
298 int PDFiumPage::getAnnotationIndex(std::unique_ptr<PDFiumAnnotation> const& rAnnotation)
300 return FPDFPage_GetAnnotIndex(mpPage, rAnnotation->getPointer());
303 std::unique_ptr<PDFiumAnnotation> PDFiumPage::getAnnotation(int nIndex)
305 std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;
306 FPDF_ANNOTATION pAnnotation = FPDFPage_GetAnnot(mpPage, nIndex);
307 if (pAnnotation)
309 pPDFiumAnnotation = std::make_unique<PDFiumAnnotation>(pAnnotation);
311 return pPDFiumAnnotation;
314 std::unique_ptr<PDFiumTextPage> PDFiumPage::getTextPage()
316 std::unique_ptr<PDFiumTextPage> pPDFiumTextPage;
317 FPDF_TEXTPAGE pTextPage = FPDFText_LoadPage(mpPage);
318 if (pTextPage)
320 pPDFiumTextPage = std::make_unique<PDFiumTextPage>(pTextPage);
322 return pPDFiumTextPage;
325 PDFiumPageObject::PDFiumPageObject(FPDF_PAGEOBJECT pPageObject)
326 : mpPageObject(pPageObject)
330 PDFiumPageObject::~PDFiumPageObject() {}
332 OUString PDFiumPageObject::getText(std::unique_ptr<PDFiumTextPage> const& pTextPage)
334 OUString sReturnText;
336 int nBytes = FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), nullptr, 0);
337 assert(nBytes % 2 == 0);
338 nBytes /= 2;
340 std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nBytes]);
342 int nActualBytes
343 = FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), pText.get(), nBytes * 2);
344 assert(nActualBytes % 2 == 0);
345 nActualBytes /= 2;
346 if (nActualBytes > 1)
348 #if defined OSL_BIGENDIAN
349 // The data returned by FPDFTextObj_GetText is documented to always be UTF-16LE:
350 for (int i = 0; i != nActualBytes; ++i)
352 pText[i] = OSL_SWAPWORD(pText[i]);
354 #endif
355 sReturnText = OUString(pText.get());
358 return sReturnText;
361 PDFPageObjectType PDFiumPageObject::getType()
363 return static_cast<PDFPageObjectType>(FPDFPageObj_GetType(mpPageObject));
366 int PDFiumPageObject::getFormObjectCount() { return FPDFFormObj_CountObjects(mpPageObject); }
368 std::unique_ptr<PDFiumPageObject> PDFiumPageObject::getFormObject(int nIndex)
370 std::unique_ptr<PDFiumPageObject> pPDFiumFormObject;
371 FPDF_PAGEOBJECT pFormObject = FPDFFormObj_GetObject(mpPageObject, nIndex);
372 if (pFormObject)
374 pPDFiumFormObject = std::make_unique<PDFiumPageObject>(pFormObject);
376 return pPDFiumFormObject;
379 basegfx::B2DHomMatrix PDFiumPageObject::getMatrix()
381 basegfx::B2DHomMatrix aB2DMatrix;
382 FS_MATRIX matrix;
383 if (FPDFFormObj_GetMatrix(mpPageObject, &matrix))
384 aB2DMatrix = basegfx::B2DHomMatrix::abcdef(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e,
385 matrix.f);
386 return aB2DMatrix;
389 basegfx::B2DRectangle PDFiumPageObject::getBounds()
391 basegfx::B2DRectangle aB2DRectangle;
393 float left = 0;
394 float bottom = 0;
395 float right = 0;
396 float top = 0;
397 if (FPDFPageObj_GetBounds(mpPageObject, &left, &bottom, &right, &top))
399 aB2DRectangle = basegfx::B2DRectangle(left, top, right, bottom);
401 return aB2DRectangle;
404 double PDFiumPageObject::getFontSize() { return FPDFTextObj_GetFontSize(mpPageObject); }
406 OUString PDFiumPageObject::getFontName()
408 OUString sFontName;
409 const int nFontName = 80 + 1;
410 std::unique_ptr<char[]> pFontName(new char[nFontName]); // + terminating null
411 int nFontNameChars = FPDFTextObj_GetFontName(mpPageObject, pFontName.get(), nFontName);
412 if (nFontName >= nFontNameChars)
414 sFontName = OUString::createFromAscii(pFontName.get());
416 return sFontName;
419 int PDFiumPageObject::getTextRenderMode() { return FPDFTextObj_GetTextRenderMode(mpPageObject); }
421 Color PDFiumPageObject::getFillColor()
423 Color aColor = COL_TRANSPARENT;
424 unsigned int nR, nG, nB, nA;
425 if (FPDFPageObj_GetFillColor(mpPageObject, &nR, &nG, &nB, &nA))
427 aColor = Color(0xFF - nA, nR, nG, nB);
429 return aColor;
432 Color PDFiumPageObject::getStrokeColor()
434 Color aColor = COL_TRANSPARENT;
435 unsigned int nR, nG, nB, nA;
436 if (FPDFPageObj_GetStrokeColor(mpPageObject, &nR, &nG, &nB, &nA))
438 aColor = Color(0xFF - nA, nR, nG, nB);
440 return aColor;
443 int PDFiumPageObject::getPathSegmentCount() { return FPDFPath_CountSegments(mpPageObject); }
445 std::unique_ptr<PDFiumPathSegment> PDFiumPageObject::getPathSegment(int index)
447 std::unique_ptr<PDFiumPathSegment> pPDFiumPathSegment;
448 FPDF_PATHSEGMENT pPathSegment = FPDFPath_GetPathSegment(mpPageObject, index);
449 if (pPathSegment)
451 pPDFiumPathSegment = std::make_unique<PDFiumPathSegment>(pPathSegment);
453 return pPDFiumPathSegment;
456 Size PDFiumPageObject::getImageSize(PDFiumPage& rPage)
458 FPDF_IMAGEOBJ_METADATA aMeta;
459 FPDFImageObj_GetImageMetadata(mpPageObject, rPage.getPointer(), &aMeta);
460 return Size(aMeta.width, aMeta.height);
463 std::unique_ptr<PDFiumBitmap> PDFiumPageObject::getImageBitmap()
465 std::unique_ptr<PDFiumBitmap> pPDFiumBitmap;
466 FPDF_BITMAP pBitmap = FPDFImageObj_GetBitmap(mpPageObject);
467 if (pBitmap)
469 pPDFiumBitmap = std::make_unique<PDFiumBitmap>(pBitmap);
471 return pPDFiumBitmap;
474 BitmapChecksum PDFiumPage::getChecksum(int nMDPPerm)
476 size_t nPageWidth = getWidth();
477 size_t nPageHeight = getHeight();
478 auto pPdfBitmap
479 = std::make_unique<PDFiumBitmap>(FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1));
480 if (!pPdfBitmap)
482 return 0;
485 int nFlags = 0;
486 if (nMDPPerm != 3)
488 // Annotations/commenting should affect the checksum, signature verification wants this.
489 nFlags = FPDF_ANNOT;
491 FPDF_RenderPageBitmap(pPdfBitmap->getPointer(), mpPage, /*start_x=*/0, /*start_y=*/0,
492 nPageWidth, nPageHeight,
493 /*rotate=*/0, nFlags);
494 Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24);
496 BitmapScopedWriteAccess pWriteAccess(aBitmap);
497 const auto pPdfBuffer
498 = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap->getPointer()));
499 const int nStride = FPDFBitmap_GetStride(pPdfBitmap->getPointer());
500 for (size_t nRow = 0; nRow < nPageHeight; ++nRow)
502 ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow);
503 pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride);
506 return aBitmap.GetChecksum();
509 double PDFiumPage::getWidth() { return FPDF_GetPageWidth(mpPage); }
511 double PDFiumPage::getHeight() { return FPDF_GetPageHeight(mpPage); }
513 bool PDFiumPage::hasTransparency() { return FPDFPage_HasTransparency(mpPage); }
515 PDFiumPathSegment::PDFiumPathSegment(FPDF_PATHSEGMENT pPathSegment)
516 : mpPathSegment(pPathSegment)
520 PDFiumPathSegment::~PDFiumPathSegment() {}
522 basegfx::B2DPoint PDFiumPathSegment::getPoint() const
524 basegfx::B2DPoint aPoint;
525 float fx, fy;
526 if (FPDFPathSegment_GetPoint(mpPathSegment, &fx, &fy))
527 aPoint = basegfx::B2DPoint(fx, fy);
528 return aPoint;
531 bool PDFiumPathSegment::isClosed() const { return FPDFPathSegment_GetClose(mpPathSegment); }
533 int PDFiumPathSegment::getType() const { return FPDFPathSegment_GetType(mpPathSegment); }
535 PDFiumFormHandle::PDFiumFormHandle(FPDF_FORMHANDLE pHandle)
536 : mpHandle(pHandle)
540 PDFiumFormHandle::~PDFiumFormHandle() { FPDFDOC_ExitFormFillEnvironment(mpHandle); }
542 FPDF_FORMHANDLE PDFiumFormHandle::getPointer() { return mpHandle; }
544 PDFiumBitmap::PDFiumBitmap(FPDF_BITMAP pBitmap)
545 : mpBitmap(pBitmap)
549 PDFiumBitmap::~PDFiumBitmap()
551 if (mpBitmap)
553 FPDFBitmap_Destroy(mpBitmap);
557 void PDFiumBitmap::fillRect(int left, int top, int width, int height, sal_uInt32 nColor)
559 FPDFBitmap_FillRect(mpBitmap, left, top, width, height, nColor);
562 void PDFiumBitmap::renderPageBitmap(PDFiumDocument* pDoc, PDFiumPage* pPage, int nStartX,
563 int nStartY, int nSizeX, int nSizeY)
565 FPDF_RenderPageBitmap(mpBitmap, pPage->getPointer(), nStartX, nStartY, nSizeX, nSizeY,
566 /*rotate=*/0, /*flags=*/0);
568 // Render widget annotations for FormFields.
569 FPDF_FFLDraw(pDoc->getFormHandlePointer(), mpBitmap, pPage->getPointer(), nStartX, nStartY,
570 nSizeX, nSizeY, /*rotate=*/0, /*flags=*/0);
573 ConstScanline PDFiumBitmap::getBuffer()
575 return static_cast<ConstScanline>(FPDFBitmap_GetBuffer(mpBitmap));
578 int PDFiumBitmap::getStride() { return FPDFBitmap_GetStride(mpBitmap); }
580 PDFiumAnnotation::PDFiumAnnotation(FPDF_ANNOTATION pAnnotation)
581 : mpAnnotation(pAnnotation)
585 PDFiumAnnotation::~PDFiumAnnotation()
587 if (mpAnnotation)
588 FPDFPage_CloseAnnot(mpAnnotation);
591 PDFAnnotationSubType PDFiumAnnotation::getSubType()
593 return PDFAnnotationSubType(FPDFAnnot_GetSubtype(mpAnnotation));
596 basegfx::B2DRectangle PDFiumAnnotation::getRectangle()
598 basegfx::B2DRectangle aB2DRectangle;
599 FS_RECTF aRect;
600 if (FPDFAnnot_GetRect(mpAnnotation, &aRect))
602 aB2DRectangle = basegfx::B2DRectangle(aRect.left, aRect.top, aRect.right, aRect.bottom);
604 return aB2DRectangle;
607 Color PDFiumAnnotation::getColor()
609 Color aColor = COL_TRANSPARENT;
610 unsigned int nR, nG, nB, nA;
611 if (FPDFAnnot_GetColor(mpAnnotation, FPDFANNOT_COLORTYPE_Color, &nR, &nG, &nB, &nA))
613 aColor = Color(0xFF - nA, nR, nG, nB);
615 return aColor;
618 Color PDFiumAnnotation::getInteriorColor()
620 Color aColor = COL_TRANSPARENT;
621 unsigned int nR, nG, nB, nA;
622 if (FPDFAnnot_GetColor(mpAnnotation, FPDFANNOT_COLORTYPE_InteriorColor, &nR, &nG, &nB, &nA))
624 aColor = Color(0xFF - nA, nR, nG, nB);
626 return aColor;
629 size_t PDFiumAnnotation::getAttachmentPointsCount()
631 return FPDFAnnot_CountAttachmentPoints(mpAnnotation);
634 std::vector<basegfx::B2DPoint> PDFiumAnnotation::getAttachmentPoints(size_t nIndex)
636 std::vector<basegfx::B2DPoint> aQuads;
638 FS_QUADPOINTSF aQuadpoints;
639 if (FPDFAnnot_GetAttachmentPoints(mpAnnotation, nIndex, &aQuadpoints))
641 aQuads.emplace_back(aQuadpoints.x1, aQuadpoints.y1);
642 aQuads.emplace_back(aQuadpoints.x2, aQuadpoints.y2);
643 aQuads.emplace_back(aQuadpoints.x3, aQuadpoints.y3);
644 aQuads.emplace_back(aQuadpoints.x4, aQuadpoints.y4);
646 return aQuads;
649 std::vector<basegfx::B2DPoint> PDFiumAnnotation::getLineGeometry()
651 std::vector<basegfx::B2DPoint> aLine;
652 FS_POINTF aStart;
653 FS_POINTF aEnd;
654 if (FPDFAnnot_GetLine(mpAnnotation, &aStart, &aEnd))
656 aLine.emplace_back(aStart.x, aStart.y);
657 aLine.emplace_back(aEnd.x, aEnd.y);
659 return aLine;
662 namespace
664 bool getBorderProperties(FPDF_ANNOTATION mpAnnotation, float& rHorizontalCornerRadius,
665 float& rVerticalCornerRadius, float& rBorderWidth)
667 float fHoriRadius = 0.0f;
668 float fVertRadius = 0.0f;
669 float fWidth = 0.0f;
671 if (!FPDFAnnot_GetBorder(mpAnnotation, &fHoriRadius, &fVertRadius, &fWidth))
672 return false;
674 rHorizontalCornerRadius = fHoriRadius;
675 rVerticalCornerRadius = fVertRadius;
676 rBorderWidth = fWidth;
677 return true;
681 float PDFiumAnnotation::getBorderWidth()
683 float fHorizontalCornerRadius;
684 float fVerticalCornerRadius;
685 float fBorderWidth;
687 if (!getBorderProperties(mpAnnotation, fHorizontalCornerRadius, fVerticalCornerRadius,
688 fBorderWidth))
689 return 0.0f;
690 return fBorderWidth;
693 basegfx::B2DSize PDFiumAnnotation::getBorderCornerRadius()
695 float fHorizontalCornerRadius;
696 float fVerticalCornerRadius;
697 float fBorderWidth;
699 if (!getBorderProperties(mpAnnotation, fHorizontalCornerRadius, fVerticalCornerRadius,
700 fBorderWidth))
701 return basegfx::B2DSize(0.0, 0.0);
702 return basegfx::B2DSize(fHorizontalCornerRadius, fVerticalCornerRadius);
705 bool PDFiumAnnotation::hasKey(OString const& rKey)
707 return FPDFAnnot_HasKey(mpAnnotation, rKey.getStr());
710 int PDFiumAnnotation::getValueType(OString const& rKey)
712 return FPDFAnnot_GetValueType(mpAnnotation, rKey.getStr());
715 OUString PDFiumAnnotation::getString(OString const& rKey)
717 OUString rString;
718 unsigned long nSize = FPDFAnnot_GetStringValue(mpAnnotation, rKey.getStr(), nullptr, 0);
719 assert(nSize % 2 == 0);
720 nSize /= 2;
721 if (nSize > 1)
723 std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]);
724 unsigned long nStringSize = FPDFAnnot_GetStringValue(
725 mpAnnotation, rKey.getStr(), reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2);
726 assert(nStringSize % 2 == 0);
727 nStringSize /= 2;
728 if (nStringSize > 0)
730 #if defined OSL_BIGENDIAN
731 // The data returned by FPDFAnnot_GetStringValue is documented to always be UTF-16LE:
732 for (unsigned long i = 0; i != nStringSize; ++i)
734 pText[i] = OSL_SWAPWORD(pText[i]);
736 #endif
737 rString = OUString(pText.get());
740 return rString;
743 std::vector<std::vector<basegfx::B2DPoint>> PDFiumAnnotation::getInkStrokes()
745 std::vector<std::vector<basegfx::B2DPoint>> aB2DPointList;
746 int nInkStrokes = FPDFAnnot_GetInkStrokeCount(mpAnnotation);
747 for (int i = 0; i < nInkStrokes; i++)
749 std::vector<basegfx::B2DPoint> aB2DPoints;
750 int nPoints = FPDFAnnot_GetInkStrokePointCount(mpAnnotation, i);
751 if (nPoints)
753 std::vector<FS_POINTF> aPoints(nPoints);
754 if (FPDFAnnot_GetInkStrokePoints(mpAnnotation, i, aPoints.data()))
756 for (auto const& rPoint : aPoints)
758 aB2DPoints.emplace_back(rPoint.x, rPoint.y);
760 aB2DPointList.push_back(aB2DPoints);
764 return aB2DPointList;
767 std::vector<basegfx::B2DPoint> PDFiumAnnotation::getVertices()
769 std::vector<basegfx::B2DPoint> aB2DPoints;
770 int nPoints = FPDFAnnot_GetVerticesCount(mpAnnotation);
771 if (nPoints)
773 std::vector<FS_POINTF> aPoints(nPoints);
774 if (FPDFAnnot_GetVertices(mpAnnotation, aPoints.data()))
776 for (auto const& rPoint : aPoints)
777 aB2DPoints.emplace_back(rPoint.x, rPoint.y);
780 return aB2DPoints;
783 std::unique_ptr<PDFiumAnnotation> PDFiumAnnotation::getLinked(OString const& rKey)
785 std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;
786 FPDF_ANNOTATION pAnnotation = FPDFAnnot_GetLinkedAnnot(mpAnnotation, rKey.getStr());
787 if (pAnnotation)
789 pPDFiumAnnotation = std::make_unique<PDFiumAnnotation>(pAnnotation);
791 return pPDFiumAnnotation;
794 int PDFiumAnnotation::getObjectCount() { return FPDFAnnot_GetObjectCount(mpAnnotation); }
796 std::unique_ptr<PDFiumPageObject> PDFiumAnnotation::getObject(int nIndex)
798 std::unique_ptr<PDFiumPageObject> pPDFiumPageObject;
799 FPDF_PAGEOBJECT pPageObject = FPDFAnnot_GetObject(mpAnnotation, nIndex);
800 if (pPageObject)
802 pPDFiumPageObject = std::make_unique<PDFiumPageObject>(pPageObject);
804 return pPDFiumPageObject;
807 PDFiumTextPage::PDFiumTextPage(FPDF_TEXTPAGE pTextPage)
808 : mpTextPage(pTextPage)
812 PDFiumTextPage::~PDFiumTextPage()
814 if (mpTextPage)
815 FPDFText_ClosePage(mpTextPage);
818 int PDFiumTextPage::countChars() { return FPDFText_CountChars(mpTextPage); }
820 unsigned int PDFiumTextPage::getUnicode(int index)
822 return FPDFText_GetUnicode(mpTextPage, index);
825 } // end vcl::pdf
827 #endif // HAVE_FEATURE_PDFIUM
829 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */