tdf#143148 Use pragma once instead of include guards
[LibreOffice.git] / vcl / source / pdf / PDFiumLibrary.cxx
blob3eea4a2010fccb484a863dffb43c2a57083d282e
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 <vcl/filter/PDFiumLibrary.hxx>
13 #include <cassert>
15 #include <sal/log.hxx>
16 #include <fpdf_doc.h>
17 #include <fpdf_annot.h>
18 #include <fpdf_edit.h>
19 #include <fpdf_text.h>
20 #include <fpdf_save.h>
21 #include <fpdf_signature.h>
22 #include <fpdf_formfill.h>
23 #include <fpdf_attachment.h>
25 #include <osl/endian.h>
26 #include <vcl/bitmap.hxx>
27 #include <tools/stream.hxx>
28 #include <tools/UnitConversion.hxx>
29 #include <o3tl/string_view.hxx>
30 #include <rtl/ustrbuf.hxx>
32 #include <vcl/BitmapWriteAccess.hxx>
33 #include <vcl/bitmapex.hxx>
34 #include <vcl/dibtools.hxx>
35 #include <functional>
37 using namespace com::sun::star;
39 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Unknown) == FPDF_PAGEOBJ_UNKNOWN,
40 "PDFPageObjectType::Unknown value mismatch");
41 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Text) == FPDF_PAGEOBJ_TEXT,
42 "PDFPageObjectType::Text value mismatch");
43 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Path) == FPDF_PAGEOBJ_PATH,
44 "PDFPageObjectType::Path value mismatch");
45 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Image) == FPDF_PAGEOBJ_IMAGE,
46 "PDFPageObjectType::Image value mismatch");
47 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Shading) == FPDF_PAGEOBJ_SHADING,
48 "PDFPageObjectType::Shading value mismatch");
49 static_assert(static_cast<int>(vcl::pdf::PDFPageObjectType::Form) == FPDF_PAGEOBJ_FORM,
50 "PDFPageObjectType::Form value mismatch");
52 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Unknown) == FPDF_SEGMENT_UNKNOWN,
53 "PDFSegmentType::Unknown value mismatch");
54 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Lineto) == FPDF_SEGMENT_LINETO,
55 "PDFSegmentType::Lineto value mismatch");
56 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Bezierto) == FPDF_SEGMENT_BEZIERTO,
57 "PDFSegmentType::Bezierto value mismatch");
58 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Moveto) == FPDF_SEGMENT_MOVETO,
59 "PDFSegmentType::Moveto value mismatch");
61 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::Unknown) == FPDFBitmap_Unknown,
62 "PDFBitmapType::Unknown value mismatch");
63 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::Gray) == FPDFBitmap_Gray,
64 "PDFBitmapType::Gray value mismatch");
65 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::BGR) == FPDFBitmap_BGR,
66 "PDFBitmapType::BGR value mismatch");
67 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::BGRx) == FPDFBitmap_BGRx,
68 "PDFBitmapType::BGRx value mismatch");
69 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::BGRA) == FPDFBitmap_BGRA,
70 "PDFBitmapType::BGRA value mismatch");
72 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Unknown) == FPDF_OBJECT_UNKNOWN,
73 "PDFObjectType::Unknown value mismatch");
74 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Boolean) == FPDF_OBJECT_BOOLEAN,
75 "PDFObjectType::Boolean value mismatch");
76 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Number) == FPDF_OBJECT_NUMBER,
77 "PDFObjectType::Number value mismatch");
78 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::String) == FPDF_OBJECT_STRING,
79 "PDFObjectType::String value mismatch");
80 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Name) == FPDF_OBJECT_NAME,
81 "PDFObjectType::Name value mismatch");
82 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Array) == FPDF_OBJECT_ARRAY,
83 "PDFObjectType::Array value mismatch");
84 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Dictionary) == FPDF_OBJECT_DICTIONARY,
85 "PDFObjectType::Dictionary value mismatch");
86 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Stream) == FPDF_OBJECT_STREAM,
87 "PDFObjectType::Stream value mismatch");
88 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Nullobj) == FPDF_OBJECT_NULLOBJ,
89 "PDFObjectType::Nullobj value mismatch");
90 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Reference) == FPDF_OBJECT_REFERENCE,
91 "PDFObjectType::Reference value mismatch");
93 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Unknown) == FPDF_TEXTRENDERMODE_UNKNOWN,
94 "PDFTextRenderMode::Unknown value mismatch");
95 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Fill) == FPDF_TEXTRENDERMODE_FILL,
96 "PDFTextRenderMode::Fill value mismatch");
97 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Stroke) == FPDF_TEXTRENDERMODE_STROKE,
98 "PDFTextRenderMode::Stroke value mismatch");
99 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::FillStroke)
100 == FPDF_TEXTRENDERMODE_FILL_STROKE,
101 "PDFTextRenderMode::FillStroke value mismatch");
102 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Invisible)
103 == FPDF_TEXTRENDERMODE_INVISIBLE,
104 "PDFTextRenderMode::Invisible value mismatch");
105 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::FillClip)
106 == FPDF_TEXTRENDERMODE_FILL_CLIP,
107 "PDFTextRenderMode::FillClip value mismatch");
108 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::StrokeClip)
109 == FPDF_TEXTRENDERMODE_STROKE_CLIP,
110 "PDFTextRenderMode::StrokeClip value mismatch");
111 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::FillStrokeClip)
112 == FPDF_TEXTRENDERMODE_FILL_STROKE_CLIP,
113 "PDFTextRenderMode::FillStrokeClip value mismatch");
114 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Clip) == FPDF_TEXTRENDERMODE_CLIP,
115 "PDFTextRenderMode::Clip value mismatch");
117 static_assert(static_cast<int>(vcl::pdf::PDFFillMode::None) == FPDF_FILLMODE_NONE,
118 "PDFFillMode::None value mismatch");
119 static_assert(static_cast<int>(vcl::pdf::PDFFillMode::Alternate) == FPDF_FILLMODE_ALTERNATE,
120 "PDFFillMode::Alternate value mismatch");
121 static_assert(static_cast<int>(vcl::pdf::PDFFillMode::Winding) == FPDF_FILLMODE_WINDING,
122 "PDFFillMode::Winding value mismatch");
124 static_assert(static_cast<int>(vcl::pdf::PDFFindFlags::MatchCase) == FPDF_MATCHCASE,
125 "PDFFindFlags::MatchCase value mismatch");
126 static_assert(static_cast<int>(vcl::pdf::PDFFindFlags::MatchWholeWord) == FPDF_MATCHWHOLEWORD,
127 "PDFFindFlags::MatchWholeWord value mismatch");
128 static_assert(static_cast<int>(vcl::pdf::PDFFindFlags::Consecutive) == FPDF_CONSECUTIVE,
129 "PDFFindFlags::Consecutive value mismatch");
131 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Success) == FPDF_ERR_SUCCESS,
132 "PDFErrorType::Success value mismatch");
133 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Unknown) == FPDF_ERR_UNKNOWN,
134 "PDFErrorType::Unknown value mismatch");
135 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::File) == FPDF_ERR_FILE,
136 "PDFErrorType::File value mismatch");
137 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Format) == FPDF_ERR_FORMAT,
138 "PDFErrorType::Format value mismatch");
139 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Password) == FPDF_ERR_PASSWORD,
140 "PDFErrorType::Password value mismatch");
141 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Security) == FPDF_ERR_SECURITY,
142 "PDFErrorType::Security value mismatch");
143 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Page) == FPDF_ERR_PAGE,
144 "PDFErrorType::Page value mismatch");
146 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::Unknown) == FPDF_FORMFIELD_UNKNOWN,
147 "PDFFormFieldType::Unknown value mismatch");
148 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::PushButton) == FPDF_FORMFIELD_PUSHBUTTON,
149 "PDFFormFieldType::PushButton value mismatch");
150 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::CheckBox) == FPDF_FORMFIELD_CHECKBOX,
151 "PDFFormFieldType::CheckBox value mismatch");
152 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::RadioButton)
153 == FPDF_FORMFIELD_RADIOBUTTON,
154 "PDFFormFieldType::RadioButton value mismatch");
155 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::ComboBox) == FPDF_FORMFIELD_COMBOBOX,
156 "PDFFormFieldType::ComboBox value mismatch");
157 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::ListBox) == FPDF_FORMFIELD_LISTBOX,
158 "PDFFormFieldType::ListBox value mismatch");
159 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::TextField) == FPDF_FORMFIELD_TEXTFIELD,
160 "PDFFormFieldType::TextField value mismatch");
161 static_assert(static_cast<int>(vcl::pdf::PDFFormFieldType::Signature) == FPDF_FORMFIELD_SIGNATURE,
162 "PDFFormFieldType::Signature value mismatch");
164 static_assert(static_cast<int>(vcl::pdf::PDFAnnotAActionType::KeyStroke)
165 == FPDF_ANNOT_AACTION_KEY_STROKE,
166 "PDFAnnotAActionType::KeyStroke) value mismatch");
167 static_assert(static_cast<int>(vcl::pdf::PDFAnnotAActionType::Format) == FPDF_ANNOT_AACTION_FORMAT,
168 "PDFAnnotAActionType::Format) value mismatch");
169 static_assert(static_cast<int>(vcl::pdf::PDFAnnotAActionType::Validate)
170 == FPDF_ANNOT_AACTION_VALIDATE,
171 "PDFAnnotAActionType::Validate) value mismatch");
172 static_assert(static_cast<int>(vcl::pdf::PDFAnnotAActionType::Calculate)
173 == FPDF_ANNOT_AACTION_CALCULATE,
174 "PDFAnnotAActionType::Calculate) value mismatch");
176 static_assert(int(vcl::pdf::PDFAnnotationSubType::Unknown) == FPDF_ANNOT_UNKNOWN);
177 static_assert(int(vcl::pdf::PDFAnnotationSubType::Text) == FPDF_ANNOT_TEXT);
178 static_assert(int(vcl::pdf::PDFAnnotationSubType::Link) == FPDF_ANNOT_LINK);
179 static_assert(int(vcl::pdf::PDFAnnotationSubType::FreeText) == FPDF_ANNOT_FREETEXT);
180 static_assert(int(vcl::pdf::PDFAnnotationSubType::Line) == FPDF_ANNOT_LINE);
181 static_assert(int(vcl::pdf::PDFAnnotationSubType::Square) == FPDF_ANNOT_SQUARE);
182 static_assert(int(vcl::pdf::PDFAnnotationSubType::Circle) == FPDF_ANNOT_CIRCLE);
183 static_assert(int(vcl::pdf::PDFAnnotationSubType::Polygon) == FPDF_ANNOT_POLYGON);
184 static_assert(int(vcl::pdf::PDFAnnotationSubType::Polyline) == FPDF_ANNOT_POLYLINE);
185 static_assert(int(vcl::pdf::PDFAnnotationSubType::Highlight) == FPDF_ANNOT_HIGHLIGHT);
186 static_assert(int(vcl::pdf::PDFAnnotationSubType::Underline) == FPDF_ANNOT_UNDERLINE);
187 static_assert(int(vcl::pdf::PDFAnnotationSubType::Squiggly) == FPDF_ANNOT_SQUIGGLY);
188 static_assert(int(vcl::pdf::PDFAnnotationSubType::Strikeout) == FPDF_ANNOT_STRIKEOUT);
189 static_assert(int(vcl::pdf::PDFAnnotationSubType::Stamp) == FPDF_ANNOT_STAMP);
190 static_assert(int(vcl::pdf::PDFAnnotationSubType::Caret) == FPDF_ANNOT_CARET);
191 static_assert(int(vcl::pdf::PDFAnnotationSubType::Ink) == FPDF_ANNOT_INK);
192 static_assert(int(vcl::pdf::PDFAnnotationSubType::Popup) == FPDF_ANNOT_POPUP);
193 static_assert(int(vcl::pdf::PDFAnnotationSubType::FileAttachment) == FPDF_ANNOT_FILEATTACHMENT);
194 static_assert(int(vcl::pdf::PDFAnnotationSubType::Sound) == FPDF_ANNOT_SOUND);
195 static_assert(int(vcl::pdf::PDFAnnotationSubType::Movie) == FPDF_ANNOT_MOVIE);
196 static_assert(int(vcl::pdf::PDFAnnotationSubType::Widget) == FPDF_ANNOT_WIDGET);
197 static_assert(int(vcl::pdf::PDFAnnotationSubType::Screen) == FPDF_ANNOT_SCREEN);
198 static_assert(int(vcl::pdf::PDFAnnotationSubType::Printermark) == FPDF_ANNOT_PRINTERMARK);
199 static_assert(int(vcl::pdf::PDFAnnotationSubType::Trapnet) == FPDF_ANNOT_TRAPNET);
200 static_assert(int(vcl::pdf::PDFAnnotationSubType::Watermark) == FPDF_ANNOT_WATERMARK);
201 static_assert(int(vcl::pdf::PDFAnnotationSubType::Threed) == FPDF_ANNOT_THREED);
202 static_assert(int(vcl::pdf::PDFAnnotationSubType::Richmedia) == FPDF_ANNOT_RICHMEDIA);
203 static_assert(int(vcl::pdf::PDFAnnotationSubType::XFAWidget) == FPDF_ANNOT_XFAWIDGET);
204 static_assert(int(vcl::pdf::PDFAnnotationSubType::Redact) == FPDF_ANNOT_REDACT);
206 namespace
208 /// Callback class to be used with FPDF_SaveWithVersion().
209 struct CompatibleWriter : public FPDF_FILEWRITE
211 CompatibleWriter(SvMemoryStream& rStream)
212 : m_rStream(rStream)
216 SvMemoryStream& m_rStream;
219 int CompatibleWriterCallback(FPDF_FILEWRITE* pFileWrite, const void* pData, unsigned long nSize)
221 auto pImpl = static_cast<CompatibleWriter*>(pFileWrite);
222 pImpl->m_rStream.WriteBytes(pData, nSize);
223 return 1;
226 OUString getUnicodeString(std::function<int(FPDF_WCHAR*, unsigned long)> aPDFiumFunctionCall)
228 OUString sReturnText;
230 int nBytes = aPDFiumFunctionCall(nullptr, 0);
231 if (nBytes == 0)
232 return sReturnText;
233 assert(nBytes % 2 == 0);
234 nBytes /= 2;
236 std::vector<sal_Unicode> pText(nBytes, 0);
238 int nActualBytes = aPDFiumFunctionCall(reinterpret_cast<FPDF_WCHAR*>(pText.data()), nBytes * 2);
239 assert(nActualBytes % 2 == 0);
240 nActualBytes /= 2;
241 if (nActualBytes > 1)
243 #ifdef OSL_BIGENDIAN
244 for (int i = 0; i != nActualBytes; ++i)
246 pText[i] = OSL_SWAPWORD(pText[i]);
248 #endif
249 sReturnText = OUString(pText.data());
252 return sReturnText;
256 namespace vcl::pdf
258 namespace
260 class PDFiumBitmapImpl final : public PDFiumBitmap
262 private:
263 FPDF_BITMAP mpBitmap;
265 PDFiumBitmapImpl(const PDFiumBitmapImpl&) = delete;
266 PDFiumBitmapImpl& operator=(const PDFiumBitmapImpl&) = delete;
268 public:
269 PDFiumBitmapImpl(FPDF_BITMAP pBitmap);
270 ~PDFiumBitmapImpl() override;
271 FPDF_BITMAP getPointer() { return mpBitmap; }
273 void fillRect(int left, int top, int width, int height, sal_uInt32 nColor) override;
274 void renderPageBitmap(PDFiumDocument* pDoc, PDFiumPage* pPage, int nStartX, int nStartY,
275 int nSizeX, int nSizeY) override;
276 ConstScanline getBuffer() override;
277 int getStride() override;
278 int getWidth() override;
279 int getHeight() override;
280 PDFBitmapType getFormat() override;
281 BitmapEx createBitmapFromBuffer() override;
284 class PDFiumPathSegmentImpl final : public PDFiumPathSegment
286 private:
287 FPDF_PATHSEGMENT mpPathSegment;
289 PDFiumPathSegmentImpl(const PDFiumPathSegmentImpl&) = delete;
290 PDFiumPathSegmentImpl& operator=(const PDFiumPathSegmentImpl&) = delete;
292 public:
293 PDFiumPathSegmentImpl(FPDF_PATHSEGMENT pPathSegment);
295 basegfx::B2DPoint getPoint() const override;
296 bool isClosed() const override;
297 PDFSegmentType getType() const override;
300 class PDFiumAnnotationImpl final : public PDFiumAnnotation
302 private:
303 FPDF_ANNOTATION mpAnnotation;
305 PDFiumAnnotationImpl(const PDFiumAnnotationImpl&) = delete;
306 PDFiumAnnotationImpl& operator=(const PDFiumAnnotationImpl&) = delete;
308 public:
309 PDFiumAnnotationImpl(FPDF_ANNOTATION pAnnotation);
310 ~PDFiumAnnotationImpl();
311 FPDF_ANNOTATION getPointer() { return mpAnnotation; }
313 PDFAnnotationSubType getSubType() override;
314 basegfx::B2DRectangle getRectangle() override;
315 bool hasKey(OString const& rKey) override;
316 PDFObjectType getValueType(OString const& rKey) override;
317 OUString getString(OString const& rKey) override;
318 std::unique_ptr<PDFiumAnnotation> getLinked(OString const& rKey) override;
319 int getObjectCount() override;
320 std::unique_ptr<PDFiumPageObject> getObject(int nIndex) override;
321 std::vector<std::vector<basegfx::B2DPoint>> getInkStrokes() override;
322 std::vector<basegfx::B2DPoint> getVertices() override;
323 Color getColor() override;
324 Color getInteriorColor() override;
325 float getBorderWidth() override;
326 basegfx::B2DSize getBorderCornerRadius() override;
327 size_t getAttachmentPointsCount() override;
328 std::vector<basegfx::B2DPoint> getAttachmentPoints(size_t nIndex) override;
329 std::vector<basegfx::B2DPoint> getLineGeometry() override;
330 PDFFormFieldType getFormFieldType(PDFiumDocument* pDoc) override;
331 float getFontSize(PDFiumDocument* pDoc) override;
332 Color getFontColor(PDFiumDocument* pDoc) override;
333 OUString getFormFieldAlternateName(PDFiumDocument* pDoc) override;
334 int getFormFieldFlags(PDFiumDocument* pDoc) override;
335 OUString getFormAdditionalActionJavaScript(PDFiumDocument* pDoc,
336 PDFAnnotAActionType eEvent) override;
337 OUString getFormFieldValue(PDFiumDocument* pDoc) override;
338 int getOptionCount(PDFiumDocument* pDoc) override;
341 class PDFiumPageObjectImpl final : public PDFiumPageObject
343 private:
344 FPDF_PAGEOBJECT mpPageObject;
346 PDFiumPageObjectImpl(const PDFiumPageObjectImpl&) = delete;
347 PDFiumPageObjectImpl& operator=(const PDFiumPageObjectImpl&) = delete;
349 public:
350 PDFiumPageObjectImpl(FPDF_PAGEOBJECT pPageObject);
352 PDFPageObjectType getType() override;
353 OUString getText(std::unique_ptr<PDFiumTextPage> const& pTextPage) override;
355 int getFormObjectCount() override;
356 std::unique_ptr<PDFiumPageObject> getFormObject(int nIndex) override;
358 basegfx::B2DHomMatrix getMatrix() override;
359 basegfx::B2DRectangle getBounds() override;
360 double getFontSize() override;
361 OUString getFontName() override;
362 PDFTextRenderMode getTextRenderMode() override;
363 Color getFillColor() override;
364 Color getStrokeColor() override;
365 double getStrokeWidth() override;
366 // Path
367 int getPathSegmentCount() override;
368 std::unique_ptr<PDFiumPathSegment> getPathSegment(int index) override;
369 Size getImageSize(PDFiumPage& rPage) override;
370 std::unique_ptr<PDFiumBitmap> getImageBitmap() override;
371 bool getDrawMode(PDFFillMode& eFillMode, bool& bStroke) override;
374 class PDFiumSearchHandleImpl final : public PDFiumSearchHandle
376 private:
377 FPDF_SCHHANDLE mpSearchHandle;
379 PDFiumSearchHandleImpl(const PDFiumSearchHandleImpl&) = delete;
380 PDFiumSearchHandleImpl& operator=(const PDFiumSearchHandleImpl&) = delete;
382 public:
383 PDFiumSearchHandleImpl(FPDF_SCHHANDLE pSearchHandle);
384 ~PDFiumSearchHandleImpl();
386 bool findNext() override;
387 bool findPrev() override;
388 int getSearchResultIndex() override;
389 int getSearchCount() override;
392 class PDFiumTextPageImpl final : public PDFiumTextPage
394 private:
395 FPDF_TEXTPAGE mpTextPage;
397 PDFiumTextPageImpl(const PDFiumTextPageImpl&) = delete;
398 PDFiumTextPageImpl& operator=(const PDFiumTextPageImpl&) = delete;
400 public:
401 PDFiumTextPageImpl(FPDF_TEXTPAGE pTextPage);
402 ~PDFiumTextPageImpl();
404 FPDF_TEXTPAGE getPointer() { return mpTextPage; }
406 int countChars() override;
407 unsigned int getUnicode(int index) override;
408 std::unique_ptr<PDFiumSearchHandle> findStart(const OUString& rFindWhat, PDFFindFlags nFlags,
409 sal_Int32 nStartIndex) override;
411 /// Returned rect is no longer upside down and is in mm100.
412 basegfx::B2DRectangle getCharBox(int nIndex, double fPageHeight) override;
415 class PDFiumSignatureImpl final : public PDFiumSignature
417 private:
418 FPDF_SIGNATURE mpSignature;
419 PDFiumSignatureImpl(const PDFiumSignatureImpl&) = delete;
420 PDFiumSignatureImpl& operator=(const PDFiumSignatureImpl&) = delete;
422 public:
423 PDFiumSignatureImpl(FPDF_SIGNATURE pSignature);
425 std::vector<int> getByteRange() override;
426 int getDocMDPPermission() override;
427 std::vector<unsigned char> getContents() override;
428 OString getSubFilter() override;
429 OUString getReason() override;
430 css::util::DateTime getTime() override;
433 class PDFiumPageImpl final : public PDFiumPage
435 private:
436 FPDF_PAGE mpPage;
438 private:
439 PDFiumPageImpl(const PDFiumPageImpl&) = delete;
440 PDFiumPageImpl& operator=(const PDFiumPageImpl&) = delete;
442 public:
443 PDFiumPageImpl(FPDF_PAGE pPage)
444 : mpPage(pPage)
448 ~PDFiumPageImpl() override
450 if (mpPage)
451 FPDF_ClosePage(mpPage);
454 FPDF_PAGE getPointer() { return mpPage; }
456 int getObjectCount() override;
457 std::unique_ptr<PDFiumPageObject> getObject(int nIndex) override;
459 int getAnnotationCount() override;
460 int getAnnotationIndex(std::unique_ptr<PDFiumAnnotation> const& rAnnotation) override;
462 std::unique_ptr<PDFiumAnnotation> getAnnotation(int nIndex) override;
464 std::unique_ptr<PDFiumTextPage> getTextPage() override;
466 BitmapChecksum getChecksum(int nMDPPerm) override;
468 double getWidth() override;
469 double getHeight() override;
471 bool hasTransparency() override;
473 bool hasLinks() override;
475 void onAfterLoadPage(PDFiumDocument* pDoc) override;
478 /// Wrapper around FPDF_FORMHANDLE.
479 class PDFiumFormHandle final
481 private:
482 FPDF_FORMHANDLE mpHandle;
484 PDFiumFormHandle(const PDFiumFormHandle&) = delete;
485 PDFiumFormHandle& operator=(const PDFiumFormHandle&) = delete;
487 public:
488 PDFiumFormHandle(FPDF_FORMHANDLE pHandle);
489 ~PDFiumFormHandle();
490 FPDF_FORMHANDLE getPointer();
493 class PDFiumAttachmentImpl final : public PDFiumAttachment
495 private:
496 FPDF_ATTACHMENT mpAttachment;
497 PDFiumAttachmentImpl(const PDFiumSignatureImpl&) = delete;
498 PDFiumAttachmentImpl& operator=(const PDFiumSignatureImpl&) = delete;
500 public:
501 PDFiumAttachmentImpl(FPDF_ATTACHMENT pAttachment)
502 : mpAttachment(pAttachment)
506 OUString getName() override;
507 bool getFile(std::vector<unsigned char>& rOutBuffer) override;
510 class PDFiumDocumentImpl : public PDFiumDocument
512 private:
513 FPDF_DOCUMENT mpPdfDocument;
514 FPDF_FORMFILLINFO m_aFormCallbacks;
515 std::unique_ptr<PDFiumFormHandle> m_pFormHandle;
517 private:
518 PDFiumDocumentImpl(const PDFiumDocumentImpl&) = delete;
519 PDFiumDocumentImpl& operator=(const PDFiumDocumentImpl&) = delete;
521 public:
522 PDFiumDocumentImpl(FPDF_DOCUMENT pPdfDocument);
523 ~PDFiumDocumentImpl() override;
524 FPDF_FORMHANDLE getFormHandlePointer();
526 // Page size in points
527 basegfx::B2DSize getPageSize(int nIndex) override;
528 int getPageCount() override;
529 int getSignatureCount() override;
530 int getAttachmentCount() override;
531 int getFileVersion() override;
532 bool saveWithVersion(SvMemoryStream& rStream, int nFileVersion) override;
534 std::unique_ptr<PDFiumPage> openPage(int nIndex) override;
535 std::unique_ptr<PDFiumSignature> getSignature(int nIndex) override;
536 std::unique_ptr<PDFiumAttachment> getAttachment(int nIndex) override;
537 std::vector<unsigned int> getTrailerEnds() override;
538 OUString getBookmarks() override;
541 class PDFiumImpl : public PDFium
543 private:
544 PDFiumImpl(const PDFiumImpl&) = delete;
545 PDFiumImpl& operator=(const PDFiumImpl&) = delete;
547 OUString maLastError;
548 void setLastError(OUString const& rErrorString);
550 public:
551 PDFiumImpl();
552 ~PDFiumImpl() override;
554 const OUString& getLastError() const override { return maLastError; }
556 std::unique_ptr<PDFiumDocument> openDocument(const void* pData, int nSize,
557 const OString& rPassword) override;
558 PDFErrorType getLastErrorCode() override;
559 /// @brief creates bitmap, can reduce size if needed, check nWidth and nHeight
560 std::unique_ptr<PDFiumBitmap> createBitmap(int& nWidth, int& nHeight, int nAlpha) override;
564 PDFiumImpl::PDFiumImpl()
566 FPDF_LIBRARY_CONFIG aConfig;
567 aConfig.version = 2;
568 aConfig.m_pUserFontPaths = nullptr;
569 aConfig.m_pIsolate = nullptr;
570 aConfig.m_v8EmbedderSlot = 0;
571 FPDF_InitLibraryWithConfig(&aConfig);
574 PDFiumImpl::~PDFiumImpl() { FPDF_DestroyLibrary(); }
576 void PDFiumImpl::setLastError(OUString const& rErrorString)
578 if (!rErrorString.isEmpty())
580 // Report what error was set (useful in test failures)
581 SAL_WARN("vcl.filter", "PDFiumImpl Error: '" << rErrorString << "' Error number: "
582 << sal_Int32(getLastErrorCode()));
584 maLastError = rErrorString;
587 std::unique_ptr<PDFiumDocument> PDFiumImpl::openDocument(const void* pData, int nSize,
588 const OString& rPassword)
590 setLastError(u""_ustr);
591 std::unique_ptr<PDFiumDocument> pPDFiumDocument;
593 FPDF_BYTESTRING pPassword = nullptr;
594 if (!rPassword.isEmpty())
596 pPassword = rPassword.getStr();
598 FPDF_DOCUMENT pDocument = FPDF_LoadMemDocument(pData, nSize, pPassword);
600 if (!pDocument)
602 switch (FPDF_GetLastError())
604 case FPDF_ERR_SUCCESS:
605 setLastError(u"Success"_ustr);
606 break;
607 case FPDF_ERR_UNKNOWN:
608 setLastError(u"Unknown error"_ustr);
609 break;
610 case FPDF_ERR_FILE:
611 setLastError(u"File not found"_ustr);
612 break;
613 case FPDF_ERR_FORMAT:
614 setLastError(u"Input is not a PDF format"_ustr);
615 break;
616 case FPDF_ERR_PASSWORD:
617 setLastError(u"Incorrect password or password is required"_ustr);
618 break;
619 case FPDF_ERR_SECURITY:
620 setLastError(u"Security error"_ustr);
621 break;
622 case FPDF_ERR_PAGE:
623 setLastError(u"Content error"_ustr);
624 break;
625 default:
626 setLastError(u"Unknown error number"_ustr);
627 break;
630 else
632 pPDFiumDocument = std::make_unique<PDFiumDocumentImpl>(pDocument);
635 return pPDFiumDocument;
638 PDFErrorType PDFiumImpl::getLastErrorCode()
640 return static_cast<PDFErrorType>(FPDF_GetLastError());
643 std::unique_ptr<PDFiumBitmap> PDFiumImpl::createBitmap(int& nWidth, int& nHeight, int nAlpha)
645 std::unique_ptr<PDFiumBitmap> pPDFiumBitmap;
647 FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nWidth, nHeight, nAlpha);
648 if (!pPdfBitmap)
650 int nOriginal = nHeight;
651 // PDFium cannot create big bitmaps, max 2^14 x 2^14 x 4 bytes per pixel
652 if (nHeight > 16384)
653 nHeight = 16384;
655 if (nWidth > 16384)
657 nWidth = 16384.0 / nOriginal * nWidth;
660 if (nWidth * nHeight > 16384 * 16384)
662 nOriginal = nWidth;
663 nHeight = 16384.0 / nOriginal * nHeight;
666 pPdfBitmap = FPDFBitmap_Create(nWidth, nHeight, nAlpha);
669 if (!pPdfBitmap)
671 setLastError(u"Failed to create bitmap"_ustr);
673 else
675 pPDFiumBitmap = std::make_unique<PDFiumBitmapImpl>(pPdfBitmap);
677 return pPDFiumBitmap;
680 PDFiumSignatureImpl::PDFiumSignatureImpl(FPDF_SIGNATURE pSignature)
681 : mpSignature(pSignature)
685 std::vector<int> PDFiumSignatureImpl::getByteRange()
687 int nByteRangeLen = FPDFSignatureObj_GetByteRange(mpSignature, nullptr, 0);
688 std::vector<int> aByteRange(nByteRangeLen);
689 if (nByteRangeLen <= 0)
691 return aByteRange;
694 FPDFSignatureObj_GetByteRange(mpSignature, aByteRange.data(), aByteRange.size());
695 return aByteRange;
698 int PDFiumSignatureImpl::getDocMDPPermission()
700 return FPDFSignatureObj_GetDocMDPPermission(mpSignature);
703 std::vector<unsigned char> PDFiumSignatureImpl::getContents()
705 int nContentsLen = FPDFSignatureObj_GetContents(mpSignature, nullptr, 0);
706 std::vector<unsigned char> aContents(nContentsLen);
707 if (aContents.empty())
709 return aContents;
712 FPDFSignatureObj_GetContents(mpSignature, aContents.data(), aContents.size());
713 return aContents;
716 OString PDFiumSignatureImpl::getSubFilter()
718 int nSubFilterLen = FPDFSignatureObj_GetSubFilter(mpSignature, nullptr, 0);
719 std::vector<char> aSubFilterBuf(nSubFilterLen);
720 FPDFSignatureObj_GetSubFilter(mpSignature, aSubFilterBuf.data(), aSubFilterBuf.size());
721 // Buffer is NUL-terminated.
722 OString aSubFilter(aSubFilterBuf.data(), aSubFilterBuf.size() - 1);
723 return aSubFilter;
726 OUString PDFiumSignatureImpl::getReason()
728 int nReasonLen = FPDFSignatureObj_GetReason(mpSignature, nullptr, 0);
729 OUString aRet;
730 if (nReasonLen > 0)
732 std::vector<char16_t> aReasonBuf(nReasonLen);
733 FPDFSignatureObj_GetReason(mpSignature, aReasonBuf.data(), aReasonBuf.size());
734 aRet = OUString(aReasonBuf.data(), aReasonBuf.size() - 1);
737 return aRet;
740 util::DateTime PDFiumSignatureImpl::getTime()
742 util::DateTime aRet;
743 int nTimeLen = FPDFSignatureObj_GetTime(mpSignature, nullptr, 0);
744 if (nTimeLen <= 0)
746 return aRet;
749 // Example: "D:20161027100104".
750 std::vector<char> aTimeBuf(nTimeLen);
751 FPDFSignatureObj_GetTime(mpSignature, aTimeBuf.data(), aTimeBuf.size());
752 OString aM(aTimeBuf.data(), aTimeBuf.size() - 1);
753 if (aM.startsWith("D:") && aM.getLength() >= 16)
755 aRet.Year = o3tl::toInt32(aM.subView(2, 4));
756 aRet.Month = o3tl::toInt32(aM.subView(6, 2));
757 aRet.Day = o3tl::toInt32(aM.subView(8, 2));
758 aRet.Hours = o3tl::toInt32(aM.subView(10, 2));
759 aRet.Minutes = o3tl::toInt32(aM.subView(12, 2));
760 aRet.Seconds = o3tl::toInt32(aM.subView(14, 2));
762 return aRet;
765 OUString PDFiumAttachmentImpl::getName()
767 return getUnicodeString([this](FPDF_WCHAR* buffer, unsigned long length) {
768 return FPDFAttachment_GetName(mpAttachment, buffer, length);
772 bool PDFiumAttachmentImpl::getFile(std::vector<unsigned char>& rOutBuffer)
774 rOutBuffer.clear();
776 unsigned long nLength{};
777 if (!FPDFAttachment_GetFile(mpAttachment, nullptr, 0, &nLength))
778 return false;
780 rOutBuffer.resize(nLength);
781 unsigned long nActualLength{};
782 if (!FPDFAttachment_GetFile(mpAttachment, rOutBuffer.data(), nLength, &nActualLength))
783 return false;
784 rOutBuffer.resize(nActualLength);
785 return true;
788 PDFiumDocumentImpl::PDFiumDocumentImpl(FPDF_DOCUMENT pPdfDocument)
789 : mpPdfDocument(pPdfDocument)
790 , m_aFormCallbacks()
792 m_aFormCallbacks.version = 1;
793 m_pFormHandle = std::make_unique<PDFiumFormHandle>(
794 FPDFDOC_InitFormFillEnvironment(pPdfDocument, &m_aFormCallbacks));
797 PDFiumDocumentImpl::~PDFiumDocumentImpl()
799 m_pFormHandle.reset();
800 if (mpPdfDocument)
801 FPDF_CloseDocument(mpPdfDocument);
804 FPDF_FORMHANDLE PDFiumDocumentImpl::getFormHandlePointer() { return m_pFormHandle->getPointer(); }
806 std::unique_ptr<PDFiumPage> PDFiumDocumentImpl::openPage(int nIndex)
808 std::unique_ptr<PDFiumPage> pPDFiumPage;
809 FPDF_PAGE pPage = FPDF_LoadPage(mpPdfDocument, nIndex);
810 if (pPage)
812 pPDFiumPage = std::make_unique<PDFiumPageImpl>(pPage);
814 return pPDFiumPage;
817 std::unique_ptr<PDFiumSignature> PDFiumDocumentImpl::getSignature(int nIndex)
819 std::unique_ptr<PDFiumSignature> pPDFiumSignature;
820 FPDF_SIGNATURE pSignature = FPDF_GetSignatureObject(mpPdfDocument, nIndex);
821 if (pSignature)
823 pPDFiumSignature = std::make_unique<PDFiumSignatureImpl>(pSignature);
825 return pPDFiumSignature;
828 std::unique_ptr<PDFiumAttachment> PDFiumDocumentImpl::getAttachment(int nIndex)
830 std::unique_ptr<PDFiumAttachment> pPDFiumAttachment;
831 FPDF_ATTACHMENT pAttachment = FPDFDoc_GetAttachment(mpPdfDocument, nIndex);
832 if (pAttachment)
834 pPDFiumAttachment = std::make_unique<PDFiumAttachmentImpl>(pAttachment);
836 return pPDFiumAttachment;
839 std::vector<unsigned int> PDFiumDocumentImpl::getTrailerEnds()
841 int nNumTrailers = FPDF_GetTrailerEnds(mpPdfDocument, nullptr, 0);
842 std::vector<unsigned int> aTrailerEnds(nNumTrailers);
843 FPDF_GetTrailerEnds(mpPdfDocument, aTrailerEnds.data(), aTrailerEnds.size());
844 return aTrailerEnds;
847 static void lcl_getBookmarks(int nLevel, OUStringBuffer& rBuf, FPDF_DOCUMENT pDoc,
848 FPDF_BOOKMARK pBookmark)
850 // no first child or too much levels
851 if (!pBookmark || nLevel > 10)
852 return;
854 OUString aString;
855 int nBytes = FPDFBookmark_GetTitle(pBookmark, nullptr, 0);
856 assert(nBytes % 2 == 0);
857 nBytes /= 2;
859 std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nBytes]);
861 int nActualBytes = FPDFBookmark_GetTitle(pBookmark, pText.get(), nBytes * 2);
862 assert(nActualBytes % 2 == 0);
863 nActualBytes /= 2;
864 if (nActualBytes > 1)
866 #if defined OSL_BIGENDIAN
867 // The data returned by FPDFTextObj_GetText is documented to always be UTF-16LE:
868 for (int i = 0; i != nActualBytes; ++i)
870 pText[i] = OSL_SWAPWORD(pText[i]);
872 #endif
873 // insert nLevel spaces before the title
874 rBuf.append(OUString(" ").subView(0, nLevel));
875 aString = OUString(pText.get());
878 rBuf.append(aString);
879 rBuf.append("\n");
881 // get children
882 lcl_getBookmarks(nLevel + 1, rBuf, pDoc, FPDFBookmark_GetFirstChild(pDoc, pBookmark));
884 // get siblings
885 while (nullptr != (pBookmark = FPDFBookmark_GetNextSibling(pDoc, pBookmark)))
886 lcl_getBookmarks(nLevel, rBuf, pDoc, pBookmark);
889 OUString PDFiumDocumentImpl::getBookmarks()
891 OUStringBuffer aBuf;
892 FPDF_BOOKMARK pBookmark = FPDFBookmark_GetFirstChild(mpPdfDocument, nullptr);
893 lcl_getBookmarks(0, aBuf, mpPdfDocument, pBookmark);
894 return aBuf.makeStringAndClear();
897 basegfx::B2DSize PDFiumDocumentImpl::getPageSize(int nIndex)
899 basegfx::B2DSize aSize;
900 FS_SIZEF aPDFSize;
901 if (FPDF_GetPageSizeByIndexF(mpPdfDocument, nIndex, &aPDFSize))
903 aSize = basegfx::B2DSize(aPDFSize.width, aPDFSize.height);
905 return aSize;
908 int PDFiumDocumentImpl::getPageCount() { return FPDF_GetPageCount(mpPdfDocument); }
910 int PDFiumDocumentImpl::getSignatureCount() { return FPDF_GetSignatureCount(mpPdfDocument); }
912 int PDFiumDocumentImpl::getAttachmentCount() { return FPDFDoc_GetAttachmentCount(mpPdfDocument); }
914 int PDFiumDocumentImpl::getFileVersion()
916 int nFileVersion = 0;
917 FPDF_GetFileVersion(mpPdfDocument, &nFileVersion);
918 return nFileVersion;
921 bool PDFiumDocumentImpl::saveWithVersion(SvMemoryStream& rStream, int nFileVersion)
923 CompatibleWriter aWriter(rStream);
924 aWriter.version = 1;
925 aWriter.WriteBlock = &CompatibleWriterCallback;
926 if (!FPDF_SaveWithVersion(mpPdfDocument, &aWriter, 0, nFileVersion))
928 return false;
931 return true;
934 int PDFiumPageImpl::getObjectCount() { return FPDFPage_CountObjects(mpPage); }
936 std::unique_ptr<PDFiumPageObject> PDFiumPageImpl::getObject(int nIndex)
938 std::unique_ptr<PDFiumPageObject> pPDFiumPageObject;
939 FPDF_PAGEOBJECT pPageObject = FPDFPage_GetObject(mpPage, nIndex);
940 if (pPageObject)
942 pPDFiumPageObject = std::make_unique<PDFiumPageObjectImpl>(pPageObject);
944 return pPDFiumPageObject;
947 int PDFiumPageImpl::getAnnotationCount() { return FPDFPage_GetAnnotCount(mpPage); }
949 int PDFiumPageImpl::getAnnotationIndex(std::unique_ptr<PDFiumAnnotation> const& rAnnotation)
951 auto pAnnotation = static_cast<PDFiumAnnotationImpl*>(rAnnotation.get());
952 return FPDFPage_GetAnnotIndex(mpPage, pAnnotation->getPointer());
955 std::unique_ptr<PDFiumAnnotation> PDFiumPageImpl::getAnnotation(int nIndex)
957 std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;
958 FPDF_ANNOTATION pAnnotation = FPDFPage_GetAnnot(mpPage, nIndex);
959 if (pAnnotation)
961 pPDFiumAnnotation = std::make_unique<PDFiumAnnotationImpl>(pAnnotation);
963 return pPDFiumAnnotation;
966 std::unique_ptr<PDFiumTextPage> PDFiumPageImpl::getTextPage()
968 std::unique_ptr<PDFiumTextPage> pPDFiumTextPage;
969 FPDF_TEXTPAGE pTextPage = FPDFText_LoadPage(mpPage);
970 if (pTextPage)
972 pPDFiumTextPage = std::make_unique<PDFiumTextPageImpl>(pTextPage);
974 return pPDFiumTextPage;
977 bool PDFiumPageImpl::hasLinks()
979 // This could be a full iterator, but at the moment we just determine if the list is empty or
980 // not.
981 int nStartPos = 0;
982 FPDF_LINK pLinkAnnot = nullptr;
983 return FPDFLink_Enumerate(mpPage, &nStartPos, &pLinkAnnot);
986 void PDFiumPageImpl::onAfterLoadPage(PDFiumDocument* pDoc)
988 auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
989 FORM_OnAfterLoadPage(mpPage, pDocImpl->getFormHandlePointer());
992 PDFiumPageObjectImpl::PDFiumPageObjectImpl(FPDF_PAGEOBJECT pPageObject)
993 : mpPageObject(pPageObject)
997 OUString PDFiumPageObjectImpl::getText(std::unique_ptr<PDFiumTextPage> const& rTextPage)
999 auto pTextPage = static_cast<PDFiumTextPageImpl*>(rTextPage.get());
1000 return getUnicodeString([this, pTextPage](FPDF_WCHAR* buffer, unsigned long length) {
1001 return FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), buffer, length);
1005 PDFPageObjectType PDFiumPageObjectImpl::getType()
1007 return static_cast<PDFPageObjectType>(FPDFPageObj_GetType(mpPageObject));
1010 int PDFiumPageObjectImpl::getFormObjectCount() { return FPDFFormObj_CountObjects(mpPageObject); }
1012 std::unique_ptr<PDFiumPageObject> PDFiumPageObjectImpl::getFormObject(int nIndex)
1014 std::unique_ptr<PDFiumPageObject> pPDFiumFormObject;
1015 FPDF_PAGEOBJECT pFormObject = FPDFFormObj_GetObject(mpPageObject, nIndex);
1016 if (pFormObject)
1018 pPDFiumFormObject = std::make_unique<PDFiumPageObjectImpl>(pFormObject);
1020 return pPDFiumFormObject;
1023 basegfx::B2DHomMatrix PDFiumPageObjectImpl::getMatrix()
1025 basegfx::B2DHomMatrix aB2DMatrix;
1026 FS_MATRIX matrix;
1027 if (FPDFPageObj_GetMatrix(mpPageObject, &matrix))
1028 aB2DMatrix = basegfx::B2DHomMatrix::abcdef(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e,
1029 matrix.f);
1030 return aB2DMatrix;
1033 basegfx::B2DRectangle PDFiumPageObjectImpl::getBounds()
1035 basegfx::B2DRectangle aB2DRectangle;
1037 float left = 0;
1038 float bottom = 0;
1039 float right = 0;
1040 float top = 0;
1041 if (FPDFPageObj_GetBounds(mpPageObject, &left, &bottom, &right, &top))
1043 aB2DRectangle = basegfx::B2DRectangle(left, top, right, bottom);
1045 return aB2DRectangle;
1048 double PDFiumPageObjectImpl::getFontSize()
1050 float nSize{};
1051 FPDFTextObj_GetFontSize(mpPageObject, &nSize);
1052 return nSize;
1055 OUString PDFiumPageObjectImpl::getFontName()
1057 OUString sFamilyName;
1058 const int nFamilyName = 80 + 1;
1059 std::unique_ptr<char[]> pFamilyName(new char[nFamilyName]); // + terminating null
1060 FPDF_FONT pFontObject = FPDFTextObj_GetFont(mpPageObject);
1061 int nFamilyNameChars = FPDFFont_GetFamilyName(pFontObject, pFamilyName.get(), nFamilyName);
1062 if (nFamilyName >= nFamilyNameChars)
1064 sFamilyName = OUString::createFromAscii(pFamilyName.get());
1066 return sFamilyName;
1069 PDFTextRenderMode PDFiumPageObjectImpl::getTextRenderMode()
1071 return static_cast<PDFTextRenderMode>(FPDFTextObj_GetTextRenderMode(mpPageObject));
1074 Color PDFiumPageObjectImpl::getFillColor()
1076 Color aColor = COL_TRANSPARENT;
1077 unsigned int nR, nG, nB, nA;
1078 if (FPDFPageObj_GetFillColor(mpPageObject, &nR, &nG, &nB, &nA))
1080 aColor = Color(ColorAlpha, nA, nR, nG, nB);
1082 return aColor;
1085 Color PDFiumPageObjectImpl::getStrokeColor()
1087 Color aColor = COL_TRANSPARENT;
1088 unsigned int nR, nG, nB, nA;
1089 if (FPDFPageObj_GetStrokeColor(mpPageObject, &nR, &nG, &nB, &nA))
1091 aColor = Color(ColorAlpha, nA, nR, nG, nB);
1093 return aColor;
1096 double PDFiumPageObjectImpl::getStrokeWidth()
1098 float fWidth = 1;
1099 FPDFPageObj_GetStrokeWidth(mpPageObject, &fWidth);
1100 return fWidth;
1103 int PDFiumPageObjectImpl::getPathSegmentCount() { return FPDFPath_CountSegments(mpPageObject); }
1105 std::unique_ptr<PDFiumPathSegment> PDFiumPageObjectImpl::getPathSegment(int index)
1107 std::unique_ptr<PDFiumPathSegment> pPDFiumPathSegment;
1108 FPDF_PATHSEGMENT pPathSegment = FPDFPath_GetPathSegment(mpPageObject, index);
1109 if (pPathSegment)
1111 pPDFiumPathSegment = std::make_unique<PDFiumPathSegmentImpl>(pPathSegment);
1113 return pPDFiumPathSegment;
1116 Size PDFiumPageObjectImpl::getImageSize(PDFiumPage& rPage)
1118 FPDF_IMAGEOBJ_METADATA aMeta;
1119 auto& rPageImpl = static_cast<PDFiumPageImpl&>(rPage);
1120 FPDFImageObj_GetImageMetadata(mpPageObject, rPageImpl.getPointer(), &aMeta);
1121 return Size(aMeta.width, aMeta.height);
1124 std::unique_ptr<PDFiumBitmap> PDFiumPageObjectImpl::getImageBitmap()
1126 std::unique_ptr<PDFiumBitmap> pPDFiumBitmap;
1127 FPDF_BITMAP pBitmap = FPDFImageObj_GetBitmap(mpPageObject);
1128 if (pBitmap)
1130 pPDFiumBitmap = std::make_unique<PDFiumBitmapImpl>(pBitmap);
1132 return pPDFiumBitmap;
1135 bool PDFiumPageObjectImpl::getDrawMode(PDFFillMode& rFillMode, bool& rStroke)
1137 auto nFillMode = static_cast<int>(rFillMode);
1138 auto bStroke = static_cast<FPDF_BOOL>(rStroke);
1139 bool bRet = FPDFPath_GetDrawMode(mpPageObject, &nFillMode, &bStroke);
1140 rFillMode = static_cast<PDFFillMode>(nFillMode);
1141 rStroke = static_cast<bool>(bStroke);
1142 return bRet;
1145 BitmapChecksum PDFiumPageImpl::getChecksum(int nMDPPerm)
1147 int nPageWidth = getWidth();
1148 int nPageHeight = getHeight();
1149 std::unique_ptr<PDFiumBitmap> pPdfBitmap
1150 = PDFiumLibrary::get()->createBitmap(nPageWidth, nPageHeight, /*nAlpha=*/1);
1151 if (!pPdfBitmap)
1152 return 0;
1154 PDFiumBitmapImpl* pBitmapImpl = static_cast<PDFiumBitmapImpl*>(pPdfBitmap.get());
1156 int nFlags = 0;
1157 if (nMDPPerm != 3)
1159 // Annotations/commenting should affect the checksum, signature verification wants this.
1160 nFlags = FPDF_ANNOT;
1162 FPDF_RenderPageBitmap(pBitmapImpl->getPointer(), mpPage, /*start_x=*/0, /*start_y=*/0,
1163 nPageWidth, nPageHeight,
1164 /*rotate=*/0, nFlags);
1165 Bitmap aBitmap(Size(nPageWidth, nPageHeight), vcl::PixelFormat::N24_BPP);
1167 BitmapScopedWriteAccess pWriteAccess(aBitmap);
1168 const auto pPdfBuffer
1169 = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pBitmapImpl->getPointer()));
1170 const int nStride = FPDFBitmap_GetStride(pBitmapImpl->getPointer());
1171 for (int nRow = 0; nRow < nPageHeight; ++nRow)
1173 ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow);
1174 pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride);
1177 return aBitmap.GetChecksum();
1180 double PDFiumPageImpl::getWidth() { return FPDF_GetPageWidth(mpPage); }
1182 double PDFiumPageImpl::getHeight() { return FPDF_GetPageHeight(mpPage); }
1184 bool PDFiumPageImpl::hasTransparency() { return FPDFPage_HasTransparency(mpPage); }
1186 PDFiumPathSegmentImpl::PDFiumPathSegmentImpl(FPDF_PATHSEGMENT pPathSegment)
1187 : mpPathSegment(pPathSegment)
1191 basegfx::B2DPoint PDFiumPathSegmentImpl::getPoint() const
1193 basegfx::B2DPoint aPoint;
1194 float fx, fy;
1195 if (FPDFPathSegment_GetPoint(mpPathSegment, &fx, &fy))
1196 aPoint = basegfx::B2DPoint(fx, fy);
1197 return aPoint;
1200 bool PDFiumPathSegmentImpl::isClosed() const { return FPDFPathSegment_GetClose(mpPathSegment); }
1202 PDFSegmentType PDFiumPathSegmentImpl::getType() const
1204 return static_cast<PDFSegmentType>(FPDFPathSegment_GetType(mpPathSegment));
1207 PDFiumFormHandle::PDFiumFormHandle(FPDF_FORMHANDLE pHandle)
1208 : mpHandle(pHandle)
1212 PDFiumFormHandle::~PDFiumFormHandle() { FPDFDOC_ExitFormFillEnvironment(mpHandle); }
1214 FPDF_FORMHANDLE PDFiumFormHandle::getPointer() { return mpHandle; }
1216 PDFiumBitmapImpl::PDFiumBitmapImpl(FPDF_BITMAP pBitmap)
1217 : mpBitmap(pBitmap)
1221 PDFiumBitmapImpl::~PDFiumBitmapImpl()
1223 if (mpBitmap)
1225 FPDFBitmap_Destroy(mpBitmap);
1229 void PDFiumBitmapImpl::fillRect(int left, int top, int width, int height, sal_uInt32 nColor)
1231 FPDFBitmap_FillRect(mpBitmap, left, top, width, height, nColor);
1234 void PDFiumBitmapImpl::renderPageBitmap(PDFiumDocument* pDoc, PDFiumPage* pPage, int nStartX,
1235 int nStartY, int nSizeX, int nSizeY)
1237 auto pPageImpl = static_cast<PDFiumPageImpl*>(pPage);
1238 FPDF_RenderPageBitmap(mpBitmap, pPageImpl->getPointer(), nStartX, nStartY, nSizeX, nSizeY,
1239 /*rotate=*/0, /*flags=*/0);
1241 // Render widget annotations for FormFields.
1242 auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1243 FPDF_FFLDraw(pDocImpl->getFormHandlePointer(), mpBitmap, pPageImpl->getPointer(), nStartX,
1244 nStartY, nSizeX, nSizeY, /*rotate=*/0, /*flags=*/0);
1247 ConstScanline PDFiumBitmapImpl::getBuffer()
1249 return static_cast<ConstScanline>(FPDFBitmap_GetBuffer(mpBitmap));
1252 int PDFiumBitmapImpl::getStride() { return FPDFBitmap_GetStride(mpBitmap); }
1254 int PDFiumBitmapImpl::getWidth() { return FPDFBitmap_GetWidth(mpBitmap); }
1256 int PDFiumBitmapImpl::getHeight() { return FPDFBitmap_GetHeight(mpBitmap); }
1258 PDFBitmapType PDFiumBitmapImpl::getFormat()
1260 return static_cast<PDFBitmapType>(FPDFBitmap_GetFormat(mpBitmap));
1263 BitmapEx PDFiumBitmapImpl::createBitmapFromBuffer()
1265 BitmapEx aBitmapEx;
1267 const vcl::pdf::PDFBitmapType eFormat = getFormat();
1268 if (eFormat == vcl::pdf::PDFBitmapType::Unknown)
1269 return aBitmapEx;
1271 const int nWidth = getWidth();
1272 const int nHeight = getHeight();
1273 const int nStride = getStride();
1275 switch (eFormat)
1277 case vcl::pdf::PDFBitmapType::BGR:
1279 aBitmapEx = BitmapEx(Size(nWidth, nHeight), vcl::PixelFormat::N24_BPP);
1280 ReadRawDIB(aBitmapEx, getBuffer(), ScanlineFormat::N24BitTcBgr, nHeight, nStride);
1282 break;
1284 case vcl::pdf::PDFBitmapType::BGRx:
1286 aBitmapEx = BitmapEx(Size(nWidth, nHeight), vcl::PixelFormat::N24_BPP);
1287 ReadRawDIB(aBitmapEx, getBuffer(), ScanlineFormat::N32BitTcRgba, nHeight, nStride);
1289 break;
1291 case vcl::pdf::PDFBitmapType::BGRA:
1293 Bitmap aBitmap(Size(nWidth, nHeight), vcl::PixelFormat::N24_BPP);
1294 AlphaMask aMask(Size(nWidth, nHeight));
1296 BitmapScopedWriteAccess pWriteAccess(aBitmap);
1297 BitmapScopedWriteAccess pMaskAccess(aMask);
1298 ConstScanline pBuffer = getBuffer();
1299 std::vector<sal_uInt8> aScanlineAlpha(nWidth);
1300 for (int nRow = 0; nRow < nHeight; ++nRow)
1302 ConstScanline pLine = pBuffer + (nStride * nRow);
1303 pWriteAccess->CopyScanline(nRow, pLine, ScanlineFormat::N32BitTcBgra, nStride);
1304 for (int nCol = 0; nCol < nWidth; ++nCol)
1306 aScanlineAlpha[nCol] = pLine[3];
1307 pLine += 4;
1309 pMaskAccess->CopyScanline(nRow, aScanlineAlpha.data(), ScanlineFormat::N8BitPal,
1310 nWidth);
1313 aBitmapEx = BitmapEx(aBitmap, aMask);
1315 break;
1317 default:
1318 break;
1321 return aBitmapEx;
1324 PDFiumAnnotationImpl::PDFiumAnnotationImpl(FPDF_ANNOTATION pAnnotation)
1325 : mpAnnotation(pAnnotation)
1329 PDFiumAnnotationImpl::~PDFiumAnnotationImpl()
1331 if (mpAnnotation)
1332 FPDFPage_CloseAnnot(mpAnnotation);
1335 PDFAnnotationSubType PDFiumAnnotationImpl::getSubType()
1337 return PDFAnnotationSubType(FPDFAnnot_GetSubtype(mpAnnotation));
1340 basegfx::B2DRectangle PDFiumAnnotationImpl::getRectangle()
1342 basegfx::B2DRectangle aB2DRectangle;
1343 FS_RECTF aRect;
1344 if (FPDFAnnot_GetRect(mpAnnotation, &aRect))
1346 aB2DRectangle = basegfx::B2DRectangle(aRect.left, aRect.top, aRect.right, aRect.bottom);
1348 return aB2DRectangle;
1351 Color PDFiumAnnotationImpl::getColor()
1353 unsigned int nR, nG, nB, nA;
1354 if (FPDFAnnot_GetColor(mpAnnotation, FPDFANNOT_COLORTYPE_Color, &nR, &nG, &nB, &nA))
1356 return Color(ColorAlpha, nA, nR, nG, nB);
1358 // FPDFAnnot_GetColor can return false if there is an appearance stream
1359 // So we search for a color with getStrokeColor
1360 for (int i = 0; i < getObjectCount(); ++i)
1362 if (getObject(i)->getType() == PDFPageObjectType::Path)
1363 return getObject(i)->getStrokeColor();
1365 return COL_TRANSPARENT;
1368 Color PDFiumAnnotationImpl::getInteriorColor()
1370 unsigned int nR, nG, nB, nA;
1371 if (FPDFAnnot_GetColor(mpAnnotation, FPDFANNOT_COLORTYPE_InteriorColor, &nR, &nG, &nB, &nA))
1373 return Color(ColorAlpha, nA, nR, nG, nB);
1375 // FPDFAnnot_GetColor can return false if there is an appearance stream
1376 // So we search for a color with getFillColor
1377 for (int i = 0; i < getObjectCount(); ++i)
1379 if (getObject(i)->getType() == PDFPageObjectType::Path)
1380 return getObject(i)->getFillColor();
1382 return COL_TRANSPARENT;
1385 size_t PDFiumAnnotationImpl::getAttachmentPointsCount()
1387 return FPDFAnnot_CountAttachmentPoints(mpAnnotation);
1390 std::vector<basegfx::B2DPoint> PDFiumAnnotationImpl::getAttachmentPoints(size_t nIndex)
1392 std::vector<basegfx::B2DPoint> aQuads;
1394 FS_QUADPOINTSF aQuadpoints;
1395 if (FPDFAnnot_GetAttachmentPoints(mpAnnotation, nIndex, &aQuadpoints))
1397 aQuads.emplace_back(aQuadpoints.x1, aQuadpoints.y1);
1398 aQuads.emplace_back(aQuadpoints.x2, aQuadpoints.y2);
1399 aQuads.emplace_back(aQuadpoints.x3, aQuadpoints.y3);
1400 aQuads.emplace_back(aQuadpoints.x4, aQuadpoints.y4);
1402 return aQuads;
1405 std::vector<basegfx::B2DPoint> PDFiumAnnotationImpl::getLineGeometry()
1407 std::vector<basegfx::B2DPoint> aLine;
1408 FS_POINTF aStart;
1409 FS_POINTF aEnd;
1410 if (FPDFAnnot_GetLine(mpAnnotation, &aStart, &aEnd))
1412 aLine.emplace_back(aStart.x, aStart.y);
1413 aLine.emplace_back(aEnd.x, aEnd.y);
1415 return aLine;
1418 PDFFormFieldType PDFiumAnnotationImpl::getFormFieldType(PDFiumDocument* pDoc)
1420 auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1421 return PDFFormFieldType(
1422 FPDFAnnot_GetFormFieldType(pDocImpl->getFormHandlePointer(), mpAnnotation));
1425 int PDFiumAnnotationImpl::getFormFieldFlags(PDFiumDocument* pDoc)
1427 auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1428 return FPDFAnnot_GetFormFieldFlags(pDocImpl->getFormHandlePointer(), mpAnnotation);
1431 float PDFiumAnnotationImpl::getFontSize(PDFiumDocument* pDoc)
1433 auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1434 float fRet{};
1435 if (!FPDFAnnot_GetFontSize(pDocImpl->getFormHandlePointer(), mpAnnotation, &fRet))
1437 return 0.0f;
1440 return fRet;
1443 Color PDFiumAnnotationImpl::getFontColor(PDFiumDocument* pDoc)
1445 auto pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1446 unsigned int nR, nG, nB;
1447 if (!FPDFAnnot_GetFontColor(pDocImpl->getFormHandlePointer(), mpAnnotation, &nR, &nG, &nB))
1449 return Color();
1452 return Color(nR, nG, nB);
1455 OUString PDFiumAnnotationImpl::getFormFieldAlternateName(PDFiumDocument* pDoc)
1457 auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1458 return getUnicodeString([this, pDocImpl](FPDF_WCHAR* buffer, unsigned long length) {
1459 return FPDFAnnot_GetFormFieldAlternateName(pDocImpl->getFormHandlePointer(), mpAnnotation,
1460 buffer, length);
1464 OUString PDFiumAnnotationImpl::getFormFieldValue(PDFiumDocument* pDoc)
1466 auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1467 return getUnicodeString([this, pDocImpl](FPDF_WCHAR* buffer, unsigned long length) {
1468 return FPDFAnnot_GetFormFieldValue(pDocImpl->getFormHandlePointer(), mpAnnotation, buffer,
1469 length);
1472 int PDFiumAnnotationImpl::getOptionCount(PDFiumDocument* pDoc)
1474 auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1475 return FPDFAnnot_GetOptionCount(pDocImpl->getFormHandlePointer(), mpAnnotation);
1478 OUString PDFiumAnnotationImpl::getFormAdditionalActionJavaScript(PDFiumDocument* pDoc,
1479 PDFAnnotAActionType eEvent)
1481 auto* pDocImpl = static_cast<PDFiumDocumentImpl*>(pDoc);
1482 return getUnicodeString([this, pDocImpl, eEvent](FPDF_WCHAR* buffer, unsigned long length) {
1483 return FPDFAnnot_GetFormAdditionalActionJavaScript(pDocImpl->getFormHandlePointer(),
1484 mpAnnotation, static_cast<int>(eEvent),
1485 buffer, length);
1489 namespace
1491 bool getBorderProperties(FPDF_ANNOTATION mpAnnotation, float& rHorizontalCornerRadius,
1492 float& rVerticalCornerRadius, float& rBorderWidth)
1494 float fHoriRadius = 0.0f;
1495 float fVertRadius = 0.0f;
1496 float fWidth = 0.0f;
1498 if (!FPDFAnnot_GetBorder(mpAnnotation, &fHoriRadius, &fVertRadius, &fWidth))
1499 return false;
1501 rHorizontalCornerRadius = fHoriRadius;
1502 rVerticalCornerRadius = fVertRadius;
1503 rBorderWidth = fWidth;
1504 return true;
1508 float PDFiumAnnotationImpl::getBorderWidth()
1510 float fHorizontalCornerRadius;
1511 float fVerticalCornerRadius;
1512 float fBorderWidth;
1514 if (!getBorderProperties(mpAnnotation, fHorizontalCornerRadius, fVerticalCornerRadius,
1515 fBorderWidth))
1516 return 0.0f;
1517 return fBorderWidth;
1520 basegfx::B2DSize PDFiumAnnotationImpl::getBorderCornerRadius()
1522 float fHorizontalCornerRadius;
1523 float fVerticalCornerRadius;
1524 float fBorderWidth;
1526 if (!getBorderProperties(mpAnnotation, fHorizontalCornerRadius, fVerticalCornerRadius,
1527 fBorderWidth))
1528 return basegfx::B2DSize(0.0, 0.0);
1529 return basegfx::B2DSize(fHorizontalCornerRadius, fVerticalCornerRadius);
1532 bool PDFiumAnnotationImpl::hasKey(OString const& rKey)
1534 return FPDFAnnot_HasKey(mpAnnotation, rKey.getStr());
1537 PDFObjectType PDFiumAnnotationImpl::getValueType(OString const& rKey)
1539 return static_cast<PDFObjectType>(FPDFAnnot_GetValueType(mpAnnotation, rKey.getStr()));
1542 OUString PDFiumAnnotationImpl::getString(OString const& rKey)
1544 return getUnicodeString([this, rKey](FPDF_WCHAR* buffer, unsigned long length) {
1545 return FPDFAnnot_GetStringValue(mpAnnotation, rKey.getStr(), buffer, length);
1549 std::vector<std::vector<basegfx::B2DPoint>> PDFiumAnnotationImpl::getInkStrokes()
1551 std::vector<std::vector<basegfx::B2DPoint>> aB2DPointList;
1552 int nInkStrokes = FPDFAnnot_GetInkListCount(mpAnnotation);
1553 for (int i = 0; i < nInkStrokes; i++)
1555 std::vector<basegfx::B2DPoint> aB2DPoints;
1556 int nPoints = FPDFAnnot_GetInkListPath(mpAnnotation, i, nullptr, 0);
1557 if (nPoints)
1559 std::vector<FS_POINTF> aPoints(nPoints);
1560 if (FPDFAnnot_GetInkListPath(mpAnnotation, i, aPoints.data(), aPoints.size()))
1562 for (auto const& rPoint : aPoints)
1564 aB2DPoints.emplace_back(rPoint.x, rPoint.y);
1566 aB2DPointList.push_back(aB2DPoints);
1570 return aB2DPointList;
1573 std::vector<basegfx::B2DPoint> PDFiumAnnotationImpl::getVertices()
1575 std::vector<basegfx::B2DPoint> aB2DPoints;
1576 int nPoints = FPDFAnnot_GetVertices(mpAnnotation, nullptr, 0);
1577 if (nPoints)
1579 std::vector<FS_POINTF> aPoints(nPoints);
1580 if (FPDFAnnot_GetVertices(mpAnnotation, aPoints.data(), aPoints.size()))
1582 for (auto const& rPoint : aPoints)
1583 aB2DPoints.emplace_back(rPoint.x, rPoint.y);
1586 return aB2DPoints;
1589 std::unique_ptr<PDFiumAnnotation> PDFiumAnnotationImpl::getLinked(OString const& rKey)
1591 std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;
1592 FPDF_ANNOTATION pAnnotation = FPDFAnnot_GetLinkedAnnot(mpAnnotation, rKey.getStr());
1593 if (pAnnotation)
1595 pPDFiumAnnotation = std::make_unique<PDFiumAnnotationImpl>(pAnnotation);
1597 return pPDFiumAnnotation;
1600 int PDFiumAnnotationImpl::getObjectCount() { return FPDFAnnot_GetObjectCount(mpAnnotation); }
1602 std::unique_ptr<PDFiumPageObject> PDFiumAnnotationImpl::getObject(int nIndex)
1604 std::unique_ptr<PDFiumPageObject> pPDFiumPageObject;
1605 FPDF_PAGEOBJECT pPageObject = FPDFAnnot_GetObject(mpAnnotation, nIndex);
1606 if (pPageObject)
1608 pPDFiumPageObject = std::make_unique<PDFiumPageObjectImpl>(pPageObject);
1610 return pPDFiumPageObject;
1613 PDFiumTextPageImpl::PDFiumTextPageImpl(FPDF_TEXTPAGE pTextPage)
1614 : mpTextPage(pTextPage)
1618 PDFiumTextPageImpl::~PDFiumTextPageImpl()
1620 if (mpTextPage)
1621 FPDFText_ClosePage(mpTextPage);
1624 int PDFiumTextPageImpl::countChars() { return FPDFText_CountChars(mpTextPage); }
1626 basegfx::B2DRectangle PDFiumTextPageImpl::getCharBox(int nIndex, double fPageHeight)
1628 double left = 0.0;
1629 double right = 0.0;
1630 double bottom = 0.0;
1631 double top = 0.0;
1633 if (FPDFText_GetCharBox(mpTextPage, nIndex, &left, &right, &bottom, &top))
1635 left = convertPointToMm100(left);
1636 right = convertPointToMm100(right);
1637 top = fPageHeight - convertPointToMm100(top);
1638 bottom = fPageHeight - convertPointToMm100(bottom);
1640 return basegfx::B2DRectangle(left, bottom, right, top);
1643 return basegfx::B2DRectangle();
1646 unsigned int PDFiumTextPageImpl::getUnicode(int index)
1648 return FPDFText_GetUnicode(mpTextPage, index);
1651 std::unique_ptr<PDFiumSearchHandle>
1652 PDFiumTextPageImpl::findStart(const OUString& rFindWhat, PDFFindFlags nFlags, sal_Int32 nStartIndex)
1654 FPDF_WIDESTRING pFindWhat = reinterpret_cast<FPDF_WIDESTRING>(rFindWhat.getStr());
1655 return std::make_unique<vcl::pdf::PDFiumSearchHandleImpl>(
1656 FPDFText_FindStart(mpTextPage, pFindWhat, static_cast<sal_uInt32>(nFlags), nStartIndex));
1659 PDFiumSearchHandleImpl::PDFiumSearchHandleImpl(FPDF_SCHHANDLE pSearchHandle)
1660 : mpSearchHandle(pSearchHandle)
1664 PDFiumSearchHandleImpl::~PDFiumSearchHandleImpl()
1666 if (mpSearchHandle)
1667 FPDFText_FindClose(mpSearchHandle);
1670 bool PDFiumSearchHandleImpl::findNext() { return FPDFText_FindNext(mpSearchHandle); }
1672 bool PDFiumSearchHandleImpl::findPrev() { return FPDFText_FindPrev(mpSearchHandle); }
1674 int PDFiumSearchHandleImpl::getSearchResultIndex()
1676 return FPDFText_GetSchResultIndex(mpSearchHandle);
1679 int PDFiumSearchHandleImpl::getSearchCount() { return FPDFText_GetSchCount(mpSearchHandle); }
1681 std::shared_ptr<PDFium>& PDFiumLibrary::get()
1683 static std::shared_ptr<PDFium> pInstance = std::make_shared<PDFiumImpl>();
1684 return pInstance;
1687 } // end vcl::pdf
1689 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */