1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
11 #include <config_features.h>
13 #if HAVE_FEATURE_PDFIUM
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");
46 /// Callback class to be used with FPDF_SaveWithVersion().
47 struct CompatibleWriter
: public FPDF_FILEWRITE
49 CompatibleWriter(SvMemoryStream
& 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
);
67 OUString
convertPdfDateToISO8601(OUString
const& rInput
)
69 if (rInput
.getLength() < 6)
72 OUString prefix
= rInput
.copy(0, 2);
76 OUString sYear
= rInput
.copy(2, 4);
78 OUString
sMonth("01");
79 if (rInput
.getLength() >= 8)
80 sMonth
= rInput
.copy(6, 2);
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
126 FPDF_LIBRARY_CONFIG aConfig
;
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);
145 switch (FPDF_GetLastError())
147 case FPDF_ERR_SUCCESS
:
148 maLastError
= "Success";
150 case FPDF_ERR_UNKNOWN
:
151 maLastError
= "Unknown error";
154 maLastError
= "File not found";
156 case FPDF_ERR_FORMAT
:
157 maLastError
= "Input is not a PDF format";
159 case FPDF_ERR_PASSWORD
:
160 maLastError
= "Incorrect password or password is required";
162 case FPDF_ERR_SECURITY
:
163 maLastError
= "Security error";
166 maLastError
= "Content error";
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
);
186 maLastError
= "Failed to create bitmap";
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
)
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();
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
);
224 pPDFiumPage
= std::make_unique
<PDFiumPage
>(pPage
);
229 std::unique_ptr
<PDFiumSignature
> PDFiumDocument::getSignature(int nIndex
)
231 std::unique_ptr
<PDFiumSignature
> pPDFiumSignature
;
232 FPDF_SIGNATURE pSignature
= FPDF_GetSignatureObject(mpPdfDocument
, nIndex
);
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());
248 basegfx::B2DSize
PDFiumDocument::getPageSize(int nIndex
)
250 basegfx::B2DSize aSize
;
252 if (FPDF_GetPageSizeByIndexF(mpPdfDocument
, nIndex
, &aPDFSize
))
254 aSize
= basegfx::B2DSize(aPDFSize
.width
, aPDFSize
.height
);
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
);
270 bool PDFiumDocument::saveWithVersion(SvMemoryStream
& rStream
, int nFileVersion
)
272 CompatibleWriter
aWriter(rStream
);
274 aWriter
.WriteBlock
= &CompatibleWriterCallback
;
275 if (!FPDF_SaveWithVersion(mpPdfDocument
, &aWriter
, 0, nFileVersion
))
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
);
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
);
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
);
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);
340 std::unique_ptr
<sal_Unicode
[]> pText(new sal_Unicode
[nBytes
]);
343 = FPDFTextObj_GetText(mpPageObject
, pTextPage
->getPointer(), pText
.get(), nBytes
* 2);
344 assert(nActualBytes
% 2 == 0);
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
]);
355 sReturnText
= OUString(pText
.get());
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
);
374 pPDFiumFormObject
= std::make_unique
<PDFiumPageObject
>(pFormObject
);
376 return pPDFiumFormObject
;
379 basegfx::B2DHomMatrix
PDFiumPageObject::getMatrix()
381 basegfx::B2DHomMatrix aB2DMatrix
;
383 if (FPDFFormObj_GetMatrix(mpPageObject
, &matrix
))
384 aB2DMatrix
= basegfx::B2DHomMatrix::abcdef(matrix
.a
, matrix
.b
, matrix
.c
, matrix
.d
, matrix
.e
,
389 basegfx::B2DRectangle
PDFiumPageObject::getBounds()
391 basegfx::B2DRectangle aB2DRectangle
;
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()
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());
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
);
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
);
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
);
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
);
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();
479 = std::make_unique
<PDFiumBitmap
>(FPDFBitmap_Create(nPageWidth
, nPageHeight
, /*alpha=*/1));
488 // Annotations/commenting should affect the checksum, signature verification wants this.
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
;
526 if (FPDFPathSegment_GetPoint(mpPathSegment
, &fx
, &fy
))
527 aPoint
= basegfx::B2DPoint(fx
, fy
);
531 bool PDFiumPathSegment::isClosed() const { return FPDFPathSegment_GetClose(mpPathSegment
); }
533 int PDFiumPathSegment::getType() const { return FPDFPathSegment_GetType(mpPathSegment
); }
535 PDFiumFormHandle::PDFiumFormHandle(FPDF_FORMHANDLE pHandle
)
540 PDFiumFormHandle::~PDFiumFormHandle() { FPDFDOC_ExitFormFillEnvironment(mpHandle
); }
542 FPDF_FORMHANDLE
PDFiumFormHandle::getPointer() { return mpHandle
; }
544 PDFiumBitmap::PDFiumBitmap(FPDF_BITMAP pBitmap
)
549 PDFiumBitmap::~PDFiumBitmap()
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()
588 FPDFPage_CloseAnnot(mpAnnotation
);
591 PDFAnnotationSubType
PDFiumAnnotation::getSubType()
593 return PDFAnnotationSubType(FPDFAnnot_GetSubtype(mpAnnotation
));
596 basegfx::B2DRectangle
PDFiumAnnotation::getRectangle()
598 basegfx::B2DRectangle aB2DRectangle
;
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
);
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
);
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
);
649 std::vector
<basegfx::B2DPoint
> PDFiumAnnotation::getLineGeometry()
651 std::vector
<basegfx::B2DPoint
> aLine
;
654 if (FPDFAnnot_GetLine(mpAnnotation
, &aStart
, &aEnd
))
656 aLine
.emplace_back(aStart
.x
, aStart
.y
);
657 aLine
.emplace_back(aEnd
.x
, aEnd
.y
);
664 bool getBorderProperties(FPDF_ANNOTATION mpAnnotation
, float& rHorizontalCornerRadius
,
665 float& rVerticalCornerRadius
, float& rBorderWidth
)
667 float fHoriRadius
= 0.0f
;
668 float fVertRadius
= 0.0f
;
671 if (!FPDFAnnot_GetBorder(mpAnnotation
, &fHoriRadius
, &fVertRadius
, &fWidth
))
674 rHorizontalCornerRadius
= fHoriRadius
;
675 rVerticalCornerRadius
= fVertRadius
;
676 rBorderWidth
= fWidth
;
681 float PDFiumAnnotation::getBorderWidth()
683 float fHorizontalCornerRadius
;
684 float fVerticalCornerRadius
;
687 if (!getBorderProperties(mpAnnotation
, fHorizontalCornerRadius
, fVerticalCornerRadius
,
693 basegfx::B2DSize
PDFiumAnnotation::getBorderCornerRadius()
695 float fHorizontalCornerRadius
;
696 float fVerticalCornerRadius
;
699 if (!getBorderProperties(mpAnnotation
, fHorizontalCornerRadius
, fVerticalCornerRadius
,
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
)
718 unsigned long nSize
= FPDFAnnot_GetStringValue(mpAnnotation
, rKey
.getStr(), nullptr, 0);
719 assert(nSize
% 2 == 0);
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);
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
]);
737 rString
= OUString(pText
.get());
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
);
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
);
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
);
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());
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
);
802 pPDFiumPageObject
= std::make_unique
<PDFiumPageObject
>(pPageObject
);
804 return pPDFiumPageObject
;
807 PDFiumTextPage::PDFiumTextPage(FPDF_TEXTPAGE pTextPage
)
808 : mpTextPage(pTextPage
)
812 PDFiumTextPage::~PDFiumTextPage()
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
);
827 #endif // HAVE_FEATURE_PDFIUM
829 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */