LibreOffice Module vcl (master)  1
PDFiumLibrary.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  */
10 
12 
13 #include <cassert>
14 
15 #include <fpdf_doc.h>
16 #include <fpdf_annot.h>
17 #include <fpdf_edit.h>
18 #include <fpdf_text.h>
19 #include <fpdf_save.h>
20 #include <fpdf_signature.h>
21 
22 #include <osl/endian.h>
23 #include <vcl/bitmap.hxx>
24 #include <tools/stream.hxx>
25 #include <tools/UnitConversion.hxx>
26 
28 
29 using namespace com::sun::star;
30 
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");
43 
44 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Unknown) == FPDF_SEGMENT_UNKNOWN,
45  "PDFSegmentType::Unknown value mismatch");
46 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Lineto) == FPDF_SEGMENT_LINETO,
47  "PDFSegmentType::Lineto value mismatch");
48 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Bezierto) == FPDF_SEGMENT_BEZIERTO,
49  "PDFSegmentType::Bezierto value mismatch");
50 static_assert(static_cast<int>(vcl::pdf::PDFSegmentType::Moveto) == FPDF_SEGMENT_MOVETO,
51  "PDFSegmentType::Moveto value mismatch");
52 
53 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::Unknown) == FPDFBitmap_Unknown,
54  "PDFBitmapType::Unknown value mismatch");
55 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::Gray) == FPDFBitmap_Gray,
56  "PDFBitmapType::Gray value mismatch");
57 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::BGR) == FPDFBitmap_BGR,
58  "PDFBitmapType::BGR value mismatch");
59 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::BGRx) == FPDFBitmap_BGRx,
60  "PDFBitmapType::BGRx value mismatch");
61 static_assert(static_cast<int>(vcl::pdf::PDFBitmapType::BGRA) == FPDFBitmap_BGRA,
62  "PDFBitmapType::BGRA value mismatch");
63 
64 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Unknown) == FPDF_OBJECT_UNKNOWN,
65  "PDFObjectType::Unknown value mismatch");
66 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Boolean) == FPDF_OBJECT_BOOLEAN,
67  "PDFObjectType::Boolean value mismatch");
68 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Number) == FPDF_OBJECT_NUMBER,
69  "PDFObjectType::Number value mismatch");
70 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::String) == FPDF_OBJECT_STRING,
71  "PDFObjectType::String value mismatch");
72 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Name) == FPDF_OBJECT_NAME,
73  "PDFObjectType::Name value mismatch");
74 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Array) == FPDF_OBJECT_ARRAY,
75  "PDFObjectType::Array value mismatch");
76 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Dictionary) == FPDF_OBJECT_DICTIONARY,
77  "PDFObjectType::Dictionary value mismatch");
78 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Stream) == FPDF_OBJECT_STREAM,
79  "PDFObjectType::Stream value mismatch");
80 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Nullobj) == FPDF_OBJECT_NULLOBJ,
81  "PDFObjectType::Nullobj value mismatch");
82 static_assert(static_cast<int>(vcl::pdf::PDFObjectType::Reference) == FPDF_OBJECT_REFERENCE,
83  "PDFObjectType::Reference value mismatch");
84 
85 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Unknown) == FPDF_TEXTRENDERMODE_UNKNOWN,
86  "PDFTextRenderMode::Unknown value mismatch");
87 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Fill) == FPDF_TEXTRENDERMODE_FILL,
88  "PDFTextRenderMode::Fill value mismatch");
89 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Stroke) == FPDF_TEXTRENDERMODE_STROKE,
90  "PDFTextRenderMode::Stroke value mismatch");
91 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::FillStroke)
92  == FPDF_TEXTRENDERMODE_FILL_STROKE,
93  "PDFTextRenderMode::FillStroke value mismatch");
94 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Invisible)
95  == FPDF_TEXTRENDERMODE_INVISIBLE,
96  "PDFTextRenderMode::Invisible value mismatch");
97 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::FillClip)
98  == FPDF_TEXTRENDERMODE_FILL_CLIP,
99  "PDFTextRenderMode::FillClip value mismatch");
100 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::StrokeClip)
101  == FPDF_TEXTRENDERMODE_STROKE_CLIP,
102  "PDFTextRenderMode::StrokeClip value mismatch");
103 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::FillStrokeClip)
104  == FPDF_TEXTRENDERMODE_FILL_STROKE_CLIP,
105  "PDFTextRenderMode::FillStrokeClip value mismatch");
106 static_assert(static_cast<int>(vcl::pdf::PDFTextRenderMode::Clip) == FPDF_TEXTRENDERMODE_CLIP,
107  "PDFTextRenderMode::Clip value mismatch");
108 
109 static_assert(static_cast<int>(vcl::pdf::PDFFillMode::None) == FPDF_FILLMODE_NONE,
110  "PDFFillMode::None value mismatch");
111 static_assert(static_cast<int>(vcl::pdf::PDFFillMode::Alternate) == FPDF_FILLMODE_ALTERNATE,
112  "PDFFillMode::Alternate value mismatch");
113 static_assert(static_cast<int>(vcl::pdf::PDFFillMode::Winding) == FPDF_FILLMODE_WINDING,
114  "PDFFillMode::Winding value mismatch");
115 
116 static_assert(static_cast<int>(vcl::pdf::PDFFindFlags::MatchCase) == FPDF_MATCHCASE,
117  "PDFFindFlags::MatchCase value mismatch");
118 static_assert(static_cast<int>(vcl::pdf::PDFFindFlags::MatchWholeWord) == FPDF_MATCHWHOLEWORD,
119  "PDFFindFlags::MatchWholeWord value mismatch");
120 static_assert(static_cast<int>(vcl::pdf::PDFFindFlags::Consecutive) == FPDF_CONSECUTIVE,
121  "PDFFindFlags::Consecutive value mismatch");
122 
123 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Success) == FPDF_ERR_SUCCESS,
124  "PDFErrorType::Success value mismatch");
125 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Unknown) == FPDF_ERR_UNKNOWN,
126  "PDFErrorType::Unknown value mismatch");
127 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::File) == FPDF_ERR_FILE,
128  "PDFErrorType::File value mismatch");
129 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Format) == FPDF_ERR_FORMAT,
130  "PDFErrorType::Format value mismatch");
131 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Password) == FPDF_ERR_PASSWORD,
132  "PDFErrorType::Password value mismatch");
133 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Security) == FPDF_ERR_SECURITY,
134  "PDFErrorType::Security value mismatch");
135 static_assert(static_cast<int>(vcl::pdf::PDFErrorType::Page) == FPDF_ERR_PAGE,
136  "PDFErrorType::Page value mismatch");
137 
138 namespace
139 {
141 struct CompatibleWriter : public FPDF_FILEWRITE
142 {
143  CompatibleWriter(SvMemoryStream& rStream)
144  : m_rStream(rStream)
145  {
146  }
147 
148  SvMemoryStream& m_rStream;
149 };
150 
151 int CompatibleWriterCallback(FPDF_FILEWRITE* pFileWrite, const void* pData, unsigned long nSize)
152 {
153  auto pImpl = static_cast<CompatibleWriter*>(pFileWrite);
154  pImpl->m_rStream.WriteBytes(pData, nSize);
155  return 1;
156 }
157 }
158 
159 namespace vcl::pdf
160 {
161 namespace
162 {
163 class PDFiumBitmapImpl final : public PDFiumBitmap
164 {
165 private:
166  FPDF_BITMAP mpBitmap;
167 
168  PDFiumBitmapImpl(const PDFiumBitmapImpl&) = delete;
169  PDFiumBitmapImpl& operator=(const PDFiumBitmapImpl&) = delete;
170 
171 public:
172  PDFiumBitmapImpl(FPDF_BITMAP pBitmap);
173  ~PDFiumBitmapImpl() override;
174  FPDF_BITMAP getPointer() { return mpBitmap; }
175 
176  void fillRect(int left, int top, int width, int height, sal_uInt32 nColor) override;
177  void renderPageBitmap(PDFiumPage* pPage, int nStartX, int nStartY, int nSizeX,
178  int nSizeY) override;
179  ConstScanline getBuffer() override;
180  int getStride() override;
181  int getWidth() override;
182  int getHeight() override;
183  PDFBitmapType getFormat() override;
184 };
185 
186 class PDFiumPathSegmentImpl final : public PDFiumPathSegment
187 {
188 private:
189  FPDF_PATHSEGMENT mpPathSegment;
190 
191  PDFiumPathSegmentImpl(const PDFiumPathSegmentImpl&) = delete;
192  PDFiumPathSegmentImpl& operator=(const PDFiumPathSegmentImpl&) = delete;
193 
194 public:
195  PDFiumPathSegmentImpl(FPDF_PATHSEGMENT pPathSegment);
196 
197  basegfx::B2DPoint getPoint() const override;
198  bool isClosed() const override;
199  PDFSegmentType getType() const override;
200 };
201 
202 class PDFiumAnnotationImpl final : public PDFiumAnnotation
203 {
204 private:
205  FPDF_ANNOTATION mpAnnotation;
206 
207  PDFiumAnnotationImpl(const PDFiumAnnotationImpl&) = delete;
208  PDFiumAnnotationImpl& operator=(const PDFiumAnnotationImpl&) = delete;
209 
210 public:
211  PDFiumAnnotationImpl(FPDF_ANNOTATION pAnnotation);
212  ~PDFiumAnnotationImpl();
213  FPDF_ANNOTATION getPointer() { return mpAnnotation; }
214 
215  PDFAnnotationSubType getSubType() override;
216  basegfx::B2DRectangle getRectangle() override;
217  bool hasKey(OString const& rKey) override;
218  PDFObjectType getValueType(OString const& rKey) override;
219  OUString getString(OString const& rKey) override;
220  std::unique_ptr<PDFiumAnnotation> getLinked(OString const& rKey) override;
221  int getObjectCount() override;
222  std::unique_ptr<PDFiumPageObject> getObject(int nIndex) override;
223  std::vector<std::vector<basegfx::B2DPoint>> getInkStrokes() override;
224  std::vector<basegfx::B2DPoint> getVertices() override;
225  Color getColor() override;
226  Color getInteriorColor() override;
227  float getBorderWidth() override;
228  basegfx::B2DSize getBorderCornerRadius() override;
229  size_t getAttachmentPointsCount() override;
230  std::vector<basegfx::B2DPoint> getAttachmentPoints(size_t nIndex) override;
231  std::vector<basegfx::B2DPoint> getLineGeometry() override;
232 };
233 
234 class PDFiumPageObjectImpl final : public PDFiumPageObject
235 {
236 private:
237  FPDF_PAGEOBJECT mpPageObject;
238 
239  PDFiumPageObjectImpl(const PDFiumPageObjectImpl&) = delete;
240  PDFiumPageObjectImpl& operator=(const PDFiumPageObjectImpl&) = delete;
241 
242 public:
243  PDFiumPageObjectImpl(FPDF_PAGEOBJECT pPageObject);
244 
245  PDFPageObjectType getType() override;
246  OUString getText(std::unique_ptr<PDFiumTextPage> const& pTextPage) override;
247 
248  int getFormObjectCount() override;
249  std::unique_ptr<PDFiumPageObject> getFormObject(int nIndex) override;
250 
251  basegfx::B2DHomMatrix getMatrix() override;
252  basegfx::B2DRectangle getBounds() override;
253  double getFontSize() override;
254  OUString getFontName() override;
255  PDFTextRenderMode getTextRenderMode() override;
256  Color getFillColor() override;
257  Color getStrokeColor() override;
258  double getStrokeWidth() override;
259  // Path
260  int getPathSegmentCount() override;
261  std::unique_ptr<PDFiumPathSegment> getPathSegment(int index) override;
262  Size getImageSize(PDFiumPage& rPage) override;
263  std::unique_ptr<PDFiumBitmap> getImageBitmap() override;
264  bool getDrawMode(PDFFillMode& eFillMode, bool& bStroke) override;
265 };
266 
267 class PDFiumSearchHandleImpl final : public PDFiumSearchHandle
268 {
269 private:
270  FPDF_SCHHANDLE mpSearchHandle;
271 
272  PDFiumSearchHandleImpl(const PDFiumSearchHandleImpl&) = delete;
273  PDFiumSearchHandleImpl& operator=(const PDFiumSearchHandleImpl&) = delete;
274 
275 public:
276  PDFiumSearchHandleImpl(FPDF_SCHHANDLE pSearchHandle);
277  ~PDFiumSearchHandleImpl();
278 
279  bool findNext() override;
280  bool findPrev() override;
281  int getSearchResultIndex() override;
282  int getSearchCount() override;
283 };
284 
285 class PDFiumTextPageImpl final : public PDFiumTextPage
286 {
287 private:
288  FPDF_TEXTPAGE mpTextPage;
289 
290  PDFiumTextPageImpl(const PDFiumTextPageImpl&) = delete;
291  PDFiumTextPageImpl& operator=(const PDFiumTextPageImpl&) = delete;
292 
293 public:
294  PDFiumTextPageImpl(FPDF_TEXTPAGE pTextPage);
295  ~PDFiumTextPageImpl();
296 
297  FPDF_TEXTPAGE getPointer() { return mpTextPage; }
298 
299  int countChars() override;
300  unsigned int getUnicode(int index) override;
301  std::unique_ptr<PDFiumSearchHandle> findStart(const OUString& rFindWhat, PDFFindFlags nFlags,
302  sal_Int32 nStartIndex) override;
303 
305  basegfx::B2DRectangle getCharBox(int nIndex, double fPageHeight) override;
306 };
307 
308 class PDFiumSignatureImpl final : public PDFiumSignature
309 {
310 private:
311  FPDF_SIGNATURE mpSignature;
312  PDFiumSignatureImpl(const PDFiumSignatureImpl&) = delete;
313  PDFiumSignatureImpl& operator=(const PDFiumSignatureImpl&) = delete;
314 
315 public:
316  PDFiumSignatureImpl(FPDF_SIGNATURE pSignature);
317 
318  std::vector<int> getByteRange() override;
319  int getDocMDPPermission() override;
320  std::vector<unsigned char> getContents() override;
321  OString getSubFilter() override;
322  OUString getReason() override;
323  css::util::DateTime getTime() override;
324 };
325 
326 class PDFiumPageImpl final : public PDFiumPage
327 {
328 private:
329  FPDF_PAGE mpPage;
330 
331 private:
332  PDFiumPageImpl(const PDFiumPageImpl&) = delete;
333  PDFiumPageImpl& operator=(const PDFiumPageImpl&) = delete;
334 
335 public:
336  PDFiumPageImpl(FPDF_PAGE pPage)
337  : mpPage(pPage)
338  {
339  }
340 
341  ~PDFiumPageImpl() override
342  {
343  if (mpPage)
344  FPDF_ClosePage(mpPage);
345  }
346 
347  FPDF_PAGE getPointer() { return mpPage; }
348 
349  int getObjectCount() override;
350  std::unique_ptr<PDFiumPageObject> getObject(int nIndex) override;
351 
352  int getAnnotationCount() override;
353  int getAnnotationIndex(std::unique_ptr<PDFiumAnnotation> const& rAnnotation) override;
354 
355  std::unique_ptr<PDFiumAnnotation> getAnnotation(int nIndex) override;
356 
357  std::unique_ptr<PDFiumTextPage> getTextPage() override;
358 
359  BitmapChecksum getChecksum(int nMDPPerm) override;
360 
361  double getWidth() override;
362  double getHeight() override;
363 
364  bool hasTransparency() override;
365 
366  bool hasLinks() override;
367 };
368 
369 class PDFiumDocumentImpl : public PDFiumDocument
370 {
371 private:
372  FPDF_DOCUMENT mpPdfDocument;
373 
374 private:
375  PDFiumDocumentImpl(const PDFiumDocumentImpl&) = delete;
376  PDFiumDocumentImpl& operator=(const PDFiumDocumentImpl&) = delete;
377 
378 public:
379  PDFiumDocumentImpl(FPDF_DOCUMENT pPdfDocument);
380  ~PDFiumDocumentImpl() override;
381 
382  // Page size in points
383  basegfx::B2DSize getPageSize(int nIndex) override;
384  int getPageCount() override;
385  int getSignatureCount() override;
386  int getFileVersion() override;
387  bool saveWithVersion(SvMemoryStream& rStream, int nFileVersion) override;
388 
389  std::unique_ptr<PDFiumPage> openPage(int nIndex) override;
390  std::unique_ptr<PDFiumSignature> getSignature(int nIndex) override;
391  std::vector<unsigned int> getTrailerEnds() override;
392 };
393 
394 class PDFiumImpl : public PDFium
395 {
396 private:
397  PDFiumImpl(const PDFiumImpl&) = delete;
398  PDFiumImpl& operator=(const PDFiumImpl&) = delete;
399 
400  OUString maLastError;
401 
402 public:
403  PDFiumImpl();
404  ~PDFiumImpl() override;
405 
406  const OUString& getLastError() const override { return maLastError; }
407 
408  std::unique_ptr<PDFiumDocument> openDocument(const void* pData, int nSize) override;
409  PDFErrorType getLastErrorCode() override;
410  std::unique_ptr<PDFiumBitmap> createBitmap(int nWidth, int nHeight, int nAlpha) override;
411 };
412 }
413 
414 PDFiumImpl::PDFiumImpl()
415 {
416  FPDF_LIBRARY_CONFIG aConfig;
417  aConfig.version = 2;
418  aConfig.m_pUserFontPaths = nullptr;
419  aConfig.m_pIsolate = nullptr;
420  aConfig.m_v8EmbedderSlot = 0;
421  FPDF_InitLibraryWithConfig(&aConfig);
422 }
423 
424 PDFiumImpl::~PDFiumImpl() { FPDF_DestroyLibrary(); }
425 
426 std::unique_ptr<PDFiumDocument> PDFiumImpl::openDocument(const void* pData, int nSize)
427 {
428  maLastError = OUString();
429  std::unique_ptr<PDFiumDocument> pPDFiumDocument;
430 
431  FPDF_DOCUMENT pDocument = FPDF_LoadMemDocument(pData, nSize, /*password=*/nullptr);
432 
433  if (!pDocument)
434  {
435  switch (FPDF_GetLastError())
436  {
437  case FPDF_ERR_SUCCESS:
438  maLastError = "Success";
439  break;
440  case FPDF_ERR_UNKNOWN:
441  maLastError = "Unknown error";
442  break;
443  case FPDF_ERR_FILE:
444  maLastError = "File not found";
445  break;
446  case FPDF_ERR_FORMAT:
447  maLastError = "Input is not a PDF format";
448  break;
449  case FPDF_ERR_PASSWORD:
450  maLastError = "Incorrect password or password is required";
451  break;
452  case FPDF_ERR_SECURITY:
453  maLastError = "Security error";
454  break;
455  case FPDF_ERR_PAGE:
456  maLastError = "Content error";
457  break;
458  default:
459  break;
460  }
461  }
462  else
463  {
464  pPDFiumDocument = std::make_unique<PDFiumDocumentImpl>(pDocument);
465  }
466 
467  return pPDFiumDocument;
468 }
469 
470 PDFErrorType PDFiumImpl::getLastErrorCode()
471 {
472  return static_cast<PDFErrorType>(FPDF_GetLastError());
473 }
474 
475 std::unique_ptr<PDFiumBitmap> PDFiumImpl::createBitmap(int nWidth, int nHeight, int nAlpha)
476 {
477  std::unique_ptr<PDFiumBitmap> pPDFiumBitmap;
478  FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nWidth, nHeight, nAlpha);
479  if (!pPdfBitmap)
480  {
481  maLastError = "Failed to create bitmap";
482  }
483  else
484  {
485  pPDFiumBitmap = std::make_unique<PDFiumBitmapImpl>(pPdfBitmap);
486  }
487  return pPDFiumBitmap;
488 }
489 
490 PDFiumSignatureImpl::PDFiumSignatureImpl(FPDF_SIGNATURE pSignature)
491  : mpSignature(pSignature)
492 {
493 }
494 
495 std::vector<int> PDFiumSignatureImpl::getByteRange()
496 {
497  int nByteRangeLen = FPDFSignatureObj_GetByteRange(mpSignature, nullptr, 0);
498  std::vector<int> aByteRange(nByteRangeLen);
499  if (nByteRangeLen <= 0)
500  {
501  return aByteRange;
502  }
503 
504  FPDFSignatureObj_GetByteRange(mpSignature, aByteRange.data(), aByteRange.size());
505  return aByteRange;
506 }
507 
508 int PDFiumSignatureImpl::getDocMDPPermission()
509 {
510  return FPDFSignatureObj_GetDocMDPPermission(mpSignature);
511 }
512 
513 std::vector<unsigned char> PDFiumSignatureImpl::getContents()
514 {
515  int nContentsLen = FPDFSignatureObj_GetContents(mpSignature, nullptr, 0);
516  std::vector<unsigned char> aContents(nContentsLen);
517  if (aContents.empty())
518  {
519  return aContents;
520  }
521 
522  FPDFSignatureObj_GetContents(mpSignature, aContents.data(), aContents.size());
523  return aContents;
524 }
525 
526 OString PDFiumSignatureImpl::getSubFilter()
527 {
528  int nSubFilterLen = FPDFSignatureObj_GetSubFilter(mpSignature, nullptr, 0);
529  std::vector<char> aSubFilterBuf(nSubFilterLen);
530  FPDFSignatureObj_GetSubFilter(mpSignature, aSubFilterBuf.data(), aSubFilterBuf.size());
531  // Buffer is NUL-terminated.
532  OString aSubFilter(aSubFilterBuf.data(), aSubFilterBuf.size() - 1);
533  return aSubFilter;
534 }
535 
536 OUString PDFiumSignatureImpl::getReason()
537 {
538  int nReasonLen = FPDFSignatureObj_GetReason(mpSignature, nullptr, 0);
539  OUString aRet;
540  if (nReasonLen > 0)
541  {
542  std::vector<char16_t> aReasonBuf(nReasonLen);
543  FPDFSignatureObj_GetReason(mpSignature, aReasonBuf.data(), aReasonBuf.size());
544  aRet = OUString(aReasonBuf.data(), aReasonBuf.size() - 1);
545  }
546 
547  return aRet;
548 }
549 
550 util::DateTime PDFiumSignatureImpl::getTime()
551 {
552  util::DateTime aRet;
553  int nTimeLen = FPDFSignatureObj_GetTime(mpSignature, nullptr, 0);
554  if (nTimeLen <= 0)
555  {
556  return aRet;
557  }
558 
559  // Example: "D:20161027100104".
560  std::vector<char> aTimeBuf(nTimeLen);
561  FPDFSignatureObj_GetTime(mpSignature, aTimeBuf.data(), aTimeBuf.size());
562  OString aM(aTimeBuf.data(), aTimeBuf.size() - 1);
563  if (aM.startsWith("D:") && aM.getLength() >= 16)
564  {
565  aRet.Year = aM.copy(2, 4).toInt32();
566  aRet.Month = aM.copy(6, 2).toInt32();
567  aRet.Day = aM.copy(8, 2).toInt32();
568  aRet.Hours = aM.copy(10, 2).toInt32();
569  aRet.Minutes = aM.copy(12, 2).toInt32();
570  aRet.Seconds = aM.copy(14, 2).toInt32();
571  }
572  return aRet;
573 }
574 
575 PDFiumDocumentImpl::PDFiumDocumentImpl(FPDF_DOCUMENT pPdfDocument)
576  : mpPdfDocument(pPdfDocument)
577 {
578 }
579 
580 PDFiumDocumentImpl::~PDFiumDocumentImpl()
581 {
582  if (mpPdfDocument)
583  FPDF_CloseDocument(mpPdfDocument);
584 }
585 
586 std::unique_ptr<PDFiumPage> PDFiumDocumentImpl::openPage(int nIndex)
587 {
588  std::unique_ptr<PDFiumPage> pPDFiumPage;
589  FPDF_PAGE pPage = FPDF_LoadPage(mpPdfDocument, nIndex);
590  if (pPage)
591  {
592  pPDFiumPage = std::make_unique<PDFiumPageImpl>(pPage);
593  }
594  return pPDFiumPage;
595 }
596 
597 std::unique_ptr<PDFiumSignature> PDFiumDocumentImpl::getSignature(int nIndex)
598 {
599  std::unique_ptr<PDFiumSignature> pPDFiumSignature;
600  FPDF_SIGNATURE pSignature = FPDF_GetSignatureObject(mpPdfDocument, nIndex);
601  if (pSignature)
602  {
603  pPDFiumSignature = std::make_unique<PDFiumSignatureImpl>(pSignature);
604  }
605  return pPDFiumSignature;
606 }
607 
608 std::vector<unsigned int> PDFiumDocumentImpl::getTrailerEnds()
609 {
610  int nNumTrailers = FPDF_GetTrailerEnds(mpPdfDocument, nullptr, 0);
611  std::vector<unsigned int> aTrailerEnds(nNumTrailers);
612  FPDF_GetTrailerEnds(mpPdfDocument, aTrailerEnds.data(), aTrailerEnds.size());
613  return aTrailerEnds;
614 }
615 
616 basegfx::B2DSize PDFiumDocumentImpl::getPageSize(int nIndex)
617 {
618  basegfx::B2DSize aSize;
619  FS_SIZEF aPDFSize;
620  if (FPDF_GetPageSizeByIndexF(mpPdfDocument, nIndex, &aPDFSize))
621  {
622  aSize = basegfx::B2DSize(aPDFSize.width, aPDFSize.height);
623  }
624  return aSize;
625 }
626 
627 int PDFiumDocumentImpl::getPageCount() { return FPDF_GetPageCount(mpPdfDocument); }
628 
629 int PDFiumDocumentImpl::getSignatureCount() { return FPDF_GetSignatureCount(mpPdfDocument); }
630 
631 int PDFiumDocumentImpl::getFileVersion()
632 {
633  int nFileVersion = 0;
634  FPDF_GetFileVersion(mpPdfDocument, &nFileVersion);
635  return nFileVersion;
636 }
637 
638 bool PDFiumDocumentImpl::saveWithVersion(SvMemoryStream& rStream, int nFileVersion)
639 {
640  CompatibleWriter aWriter(rStream);
641  aWriter.version = 1;
642  aWriter.WriteBlock = &CompatibleWriterCallback;
643  if (!FPDF_SaveWithVersion(mpPdfDocument, &aWriter, 0, nFileVersion))
644  {
645  return false;
646  }
647 
648  return true;
649 }
650 
651 int PDFiumPageImpl::getObjectCount() { return FPDFPage_CountObjects(mpPage); }
652 
653 std::unique_ptr<PDFiumPageObject> PDFiumPageImpl::getObject(int nIndex)
654 {
655  std::unique_ptr<PDFiumPageObject> pPDFiumPageObject;
656  FPDF_PAGEOBJECT pPageObject = FPDFPage_GetObject(mpPage, nIndex);
657  if (pPageObject)
658  {
659  pPDFiumPageObject = std::make_unique<PDFiumPageObjectImpl>(pPageObject);
660  }
661  return pPDFiumPageObject;
662 }
663 
664 int PDFiumPageImpl::getAnnotationCount() { return FPDFPage_GetAnnotCount(mpPage); }
665 
666 int PDFiumPageImpl::getAnnotationIndex(std::unique_ptr<PDFiumAnnotation> const& rAnnotation)
667 {
668  auto pAnnotation = static_cast<PDFiumAnnotationImpl*>(rAnnotation.get());
669  return FPDFPage_GetAnnotIndex(mpPage, pAnnotation->getPointer());
670 }
671 
672 std::unique_ptr<PDFiumAnnotation> PDFiumPageImpl::getAnnotation(int nIndex)
673 {
674  std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;
675  FPDF_ANNOTATION pAnnotation = FPDFPage_GetAnnot(mpPage, nIndex);
676  if (pAnnotation)
677  {
678  pPDFiumAnnotation = std::make_unique<PDFiumAnnotationImpl>(pAnnotation);
679  }
680  return pPDFiumAnnotation;
681 }
682 
683 std::unique_ptr<PDFiumTextPage> PDFiumPageImpl::getTextPage()
684 {
685  std::unique_ptr<PDFiumTextPage> pPDFiumTextPage;
686  FPDF_TEXTPAGE pTextPage = FPDFText_LoadPage(mpPage);
687  if (pTextPage)
688  {
689  pPDFiumTextPage = std::make_unique<PDFiumTextPageImpl>(pTextPage);
690  }
691  return pPDFiumTextPage;
692 }
693 
694 bool PDFiumPageImpl::hasLinks()
695 {
696  // This could be a full iterator, but at the moment we just determine if the list is empty or
697  // not.
698  int nStartPos = 0;
699  FPDF_LINK pLinkAnnot = nullptr;
700  return FPDFLink_Enumerate(mpPage, &nStartPos, &pLinkAnnot);
701 }
702 
703 PDFiumPageObjectImpl::PDFiumPageObjectImpl(FPDF_PAGEOBJECT pPageObject)
704  : mpPageObject(pPageObject)
705 {
706 }
707 
708 OUString PDFiumPageObjectImpl::getText(std::unique_ptr<PDFiumTextPage> const& rTextPage)
709 {
710  OUString sReturnText;
711 
712  auto pTextPage = static_cast<PDFiumTextPageImpl*>(rTextPage.get());
713  int nBytes = FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), nullptr, 0);
714  assert(nBytes % 2 == 0);
715  nBytes /= 2;
716 
717  std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nBytes]);
718 
719  int nActualBytes
720  = FPDFTextObj_GetText(mpPageObject, pTextPage->getPointer(), pText.get(), nBytes * 2);
721  assert(nActualBytes % 2 == 0);
722  nActualBytes /= 2;
723  if (nActualBytes > 1)
724  {
725 #if defined OSL_BIGENDIAN
726  // The data returned by FPDFTextObj_GetText is documented to always be UTF-16LE:
727  for (int i = 0; i != nActualBytes; ++i)
728  {
729  pText[i] = OSL_SWAPWORD(pText[i]);
730  }
731 #endif
732  sReturnText = OUString(pText.get());
733  }
734 
735  return sReturnText;
736 }
737 
738 PDFPageObjectType PDFiumPageObjectImpl::getType()
739 {
740  return static_cast<PDFPageObjectType>(FPDFPageObj_GetType(mpPageObject));
741 }
742 
743 int PDFiumPageObjectImpl::getFormObjectCount() { return FPDFFormObj_CountObjects(mpPageObject); }
744 
745 std::unique_ptr<PDFiumPageObject> PDFiumPageObjectImpl::getFormObject(int nIndex)
746 {
747  std::unique_ptr<PDFiumPageObject> pPDFiumFormObject;
748  FPDF_PAGEOBJECT pFormObject = FPDFFormObj_GetObject(mpPageObject, nIndex);
749  if (pFormObject)
750  {
751  pPDFiumFormObject = std::make_unique<PDFiumPageObjectImpl>(pFormObject);
752  }
753  return pPDFiumFormObject;
754 }
755 
756 basegfx::B2DHomMatrix PDFiumPageObjectImpl::getMatrix()
757 {
758  basegfx::B2DHomMatrix aB2DMatrix;
759  FS_MATRIX matrix;
760  if (FPDFFormObj_GetMatrix(mpPageObject, &matrix))
761  aB2DMatrix = basegfx::B2DHomMatrix::abcdef(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e,
762  matrix.f);
763  return aB2DMatrix;
764 }
765 
766 basegfx::B2DRectangle PDFiumPageObjectImpl::getBounds()
767 {
768  basegfx::B2DRectangle aB2DRectangle;
769 
770  float left = 0;
771  float bottom = 0;
772  float right = 0;
773  float top = 0;
774  if (FPDFPageObj_GetBounds(mpPageObject, &left, &bottom, &right, &top))
775  {
776  aB2DRectangle = basegfx::B2DRectangle(left, top, right, bottom);
777  }
778  return aB2DRectangle;
779 }
780 
781 double PDFiumPageObjectImpl::getFontSize() { return FPDFTextObj_GetFontSize(mpPageObject); }
782 
783 OUString PDFiumPageObjectImpl::getFontName()
784 {
785  OUString sFontName;
786  const int nFontName = 80 + 1;
787  std::unique_ptr<char[]> pFontName(new char[nFontName]); // + terminating null
788  int nFontNameChars = FPDFTextObj_GetFontName(mpPageObject, pFontName.get(), nFontName);
789  if (nFontName >= nFontNameChars)
790  {
791  sFontName = OUString::createFromAscii(pFontName.get());
792  }
793  return sFontName;
794 }
795 
796 PDFTextRenderMode PDFiumPageObjectImpl::getTextRenderMode()
797 {
798  return static_cast<PDFTextRenderMode>(FPDFTextObj_GetTextRenderMode(mpPageObject));
799 }
800 
801 Color PDFiumPageObjectImpl::getFillColor()
802 {
803  Color aColor = COL_TRANSPARENT;
804  unsigned int nR, nG, nB, nA;
805  if (FPDFPageObj_GetFillColor(mpPageObject, &nR, &nG, &nB, &nA))
806  {
807  aColor = Color(ColorAlpha, nA, nR, nG, nB);
808  }
809  return aColor;
810 }
811 
812 Color PDFiumPageObjectImpl::getStrokeColor()
813 {
814  Color aColor = COL_TRANSPARENT;
815  unsigned int nR, nG, nB, nA;
816  if (FPDFPageObj_GetStrokeColor(mpPageObject, &nR, &nG, &nB, &nA))
817  {
818  aColor = Color(ColorAlpha, nA, nR, nG, nB);
819  }
820  return aColor;
821 }
822 
823 double PDFiumPageObjectImpl::getStrokeWidth()
824 {
825  float fWidth = 1;
826  FPDFPageObj_GetStrokeWidth(mpPageObject, &fWidth);
827  return fWidth;
828 }
829 
830 int PDFiumPageObjectImpl::getPathSegmentCount() { return FPDFPath_CountSegments(mpPageObject); }
831 
832 std::unique_ptr<PDFiumPathSegment> PDFiumPageObjectImpl::getPathSegment(int index)
833 {
834  std::unique_ptr<PDFiumPathSegment> pPDFiumPathSegment;
835  FPDF_PATHSEGMENT pPathSegment = FPDFPath_GetPathSegment(mpPageObject, index);
836  if (pPathSegment)
837  {
838  pPDFiumPathSegment = std::make_unique<PDFiumPathSegmentImpl>(pPathSegment);
839  }
840  return pPDFiumPathSegment;
841 }
842 
843 Size PDFiumPageObjectImpl::getImageSize(PDFiumPage& rPage)
844 {
845  FPDF_IMAGEOBJ_METADATA aMeta;
846  auto& rPageImpl = static_cast<PDFiumPageImpl&>(rPage);
847  FPDFImageObj_GetImageMetadata(mpPageObject, rPageImpl.getPointer(), &aMeta);
848  return Size(aMeta.width, aMeta.height);
849 }
850 
851 std::unique_ptr<PDFiumBitmap> PDFiumPageObjectImpl::getImageBitmap()
852 {
853  std::unique_ptr<PDFiumBitmap> pPDFiumBitmap;
854  FPDF_BITMAP pBitmap = FPDFImageObj_GetBitmap(mpPageObject);
855  if (pBitmap)
856  {
857  pPDFiumBitmap = std::make_unique<PDFiumBitmapImpl>(pBitmap);
858  }
859  return pPDFiumBitmap;
860 }
861 
862 bool PDFiumPageObjectImpl::getDrawMode(PDFFillMode& rFillMode, bool& rStroke)
863 {
864  auto nFillMode = static_cast<int>(rFillMode);
865  auto bStroke = static_cast<FPDF_BOOL>(rStroke);
866  bool bRet = FPDFPath_GetDrawMode(mpPageObject, &nFillMode, &bStroke);
867  rFillMode = static_cast<PDFFillMode>(nFillMode);
868  rStroke = static_cast<bool>(bStroke);
869  return bRet;
870 }
871 
872 BitmapChecksum PDFiumPageImpl::getChecksum(int nMDPPerm)
873 {
874  size_t nPageWidth = getWidth();
875  size_t nPageHeight = getHeight();
876  auto pPdfBitmap = std::make_unique<PDFiumBitmapImpl>(
877  FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1));
878  if (!pPdfBitmap)
879  {
880  return 0;
881  }
882 
883  int nFlags = 0;
884  if (nMDPPerm != 3)
885  {
886  // Annotations/commenting should affect the checksum, signature verification wants this.
887  nFlags = FPDF_ANNOT;
888  }
889  FPDF_RenderPageBitmap(pPdfBitmap->getPointer(), mpPage, /*start_x=*/0, /*start_y=*/0,
890  nPageWidth, nPageHeight,
891  /*rotate=*/0, nFlags);
892  Bitmap aBitmap(Size(nPageWidth, nPageHeight), vcl::PixelFormat::N24_BPP);
893  {
894  BitmapScopedWriteAccess pWriteAccess(aBitmap);
895  const auto pPdfBuffer
896  = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap->getPointer()));
897  const int nStride = FPDFBitmap_GetStride(pPdfBitmap->getPointer());
898  for (size_t nRow = 0; nRow < nPageHeight; ++nRow)
899  {
900  ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow);
901  pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride);
902  }
903  }
904  return aBitmap.GetChecksum();
905 }
906 
907 double PDFiumPageImpl::getWidth() { return FPDF_GetPageWidth(mpPage); }
908 
909 double PDFiumPageImpl::getHeight() { return FPDF_GetPageHeight(mpPage); }
910 
911 bool PDFiumPageImpl::hasTransparency() { return FPDFPage_HasTransparency(mpPage); }
912 
913 PDFiumPathSegmentImpl::PDFiumPathSegmentImpl(FPDF_PATHSEGMENT pPathSegment)
914  : mpPathSegment(pPathSegment)
915 {
916 }
917 
918 basegfx::B2DPoint PDFiumPathSegmentImpl::getPoint() const
919 {
920  basegfx::B2DPoint aPoint;
921  float fx, fy;
922  if (FPDFPathSegment_GetPoint(mpPathSegment, &fx, &fy))
923  aPoint = basegfx::B2DPoint(fx, fy);
924  return aPoint;
925 }
926 
927 bool PDFiumPathSegmentImpl::isClosed() const { return FPDFPathSegment_GetClose(mpPathSegment); }
928 
929 PDFSegmentType PDFiumPathSegmentImpl::getType() const
930 {
931  return static_cast<PDFSegmentType>(FPDFPathSegment_GetType(mpPathSegment));
932 }
933 
934 PDFiumBitmapImpl::PDFiumBitmapImpl(FPDF_BITMAP pBitmap)
935  : mpBitmap(pBitmap)
936 {
937 }
938 
939 PDFiumBitmapImpl::~PDFiumBitmapImpl()
940 {
941  if (mpBitmap)
942  {
943  FPDFBitmap_Destroy(mpBitmap);
944  }
945 }
946 
947 void PDFiumBitmapImpl::fillRect(int left, int top, int width, int height, sal_uInt32 nColor)
948 {
949  FPDFBitmap_FillRect(mpBitmap, left, top, width, height, nColor);
950 }
951 
952 void PDFiumBitmapImpl::renderPageBitmap(PDFiumPage* pPage, int nStartX, int nStartY, int nSizeX,
953  int nSizeY)
954 {
955  auto pPageImpl = static_cast<PDFiumPageImpl*>(pPage);
956  FPDF_RenderPageBitmap(mpBitmap, pPageImpl->getPointer(), nStartX, nStartY, nSizeX, nSizeY,
957  /*rotate=*/0, /*flags=*/0);
958 }
959 
960 ConstScanline PDFiumBitmapImpl::getBuffer()
961 {
962  return static_cast<ConstScanline>(FPDFBitmap_GetBuffer(mpBitmap));
963 }
964 
965 int PDFiumBitmapImpl::getStride() { return FPDFBitmap_GetStride(mpBitmap); }
966 
967 int PDFiumBitmapImpl::getWidth() { return FPDFBitmap_GetWidth(mpBitmap); }
968 
969 int PDFiumBitmapImpl::getHeight() { return FPDFBitmap_GetHeight(mpBitmap); }
970 
971 PDFBitmapType PDFiumBitmapImpl::getFormat()
972 {
973  return static_cast<PDFBitmapType>(FPDFBitmap_GetFormat(mpBitmap));
974 }
975 
976 PDFiumAnnotationImpl::PDFiumAnnotationImpl(FPDF_ANNOTATION pAnnotation)
977  : mpAnnotation(pAnnotation)
978 {
979 }
980 
981 PDFiumAnnotationImpl::~PDFiumAnnotationImpl()
982 {
983  if (mpAnnotation)
984  FPDFPage_CloseAnnot(mpAnnotation);
985 }
986 
987 PDFAnnotationSubType PDFiumAnnotationImpl::getSubType()
988 {
989  return PDFAnnotationSubType(FPDFAnnot_GetSubtype(mpAnnotation));
990 }
991 
992 basegfx::B2DRectangle PDFiumAnnotationImpl::getRectangle()
993 {
994  basegfx::B2DRectangle aB2DRectangle;
995  FS_RECTF aRect;
996  if (FPDFAnnot_GetRect(mpAnnotation, &aRect))
997  {
998  aB2DRectangle = basegfx::B2DRectangle(aRect.left, aRect.top, aRect.right, aRect.bottom);
999  }
1000  return aB2DRectangle;
1001 }
1002 
1004 {
1005  Color aColor = COL_TRANSPARENT;
1006  unsigned int nR, nG, nB, nA;
1007  if (FPDFAnnot_GetColor(mpAnnotation, FPDFANNOT_COLORTYPE_Color, &nR, &nG, &nB, &nA))
1008  {
1009  aColor = Color(ColorAlpha, nA, nR, nG, nB);
1010  }
1011  return aColor;
1012 }
1013 
1014 Color PDFiumAnnotationImpl::getInteriorColor()
1015 {
1016  Color aColor = COL_TRANSPARENT;
1017  unsigned int nR, nG, nB, nA;
1018  if (FPDFAnnot_GetColor(mpAnnotation, FPDFANNOT_COLORTYPE_InteriorColor, &nR, &nG, &nB, &nA))
1019  {
1020  aColor = Color(ColorAlpha, nA, nR, nG, nB);
1021  }
1022  return aColor;
1023 }
1024 
1025 size_t PDFiumAnnotationImpl::getAttachmentPointsCount()
1026 {
1027  return FPDFAnnot_CountAttachmentPoints(mpAnnotation);
1028 }
1029 
1030 std::vector<basegfx::B2DPoint> PDFiumAnnotationImpl::getAttachmentPoints(size_t nIndex)
1031 {
1032  std::vector<basegfx::B2DPoint> aQuads;
1033 
1034  FS_QUADPOINTSF aQuadpoints;
1035  if (FPDFAnnot_GetAttachmentPoints(mpAnnotation, nIndex, &aQuadpoints))
1036  {
1037  aQuads.emplace_back(aQuadpoints.x1, aQuadpoints.y1);
1038  aQuads.emplace_back(aQuadpoints.x2, aQuadpoints.y2);
1039  aQuads.emplace_back(aQuadpoints.x3, aQuadpoints.y3);
1040  aQuads.emplace_back(aQuadpoints.x4, aQuadpoints.y4);
1041  }
1042  return aQuads;
1043 }
1044 
1045 std::vector<basegfx::B2DPoint> PDFiumAnnotationImpl::getLineGeometry()
1046 {
1047  std::vector<basegfx::B2DPoint> aLine;
1048  FS_POINTF aStart;
1049  FS_POINTF aEnd;
1050  if (FPDFAnnot_GetLine(mpAnnotation, &aStart, &aEnd))
1051  {
1052  aLine.emplace_back(aStart.x, aStart.y);
1053  aLine.emplace_back(aEnd.x, aEnd.y);
1054  }
1055  return aLine;
1056 }
1057 
1058 namespace
1059 {
1060 bool getBorderProperties(FPDF_ANNOTATION mpAnnotation, float& rHorizontalCornerRadius,
1061  float& rVerticalCornerRadius, float& rBorderWidth)
1062 {
1063  float fHoriRadius = 0.0f;
1064  float fVertRadius = 0.0f;
1065  float fWidth = 0.0f;
1066 
1067  if (!FPDFAnnot_GetBorder(mpAnnotation, &fHoriRadius, &fVertRadius, &fWidth))
1068  return false;
1069 
1070  rHorizontalCornerRadius = fHoriRadius;
1071  rVerticalCornerRadius = fVertRadius;
1072  rBorderWidth = fWidth;
1073  return true;
1074 }
1075 }
1076 
1077 float PDFiumAnnotationImpl::getBorderWidth()
1078 {
1079  float fHorizontalCornerRadius;
1080  float fVerticalCornerRadius;
1081  float fBorderWidth;
1082 
1083  if (!getBorderProperties(mpAnnotation, fHorizontalCornerRadius, fVerticalCornerRadius,
1084  fBorderWidth))
1085  return 0.0f;
1086  return fBorderWidth;
1087 }
1088 
1089 basegfx::B2DSize PDFiumAnnotationImpl::getBorderCornerRadius()
1090 {
1091  float fHorizontalCornerRadius;
1092  float fVerticalCornerRadius;
1093  float fBorderWidth;
1094 
1095  if (!getBorderProperties(mpAnnotation, fHorizontalCornerRadius, fVerticalCornerRadius,
1096  fBorderWidth))
1097  return basegfx::B2DSize(0.0, 0.0);
1098  return basegfx::B2DSize(fHorizontalCornerRadius, fVerticalCornerRadius);
1099 }
1100 
1101 bool PDFiumAnnotationImpl::hasKey(OString const& rKey)
1102 {
1103  return FPDFAnnot_HasKey(mpAnnotation, rKey.getStr());
1104 }
1105 
1106 PDFObjectType PDFiumAnnotationImpl::getValueType(OString const& rKey)
1107 {
1108  return static_cast<PDFObjectType>(FPDFAnnot_GetValueType(mpAnnotation, rKey.getStr()));
1109 }
1110 
1111 OUString PDFiumAnnotationImpl::getString(OString const& rKey)
1112 {
1113  OUString rString;
1114  unsigned long nSize = FPDFAnnot_GetStringValue(mpAnnotation, rKey.getStr(), nullptr, 0);
1115  assert(nSize % 2 == 0);
1116  nSize /= 2;
1117  if (nSize > 1)
1118  {
1119  std::unique_ptr<sal_Unicode[]> pText(new sal_Unicode[nSize]);
1120  unsigned long nStringSize = FPDFAnnot_GetStringValue(
1121  mpAnnotation, rKey.getStr(), reinterpret_cast<FPDF_WCHAR*>(pText.get()), nSize * 2);
1122  assert(nStringSize % 2 == 0);
1123  nStringSize /= 2;
1124  if (nStringSize > 0)
1125  {
1126 #if defined OSL_BIGENDIAN
1127  // The data returned by FPDFAnnot_GetStringValue is documented to always be UTF-16LE:
1128  for (unsigned long i = 0; i != nStringSize; ++i)
1129  {
1130  pText[i] = OSL_SWAPWORD(pText[i]);
1131  }
1132 #endif
1133  rString = OUString(pText.get());
1134  }
1135  }
1136  return rString;
1137 }
1138 
1139 std::vector<std::vector<basegfx::B2DPoint>> PDFiumAnnotationImpl::getInkStrokes()
1140 {
1141  std::vector<std::vector<basegfx::B2DPoint>> aB2DPointList;
1142  int nInkStrokes = FPDFAnnot_GetInkListCount(mpAnnotation);
1143  for (int i = 0; i < nInkStrokes; i++)
1144  {
1145  std::vector<basegfx::B2DPoint> aB2DPoints;
1146  int nPoints = FPDFAnnot_GetInkListPath(mpAnnotation, i, nullptr, 0);
1147  if (nPoints)
1148  {
1149  std::vector<FS_POINTF> aPoints(nPoints);
1150  if (FPDFAnnot_GetInkListPath(mpAnnotation, i, aPoints.data(), aPoints.size()))
1151  {
1152  for (auto const& rPoint : aPoints)
1153  {
1154  aB2DPoints.emplace_back(rPoint.x, rPoint.y);
1155  }
1156  aB2DPointList.push_back(aB2DPoints);
1157  }
1158  }
1159  }
1160  return aB2DPointList;
1161 }
1162 
1163 std::vector<basegfx::B2DPoint> PDFiumAnnotationImpl::getVertices()
1164 {
1165  std::vector<basegfx::B2DPoint> aB2DPoints;
1166  int nPoints = FPDFAnnot_GetVertices(mpAnnotation, nullptr, 0);
1167  if (nPoints)
1168  {
1169  std::vector<FS_POINTF> aPoints(nPoints);
1170  if (FPDFAnnot_GetVertices(mpAnnotation, aPoints.data(), aPoints.size()))
1171  {
1172  for (auto const& rPoint : aPoints)
1173  aB2DPoints.emplace_back(rPoint.x, rPoint.y);
1174  }
1175  }
1176  return aB2DPoints;
1177 }
1178 
1179 std::unique_ptr<PDFiumAnnotation> PDFiumAnnotationImpl::getLinked(OString const& rKey)
1180 {
1181  std::unique_ptr<PDFiumAnnotation> pPDFiumAnnotation;
1182  FPDF_ANNOTATION pAnnotation = FPDFAnnot_GetLinkedAnnot(mpAnnotation, rKey.getStr());
1183  if (pAnnotation)
1184  {
1185  pPDFiumAnnotation = std::make_unique<PDFiumAnnotationImpl>(pAnnotation);
1186  }
1187  return pPDFiumAnnotation;
1188 }
1189 
1190 int PDFiumAnnotationImpl::getObjectCount() { return FPDFAnnot_GetObjectCount(mpAnnotation); }
1191 
1192 std::unique_ptr<PDFiumPageObject> PDFiumAnnotationImpl::getObject(int nIndex)
1193 {
1194  std::unique_ptr<PDFiumPageObject> pPDFiumPageObject;
1195  FPDF_PAGEOBJECT pPageObject = FPDFAnnot_GetObject(mpAnnotation, nIndex);
1196  if (pPageObject)
1197  {
1198  pPDFiumPageObject = std::make_unique<PDFiumPageObjectImpl>(pPageObject);
1199  }
1200  return pPDFiumPageObject;
1201 }
1202 
1203 PDFiumTextPageImpl::PDFiumTextPageImpl(FPDF_TEXTPAGE pTextPage)
1204  : mpTextPage(pTextPage)
1205 {
1206 }
1207 
1208 PDFiumTextPageImpl::~PDFiumTextPageImpl()
1209 {
1210  if (mpTextPage)
1211  FPDFText_ClosePage(mpTextPage);
1212 }
1213 
1214 int PDFiumTextPageImpl::countChars() { return FPDFText_CountChars(mpTextPage); }
1215 
1216 basegfx::B2DRectangle PDFiumTextPageImpl::getCharBox(int nIndex, double fPageHeight)
1217 {
1218  double left = 0.0;
1219  double right = 0.0;
1220  double bottom = 0.0;
1221  double top = 0.0;
1222 
1223  if (FPDFText_GetCharBox(mpTextPage, nIndex, &left, &right, &bottom, &top))
1224  {
1225  left = convertPointToMm100(left);
1226  right = convertPointToMm100(right);
1227  top = fPageHeight - convertPointToMm100(top);
1228  bottom = fPageHeight - convertPointToMm100(bottom);
1229 
1230  return basegfx::B2DRectangle(left, bottom, right, top);
1231  }
1232 
1233  return basegfx::B2DRectangle();
1234 }
1235 
1236 unsigned int PDFiumTextPageImpl::getUnicode(int index)
1237 {
1238  return FPDFText_GetUnicode(mpTextPage, index);
1239 }
1240 
1241 std::unique_ptr<PDFiumSearchHandle>
1242 PDFiumTextPageImpl::findStart(const OUString& rFindWhat, PDFFindFlags nFlags, sal_Int32 nStartIndex)
1243 {
1244  FPDF_WIDESTRING pFindWhat = reinterpret_cast<FPDF_WIDESTRING>(rFindWhat.getStr());
1245  return std::make_unique<vcl::pdf::PDFiumSearchHandleImpl>(
1246  FPDFText_FindStart(mpTextPage, pFindWhat, static_cast<sal_uInt32>(nFlags), nStartIndex));
1247 }
1248 
1249 PDFiumSearchHandleImpl::PDFiumSearchHandleImpl(FPDF_SCHHANDLE pSearchHandle)
1250  : mpSearchHandle(pSearchHandle)
1251 {
1252 }
1253 
1254 PDFiumSearchHandleImpl::~PDFiumSearchHandleImpl()
1255 {
1256  if (mpSearchHandle)
1257  FPDFText_FindClose(mpSearchHandle);
1258 }
1259 
1260 bool PDFiumSearchHandleImpl::findNext() { return FPDFText_FindNext(mpSearchHandle); }
1261 
1262 bool PDFiumSearchHandleImpl::findPrev() { return FPDFText_FindPrev(mpSearchHandle); }
1263 
1264 int PDFiumSearchHandleImpl::getSearchResultIndex()
1265 {
1266  return FPDFText_GetSchResultIndex(mpSearchHandle);
1267 }
1268 
1269 int PDFiumSearchHandleImpl::getSearchCount() { return FPDFText_GetSchCount(mpSearchHandle); }
1270 
1271 std::shared_ptr<PDFium>& PDFiumLibrary::get()
1272 {
1273  static std::shared_ptr<PDFium> pInstance = std::make_shared<PDFiumImpl>();
1274  return pInstance;
1275 }
1276 
1277 } // end vcl::pdf
1278 
1279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt64 BitmapChecksum
Definition: checksum.hxx:30
sal_uInt64 left
bool getType(BSTR name, Type &type)
constexpr::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
This template handles BitmapAccess the RAII way.
B2DRange B2DRectangle
FPDF_BITMAP mpBitmap
sal_uInt16 sal_Unicode
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
B2DVector B2DSize
void fillRect(const ::cppcanvas::CanvasSharedPtr &rCanvas, const ::basegfx::B2DRectangle &rRect,::cppcanvas::IntSRGBA aFillColor)
def right
int i
FPDF_TEXTPAGE mpTextPage
FPDF_PAGE mpPage
FPDF_ANNOTATION mpAnnotation
std::size_t WriteBytes(const void *pData, std::size_t nSize)
FPDF_PAGEOBJECT mpPageObject
static BitmapColor getColor(BitmapReadAccess *pReadAcc, tools::Long nZ)
const sal_uInt8 * ConstScanline
Definition: Scanline.hxx:26
constexpr auto convertPointToMm100(N n)
sal_Int32 getPageCount(const uno::Reference< frame::XModel > &xModel)
FPDF_DOCUMENT mpPdfDocument
FPDF_PATHSEGMENT mpPathSegment
FPDF_SCHHANDLE mpSearchHandle
OUString getString(const Any &_rAny)
FPDF_SIGNATURE mpSignature
OUString maLastError
static B2DHomMatrix abcdef(double da, double db, double dc, double dd, double de, double df)