diff options
-rw-r--r-- | include/vcl/filter/PDFiumLibrary.hxx | 22 | ||||
-rw-r--r-- | vcl/qa/cppunit/PDFiumLibraryTest.cxx | 39 | ||||
-rw-r--r-- | vcl/qa/cppunit/data/form-fields.pdf | 95 | ||||
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 2 | ||||
-rw-r--r-- | vcl/source/pdf/PDFiumLibrary.cxx | 25 |
5 files changed, 179 insertions, 4 deletions
diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx index 8d139889591a..c61860b3a530 100644 --- a/include/vcl/filter/PDFiumLibrary.hxx +++ b/include/vcl/filter/PDFiumLibrary.hxx @@ -31,6 +31,7 @@ #include <vcl/pdf/PDFPageObjectType.hxx> #include <fpdf_doc.h> +#include <fpdf_formfill.h> class SvMemoryStream; @@ -79,7 +80,8 @@ public: ~PDFiumBitmap(); FPDF_BITMAP getPointer() { return mpBitmap; } void fillRect(int left, int top, int width, int height, sal_uInt32 nColor); - void renderPageBitmap(PDFiumPage* pPage, int nStartX, int nStartY, int nSizeX, int nSizeY); + void renderPageBitmap(PDFiumDocument* pDoc, PDFiumPage* pPage, int nStartX, int nStartY, + int nSizeX, int nSizeY); ConstScanline getBuffer(); int getStride(); }; @@ -244,10 +246,27 @@ public: FPDF_SIGNATURE getPointer() { return mpSignature; } }; +/// Wrapper around FPDF_FORMHANDLE. +class PDFiumFormHandle final +{ +private: + FPDF_FORMHANDLE mpHandle; + + PDFiumFormHandle(const PDFiumFormHandle&) = delete; + PDFiumFormHandle& operator=(const PDFiumFormHandle&) = delete; + +public: + PDFiumFormHandle(FPDF_FORMHANDLE pHandle); + ~PDFiumFormHandle(); + FPDF_FORMHANDLE getPointer(); +}; + class VCL_DLLPUBLIC PDFiumDocument final { private: FPDF_DOCUMENT mpPdfDocument; + FPDF_FORMFILLINFO m_aFormCallbacks; + std::unique_ptr<PDFiumFormHandle> m_pFormHandle; private: PDFiumDocument(const PDFiumDocument&) = delete; @@ -256,6 +275,7 @@ private: public: PDFiumDocument(FPDF_DOCUMENT pPdfDocument); ~PDFiumDocument(); + FPDF_FORMHANDLE getFormHandlePointer(); // Page size in points basegfx::B2DSize getPageSize(int nIndex); diff --git a/vcl/qa/cppunit/PDFiumLibraryTest.cxx b/vcl/qa/cppunit/PDFiumLibraryTest.cxx index 577f73ed1130..9ae14625b4f7 100644 --- a/vcl/qa/cppunit/PDFiumLibraryTest.cxx +++ b/vcl/qa/cppunit/PDFiumLibraryTest.cxx @@ -25,6 +25,8 @@ #include <tools/stream.hxx> #include <vcl/filter/PDFiumLibrary.hxx> +#include <vcl/pdfread.hxx> +#include <vcl/bitmapaccess.hxx> class PDFiumLibraryTest : public test::BootstrapFixtureBase { @@ -40,6 +42,7 @@ class PDFiumLibraryTest : public test::BootstrapFixtureBase void testAnnotationsMadeInAcrobat(); void testAnnotationsDifferentTypes(); void testTools(); + void testFormFields(); CPPUNIT_TEST_SUITE(PDFiumLibraryTest); CPPUNIT_TEST(testDocument); @@ -49,6 +52,7 @@ class PDFiumLibraryTest : public test::BootstrapFixtureBase CPPUNIT_TEST(testAnnotationsMadeInAcrobat); CPPUNIT_TEST(testAnnotationsDifferentTypes); CPPUNIT_TEST(testTools); + CPPUNIT_TEST(testFormFields); CPPUNIT_TEST_SUITE_END(); }; @@ -291,6 +295,41 @@ void PDFiumLibraryTest::testAnnotationsMadeInAcrobat() } } +void PDFiumLibraryTest::testFormFields() +{ + // Given a document with a form field that looks like plain text: + OUString aURL = getFullUrl(u"form-fields.pdf"); + SvFileStream aFileStream(aURL, StreamMode::READ); + SvMemoryStream aMemory; + aMemory.WriteStream(aFileStream); + aMemory.Seek(0); + + // When rendering its first (and only) page to a bitmap: + std::vector<BitmapEx> aBitmaps; + int nRet = vcl::RenderPDFBitmaps(aMemory.GetData(), aMemory.GetSize(), aBitmaps); + CPPUNIT_ASSERT(nRet); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aBitmaps.size()); + + // Then make sure the bitmap contains that text: + Bitmap aBitmap = aBitmaps[0].GetBitmap(); + BitmapReadAccess aAccess(aBitmap); + Size aSize = aBitmap.GetSizePixel(); + std::set<sal_uInt32> aColors; + for (tools::Long y = 0; y < aSize.Height(); ++y) + { + for (tools::Long x = 0; x < aSize.Width(); ++x) + { + aColors.insert(static_cast<sal_uInt32>(aAccess.GetPixel(y, x))); + } + } + // Without the accompanying fix in place, this test would have failed with: + // - Expected greater than: 1 + // - Actual : 1 + // i.e. at least black text and white background is expected (possibly more, due to + // anti-aliasing), but nothing was rendered. + CPPUNIT_ASSERT_GREATER(static_cast<size_t>(1), aColors.size()); +} + void PDFiumLibraryTest::testAnnotationsDifferentTypes() { OUString aURL = getFullUrl("PangramWithMultipleTypeOfAnnotations.pdf"); diff --git a/vcl/qa/cppunit/data/form-fields.pdf b/vcl/qa/cppunit/data/form-fields.pdf new file mode 100644 index 000000000000..a014b36c9821 --- /dev/null +++ b/vcl/qa/cppunit/data/form-fields.pdf @@ -0,0 +1,95 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 5 0 R +>> +endobj + +2 0 obj << + /Length 0 +>> +stream +endstream +endobj + +3 0 obj << + /Font << + /TT1 4 0 R + >> +>> +endobj + +4 0 obj << + /Type /Font + /Subtype /Type1 + /Name /TT1 + /BaseFont/Helvetica +>> +endobj + +5 0 obj << + /Type /Pages + /Kids [6 0 R] + /Count 1 + /MediaBox [ 0 0 612 446 ] +>> +endobj + +6 0 obj << + /Type /Page + /Parent 5 0 R + /Resources 3 0 R + /Contents 2 0 R + /Annots [7 0 R] +>> +endobj + +7 0 obj << + /Type /Annot + /Subtype /Widget + /T (T) + /V (V) + /DA (/Helv 0 Tf 0 g) + /Rect [ 0 0 612 446 ] + /FT /Tx + /AP << + /N 8 0 R + >> +>> +endobj + +8 0 obj << + /Type /XObject + /Subtype /Form + /Matrix [1.0 0.0 0.0 1.0 0.0 0.0] + /Resources 3 0 R + /BBox [ 0 0 612 446 ] + /Length 55 +>> +stream + BT + /TT1 24 Tf + 1 0 0 1 260 254 Tm + (test)Tj + ET +endstream +endobj +xref +0 9 +0000000000 65535 f +0000000015 00000 n +0000000069 00000 n +0000000121 00000 n +0000000174 00000 n +0000000259 00000 n +0000000351 00000 n +0000000458 00000 n +0000000616 00000 n +trailer << + /Root 1 0 R + /Size 9 +>> +startxref +836 +%%EOF diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 80f207a68196..bd5f4c3a7b21 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -182,7 +182,7 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector<BitmapEx>& r } const sal_uInt32 nColor = bTransparent ? 0x00000000 : 0xFFFFFFFF; pPdfBitmap->fillRect(0, 0, nPageWidth, nPageHeight, nColor); - pPdfBitmap->renderPageBitmap(pPdfPage.get(), /*start_x=*/0, + pPdfBitmap->renderPageBitmap(pPdfDocument.get(), pPdfPage.get(), /*start_x=*/0, /*start_y=*/0, nPageWidth, nPageHeight); // Save the buffer as a bitmap. diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx index 3e9ae64dc950..76a70ad107b1 100644 --- a/vcl/source/pdf/PDFiumLibrary.cxx +++ b/vcl/source/pdf/PDFiumLibrary.cxx @@ -20,6 +20,7 @@ #include <fpdf_text.h> #include <fpdf_save.h> #include <fpdf_signature.h> +#include <fpdf_formfill.h> #include <osl/endian.h> #include <vcl/bitmap.hxx> @@ -198,15 +199,22 @@ PDFiumSignature::PDFiumSignature(FPDF_SIGNATURE pSignature) PDFiumDocument::PDFiumDocument(FPDF_DOCUMENT pPdfDocument) : mpPdfDocument(pPdfDocument) + , m_aFormCallbacks() { + m_aFormCallbacks.version = 1; + m_pFormHandle = std::make_unique<PDFiumFormHandle>( + FPDFDOC_InitFormFillEnvironment(pPdfDocument, &m_aFormCallbacks)); } PDFiumDocument::~PDFiumDocument() { + m_pFormHandle.reset(); if (mpPdfDocument) FPDF_CloseDocument(mpPdfDocument); } +FPDF_FORMHANDLE PDFiumDocument::getFormHandlePointer() { return m_pFormHandle->getPointer(); } + std::unique_ptr<PDFiumPage> PDFiumDocument::openPage(int nIndex) { std::unique_ptr<PDFiumPage> pPDFiumPage; @@ -524,6 +532,15 @@ bool PDFiumPathSegment::isClosed() const { return FPDFPathSegment_GetClose(mpPat int PDFiumPathSegment::getType() const { return FPDFPathSegment_GetType(mpPathSegment); } +PDFiumFormHandle::PDFiumFormHandle(FPDF_FORMHANDLE pHandle) + : mpHandle(pHandle) +{ +} + +PDFiumFormHandle::~PDFiumFormHandle() { FPDFDOC_ExitFormFillEnvironment(mpHandle); } + +FPDF_FORMHANDLE PDFiumFormHandle::getPointer() { return mpHandle; } + PDFiumBitmap::PDFiumBitmap(FPDF_BITMAP pBitmap) : mpBitmap(pBitmap) { @@ -542,11 +559,15 @@ void PDFiumBitmap::fillRect(int left, int top, int width, int height, sal_uInt32 FPDFBitmap_FillRect(mpBitmap, left, top, width, height, nColor); } -void PDFiumBitmap::renderPageBitmap(PDFiumPage* pPage, int nStartX, int nStartY, int nSizeX, - int nSizeY) +void PDFiumBitmap::renderPageBitmap(PDFiumDocument* pDoc, PDFiumPage* pPage, int nStartX, + int nStartY, int nSizeX, int nSizeY) { FPDF_RenderPageBitmap(mpBitmap, pPage->getPointer(), nStartX, nStartY, nSizeX, nSizeY, /*rotate=*/0, /*flags=*/0); + + // Render widget annotations for FormFields. + FPDF_FFLDraw(pDoc->getFormHandlePointer(), mpBitmap, pPage->getPointer(), nStartX, nStartY, + nSizeX, nSizeY, /*rotate=*/0, /*flags=*/0); } ConstScanline PDFiumBitmap::getBuffer() |