/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
int nTable(0); for (constauto& rDocElement : aDocument.GetElements())
{ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get()); if (!pObject) continue;
auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"_ostr)); if (pType && pType->GetValue() == "StructElem")
{ auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"_ostr)); if (pS && pS->GetValue() == "Table")
{ auto pKids = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject->Lookup("K"_ostr));
CPPUNIT_ASSERT(pKids);
// In the first table, the caption element is the first child element // In the second table, the caption element is the last child element // In the third table, the caption element is the first child element int nId = 0; if (nTable == 1) // second table
nId = pKids->GetElements().size() - 1; elseif (nTable == 2) // third table
nId = 0;
auto pTableKids = pKids->GetElements(); auto pRefKid = dynamic_cast<vcl::filter::PDFReferenceElement*>(pTableKids[nId]);
CPPUNIT_ASSERT(pRefKid); auto pObj = pRefKid->LookupObject();
CPPUNIT_ASSERT(pObj); auto pType1 = dynamic_cast<vcl::filter::PDFNameElement*>(pObj->Lookup("Type"_ostr));
CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1->GetValue()); auto pS1 = dynamic_cast<vcl::filter::PDFNameElement*>(pObj->Lookup("S"_ostr));
CPPUNIT_ASSERT_EQUAL("TableCaption"_ostr, pS1->GetValue());
auto pKids2 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObj->Lookup("K"_ostr));
CPPUNIT_ASSERT(pKids2);
// The captions of Table1, Table2 and Table3 also have two standard elements
CPPUNIT_ASSERT_EQUAL(size_t(2), pKids2->GetElements().size());
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
for (constauto& rDocElement : aDocument.GetElements())
{ auto pObj = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get()); if (!pObj) continue;
auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObj->Lookup("Type"_ostr)); if (pType && pType->GetValue() == "XObject")
{ auto pFilter = dynamic_cast<vcl::filter::PDFNameElement*>(pObj->Lookup("Filter"_ostr));
CPPUNIT_ASSERT(pFilter);
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf124272)
{ // Import the bugdoc and export as PDF.
vcl::filter::PDFDocument aDocument;
load(u"tdf124272.odt", aDocument);
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
// The page has a stream.
vcl::filter::PDFObjectElement* pContents = aPages[0]->LookupObject("Contents"_ostr);
CPPUNIT_ASSERT(pContents);
vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
CPPUNIT_ASSERT(pStream);
SvMemoryStream& rObjectStream = pStream->GetMemory(); // Uncompress it.
SvMemoryStream aUncompressed;
ZCodec aZCodec;
aZCodec.BeginCompression();
rObjectStream.Seek(0);
aZCodec.Decompress(rObjectStream, aUncompressed);
CPPUNIT_ASSERT(aZCodec.EndCompression());
OString aBitmap("Q q 299.899 782.189 m\n" "55.2 435.889 l 299.899 435.889 l 299.899 782.189 l\n" "h"_ostr);
auto pStart = static_cast<constchar*>(aUncompressed.GetData()); constchar* pEnd = pStart + aUncompressed.GetSize(); auto it = std::search(pStart, pEnd, aBitmap.getStr(), aBitmap.getStr() + aBitmap.getLength());
CPPUNIT_ASSERT(it != pEnd);
}
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
// Get access to the only image on the only page.
vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr);
CPPUNIT_ASSERT(pResources); auto pXObjects
= dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"_ostr));
CPPUNIT_ASSERT(pXObjects);
CPPUNIT_ASSERT_EQUAL(size_t(1), pXObjects->GetItems().size());
vcl::filter::PDFObjectElement* pXObject
= pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
CPPUNIT_ASSERT(pXObject);
vcl::filter::PDFStreamElement* pStream = pXObject->GetStream();
CPPUNIT_ASSERT(pStream);
SvMemoryStream& rObjectStream = pStream->GetMemory();
// The image should be grayscale 8bit JPEG.
sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME);
CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND);
CPPUNIT_ASSERT_EQUAL(jpegFormat, format);
BitmapEx aBitmap = aGraphic.GetBitmapEx();
CPPUNIT_ASSERT_EQUAL(tools::Long(200), aBitmap.GetSizePixel().Width());
CPPUNIT_ASSERT_EQUAL(tools::Long(300), aBitmap.GetSizePixel().Height());
CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat()); // tdf#121615 was caused by broken handling of data width with 8bit color, // so the test image has some black in the bottomright corner, check it's there
CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 0));
CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 299));
CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(199, 0));
CPPUNIT_ASSERT_EQUAL(COL_BLACK, aBitmap.GetPixelColor(199, 299));
}
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
// Get access to the only image on the only page.
vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr);
CPPUNIT_ASSERT(pResources); auto pXObjects
= dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"_ostr));
CPPUNIT_ASSERT(pXObjects);
CPPUNIT_ASSERT_EQUAL(size_t(1), pXObjects->GetItems().size());
vcl::filter::PDFObjectElement* pXObject
= pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
CPPUNIT_ASSERT(pXObject);
vcl::filter::PDFStreamElement* pStream = pXObject->GetStream();
CPPUNIT_ASSERT(pStream);
SvMemoryStream& rObjectStream = pStream->GetMemory();
for (tools::Long nX = 0; nX < aSize.Width(); ++nX)
{ for (tools::Long nY = 0; nY < aSize.Height(); ++nY)
{ // Check all pixels in the image are white // Without the fix in place, this test would have failed with // - Expected: Color: R:255 G:255 B:255 A:0 // - Actual : Color: R:0 G:0 B:0 A:0
CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(nX, nY));
}
}
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf161346)
{ // this crashed
vcl::filter::PDFDocument aDocument;
load(u"fdo47811-1_Word2013.docx", aDocument);
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf129085)
{
uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence({ // if the Quality is too high (like 90) then the image will be a DIB, // not a JPEG! 80 works currently but set it lower to be sure...
{ "Quality", uno::Any(sal_Int32(50)) },
}));
aMediaDescriptor[u"FilterData"_ustr] <<= aFilterData;
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
// Get access to the only image on the only page.
vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr);
CPPUNIT_ASSERT(pResources); auto pXObjects
= dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"_ostr));
// Without the fix in place, this test would have failed here
CPPUNIT_ASSERT(pXObjects);
CPPUNIT_ASSERT_EQUAL(size_t(1), pXObjects->GetItems().size());
vcl::filter::PDFObjectElement* pXObject
= pXObjects->LookupObject(pXObjects->GetItems().begin()->first);
CPPUNIT_ASSERT(pXObject);
vcl::filter::PDFStreamElement* pStream = pXObject->GetStream();
CPPUNIT_ASSERT(pStream);
SvMemoryStream& rObjectStream = pStream->GetMemory();
// Ensure there is a link on the first page (in the ToC). // Without the accompanying fix in place, this test would have failed, as the page contained no // links.
CPPUNIT_ASSERT(pPdfPage->hasLinks());
}
// Make sure we don't scale down a tiny bitmap.
std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap = pPageObject->getImageBitmap();
CPPUNIT_ASSERT(pBitmap); int nWidth = pBitmap->getWidth(); int nHeight = pBitmap->getHeight(); // Without the accompanying fix in place, this test would have failed with: // - Expected: 16 // - Actual : 6 // i.e. the image was scaled down to 300 DPI, even if it had tiny size.
CPPUNIT_ASSERT_EQUAL(16, nWidth);
CPPUNIT_ASSERT_EQUAL(16, nHeight);
}
// Without the fix in place, this test would have failed with // - Expected: 13 // - Actual : 0
CPPUNIT_ASSERT_EQUAL(13, pPdfPage->getObjectCount());
}
int nPageObjectCount = pPdfPage->getObjectCount(); // Without the fix in place, this test would have failed with // - Expected: 15 // - Actual : 16
CPPUNIT_ASSERT_EQUAL(16, nPageObjectCount);
int nYellowPathCount = 0; int nBlackPathCount = 0; int nGrayPathCount = 0; int nRedPathCount = 0; for (int i = 0; i < nPageObjectCount; ++i)
{
std::unique_ptr<vcl::pdf::PDFiumPageObject> pPdfPageObject = pPdfPage->getObject(i); if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path) continue;
int nSegments = pPdfPageObject->getPathSegmentCount();
CPPUNIT_ASSERT_EQUAL(5, nSegments);
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf147027)
{ // FIXME: the DPI check should be removed when either (1) the test is fixed to work with // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. if (!IsDefaultDPI()) return;
// Without the fix in place, this test would have failed with // - Expected: 778 // - Actual : 40
CPPUNIT_ASSERT_EQUAL(778, pPdfPage->getObjectCount());
}
// Without the fix in place, this test would have failed with // - Expected: 55 // - Actual : 0
CPPUNIT_ASSERT_EQUAL(55, pPdfPage->getObjectCount());
}
// Without the fix in place, this test would have failed with // - Expected: 22 // - Actual : 16
CPPUNIT_ASSERT_EQUAL(22, pPdfPage->getObjectCount());
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReduceImage)
{ // Load the Writer document.
loadFromFile(u"reduce-image.fodt");
// Save as PDF.
uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
uno::Reference<document::XFilter> xFilter(
xFactory->createInstance(u"com.sun.star.document.PDFFilter"_ustr), uno::UNO_QUERY);
uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
xExporter->setSourceDocument(mxComponent);
// This is intentionally in an "unlucky" order, output stream comes before filter data.
uno::Sequence<beans::PropertyValue> aDescriptor(comphelper::InitPropertySequence({
{ "FilterName", uno::Any(u"writer_pdf_Export"_ustr) },
{ "OutputStream", uno::Any(xOutputStream) },
{ "FilterData", uno::Any(aFilterData) },
}));
xFilter->filter(aDescriptor);
aOutputStream.Close();
// Parse the PDF: get the image.
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
CPPUNIT_ASSERT(pPdfPage);
CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pPageObject->getType());
// Make sure we don't scale down a bitmap.
std::unique_ptr<vcl::pdf::PDFiumBitmap> pBitmap = pPageObject->getImageBitmap();
CPPUNIT_ASSERT(pBitmap); int nWidth = pBitmap->getWidth(); int nHeight = pBitmap->getHeight(); // Without the accompanying fix in place, this test would have failed with: // - Expected: 160 // - Actual : 6 // i.e. the image was scaled down even with ReduceImageResolution=false.
CPPUNIT_ASSERT_EQUAL(160, nWidth);
CPPUNIT_ASSERT_EQUAL(160, nHeight);
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testLinkWrongPage)
{ // Import the bugdoc and export as PDF.
saveAsPDF(u"link-wrong-page.odp");
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
// The document has 2 pages.
CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
// First page should have 1 link (2nd slide, 1st was hidden).
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
CPPUNIT_ASSERT(pPdfPage);
// Without the accompanying fix in place, this test would have failed, as the link of the first // page went to the second page due to the hidden first slide.
CPPUNIT_ASSERT(pPdfPage->hasLinks());
// Second page should have no links (3rd slide).
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1);
CPPUNIT_ASSERT(pPdfPage2);
CPPUNIT_ASSERT(!pPdfPage2->hasLinks());
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testLinkWrongPagePartial)
{ // Given a Draw document with 3 pages, a link on the 2nd page: // When exporting that the 2nd and 3rd page to pdf:
uno::Sequence<beans::PropertyValue> aFilterData = {
comphelper::makePropertyValue(u"PageRange"_ustr, u"2-3"_ustr),
};
aMediaDescriptor[u"FilterData"_ustr] <<= aFilterData;
saveAsPDF(u"link-wrong-page-partial.odg");
// Then make sure the we have a link on the 1st page, but not on the 2nd one:
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
CPPUNIT_ASSERT(pPdfPage); // Without the accompanying fix in place, this test would have failed, as the link was on the // 2nd page instead.
CPPUNIT_ASSERT(pPdfPage->hasLinks());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1);
CPPUNIT_ASSERT(pPdfPage2);
CPPUNIT_ASSERT(!pPdfPage2->hasLinks());
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPageRange)
{ // Given a document with 3 pages: // When exporting that document to PDF, skipping the first page:
aMediaDescriptor[u"FilterOptions"_ustr]
<<= u"{\"PageRange\":{\"type\":\"string\",\"value\":\"2-\"}}"_ustr;
saveAsPDF(u"link-wrong-page-partial.odg");
// Then make sure the resulting PDF has 2 pages:
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport(); // Without the accompanying fix in place, this test would have failed with: // - Expected: 2 // - Actual : 3 // i.e. FilterOptions was ignored.
CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount());
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testLargePage)
{ // Import the bugdoc and export as PDF.
saveAsPDF(u"6m-wide.odg");
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
// The document has 1 page.
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); // Check the value (not the unit) of the page size.
basegfx::B2DSize aSize = pPdfDocument->getPageSize(0); // Without the accompanying fix in place, this test would have failed with: // - Expected: 8503.94 // - Actual : 17007.875 // i.e. the value for 600 cm was larger than the 14 400 limit set in the spec.
CPPUNIT_ASSERT_DOUBLES_EQUAL(8503.94, aSize.getWidth(), 0.01);
}
// Make sure that the page -> form -> form has a child image.
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
CPPUNIT_ASSERT(pPdfPage);
CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount());
std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPdfPage->getObject(0);
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType()); // 2: white background and the actual object.
CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount());
std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(1);
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pFormObject->getType()); // Without the accompanying fix in place, this test would have failed with: // - Expected: 1 // - Actual : 0 // i.e. the sub-form was missing its image.
CPPUNIT_ASSERT_EQUAL(1, pFormObject->getFormObjectCount());
// Check if the inner form object (original page object in the pdf image) has the correct // rotation.
std::unique_ptr<vcl::pdf::PDFiumPageObject> pInnerFormObject = pFormObject->getFormObject(0);
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pInnerFormObject->getType());
CPPUNIT_ASSERT_EQUAL(1, pInnerFormObject->getFormObjectCount());
std::unique_ptr<vcl::pdf::PDFiumPageObject> pImage = pInnerFormObject->getFormObject(0);
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pImage->getType());
basegfx::B2DHomMatrix aMat = pInnerFormObject->getMatrix();
basegfx::B2DTuple aScale;
basegfx::B2DTuple aTranslate; double fRotate = 0; double fShearX = 0;
aMat.decompose(aScale, aTranslate, fRotate, fShearX); int nRotateDeg = basegfx::rad2deg(fRotate); // Without the accompanying fix in place, this test would have failed with: // - Expected: -90 // - Actual : 0 // i.e. rotation was lost on pdf export.
CPPUNIT_ASSERT_EQUAL(-90, nRotateDeg);
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testDefaultVersion)
{ // Create an empty document.
loadFromURL(u"private:factory/swriter"_ustr);
// Save as PDF.
aMediaDescriptor[u"FilterName"_ustr] <<= u"writer_pdf_Export"_ustr;
saveWithParams(aMediaDescriptor.getAsConstPropertyValueList());
// Parse the export result.
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport(); int nFileVersion = pPdfDocument->getFileVersion();
CPPUNIT_ASSERT_EQUAL(17, nFileVersion);
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testVersion15)
{ // Create an empty document.
loadFromURL(u"private:factory/swriter"_ustr);
// Save as PDF.
uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence(
{ { "SelectPdfVersion", uno::Any(static_cast<sal_Int32>(15)) } }));
aMediaDescriptor[u"FilterName"_ustr] <<= u"writer_pdf_Export"_ustr;
aMediaDescriptor[u"FilterData"_ustr] <<= aFilterData;
saveWithParams(aMediaDescriptor.getAsConstPropertyValueList());
// Parse the export result.
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport(); int nFileVersion = pPdfDocument->getFileVersion();
CPPUNIT_ASSERT_EQUAL(15, nFileVersion);
}
// Parse the export result.
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport(); int nFileVersion = pPdfDocument->getFileVersion();
CPPUNIT_ASSERT_EQUAL(20, nFileVersion);
}
// Check round-trip of importing and exporting the PDF with PDFium filter, // which imports the PDF document as multiple PDFs as graphic object. // Each page in the document has one PDF graphic object which content is // the corresponding page in the PDF. When such a document is exported, // the PDF graphic gets embedded into the exported PDF document (as a // Form XObject).
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testMultiPagePDF)
{ // setenv only works on unix based systems #ifndef _WIN32 // We need to enable PDFium import (and make sure to disable after the test) bool bResetEnvVar = false; if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
{
bResetEnvVar = true;
setenv("LO_IMPORT_USE_PDFIUM", "1", false);
}
comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { if (bResetEnvVar)
unsetenv("LO_IMPORT_USE_PDFIUM");
});
// Load the PDF and save as PDF
vcl::filter::PDFDocument aDocument;
load(u"SimpleMultiPagePDF.pdf", aDocument);
// Just check that the size of the page stream is what is expected.
CPPUNIT_ASSERT_EQUAL(sal_uInt64(355), aUncompressed.Tell());
} #endif
}
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFormFontName)
{ // Import the bugdoc and export as PDF.
uno::Sequence<beans::PropertyValue> aFilterData(comphelper::InitPropertySequence({
{ "ExportFormFields", uno::Any(true) },
}));
aMediaDescriptor[u"FilterData"_ustr] <<= aFilterData;
saveAsPDF(u"form-font-name.odt");
// Parse the export result with pdfium.
std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
// The document has one page.
CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
CPPUNIT_ASSERT(pPdfPage);
// The page has one annotation.
CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount());
std::unique_ptr<vcl::pdf::PDFiumAnnotation> pAnnot = pPdfPage->getAnnotation(0);
// Examine the default appearance.
CPPUNIT_ASSERT(pAnnot->hasKey("DA"_ostr));
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("DA"_ostr));
OUString aDA = pAnnot->getString("DA"_ostr);
// Without the accompanying fix in place, this test would have failed with: // - Expected: 0 0 0 rg /TiRo 12 Tf // - Actual : 0 0 0 rg /F2 12 Tf // i.e. Liberation Serif was exposed as a form font as-is, without picking the closest built-in // font.
CPPUNIT_ASSERT_EQUAL(u"0 0 0 rg /TiRo 12 Tf"_ustr, aDA);
}
// Check we don't have duplicated objects when we reexport the PDF multiple // times or the size will exponentially increase over time.
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReexportPDF)
{ // setenv only works on unix based systems #ifndef _WIN32 // We need to enable PDFium import (and make sure to disable after the test) bool bResetEnvVar = false; if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
{
bResetEnvVar = true;
setenv("LO_IMPORT_USE_PDFIUM", "1", false);
}
comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { if (bResetEnvVar)
unsetenv("LO_IMPORT_USE_PDFIUM");
});
// Load the PDF and save as PDF
vcl::filter::PDFDocument aDocument;
load(u"PDFWithImages.pdf", aDocument);
// Assert that the XObject in the page resources dictionary is a reference XObject.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
// The document has 2 pages.
CPPUNIT_ASSERT_EQUAL(size_t(2), aPages.size());
vcl::filter::PDFObjectElement* pBitmap
= pInnerInnerXObjects->LookupObject(aBitmapIDs2[1]);
CPPUNIT_ASSERT(pBitmap); auto pBitmapSubtype
= dynamic_cast<vcl::filter::PDFNameElement*>(pBitmap->Lookup("Subtype"_ostr));
CPPUNIT_ASSERT(pBitmapSubtype);
CPPUNIT_ASSERT_EQUAL("Image"_ostr, pBitmapSubtype->GetValue());
}
} // Ref should point to the same bitmap
CPPUNIT_ASSERT_EQUAL(aBitmapRefs1[0], aBitmapRefs2[0]);
CPPUNIT_ASSERT_EQUAL(aBitmapRefs1[1], aBitmapRefs2[1]);
}
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
int nCount = 0; bool bFound1 = false; bool bFound2 = false; bool bFound3 = false; for (constauto& rDocElement : aDocument.GetElements())
{ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get()); if (!pObject) continue; auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"_ostr)); if (pType && pType->GetValue() == "FontDescriptor")
{ auto pFontName
= dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("FontName"_ostr));
CPPUNIT_ASSERT(pFontName); if ("CAAAAA+LiberationSans-Bold"_ostr == pFontName->GetValue())
bFound1 = true; elseif ("DAAAAA+LiberationSans-Italic"_ostr == pFontName->GetValue())
bFound2 = true; elseif ("BAAAAA+LiberationSans"_ostr == pFontName->GetValue())
bFound3 = true;
++nCount;
}
} // Without the fix in place, this test would have failed with // - Expected: 3 // - Actual : 2
CPPUNIT_ASSERT_EQUAL(3, nCount);
CPPUNIT_ASSERT(bFound1);
CPPUNIT_ASSERT(bFound2);
CPPUNIT_ASSERT(bFound3);
}
// Check we correctly copy more complex resources (Fonts describing // glyphs in recursive arrays) to the target PDF
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReexportDocumentWithComplexResources)
{ // setenv only works on unix based systems #ifndef _WIN32 // We need to enable PDFium import (and make sure to disable after the test) bool bResetEnvVar = false; if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
{
bResetEnvVar = true;
setenv("LO_IMPORT_USE_PDFIUM", "1", false);
}
comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { if (bResetEnvVar)
unsetenv("LO_IMPORT_USE_PDFIUM");
});
// Load the PDF and save as PDF
vcl::filter::PDFDocument aDocument;
load(u"ComplexContentDictionary.pdf", aDocument);
// Assert that the XObject in the page resources dictionary is a reference XObject.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size());
// Go directly to the Font object (24 0) (number could change if we change how PDF export works) auto pFont = aDocument.LookupObject(24);
CPPUNIT_ASSERT(pFont);
// Check it is the Font object (Type = Font) auto pName = dynamic_cast<vcl::filter::PDFNameElement*>(
pFont->GetDictionary()->LookupElement("Type"_ostr));
CPPUNIT_ASSERT(pName);
CPPUNIT_ASSERT_EQUAL("Font"_ostr, pName->GetValue());
// Check BaseFont is what we expect auto pBaseFont = dynamic_cast<vcl::filter::PDFNameElement*>(
pFont->GetDictionary()->LookupElement("BaseFont"_ostr));
CPPUNIT_ASSERT(pBaseFont);
CPPUNIT_ASSERT_EQUAL("HOTOMR+Calibri,Italic"_ostr, pBaseFont->GetValue());
// Check and get the W array auto pWArray = dynamic_cast<vcl::filter::PDFArrayElement*>(
pFont->GetDictionary()->LookupElement("W"_ostr));
CPPUNIT_ASSERT(pWArray);
CPPUNIT_ASSERT_EQUAL(size_t(26), pWArray->GetElements().size());
// Check the content of W array // ObjectCopier didn't copy this array correctly and the document // had glyphs at the wrong places
{ // first 2 elements auto pNumberAtIndex0 = dynamic_cast<vcl::filter::PDFNumberElement*>(pWArray->GetElement(0));
CPPUNIT_ASSERT(pNumberAtIndex0);
CPPUNIT_ASSERT_EQUAL(3.0, pNumberAtIndex0->GetValue());
auto pArrayAtIndex1 = dynamic_cast<vcl::filter::PDFArrayElement*>(pWArray->GetElement(1));
CPPUNIT_ASSERT(pArrayAtIndex1);
CPPUNIT_ASSERT_EQUAL(size_t(1), pArrayAtIndex1->GetElements().size());
{ auto pNumber
= dynamic_cast<vcl::filter::PDFNumberElement*>(pArrayAtIndex1->GetElement(0));
CPPUNIT_ASSERT(pNumber);
CPPUNIT_ASSERT_EQUAL(226.0, pNumber->GetValue());
}
// last 2 elements auto pNumberAtIndex24
= dynamic_cast<vcl::filter::PDFNumberElement*>(pWArray->GetElement(24));
CPPUNIT_ASSERT(pNumberAtIndex24);
CPPUNIT_ASSERT_EQUAL(894.0, pNumberAtIndex24->GetValue());
auto pArrayAtIndex25 = dynamic_cast<vcl::filter::PDFArrayElement*>(pWArray->GetElement(25));
CPPUNIT_ASSERT(pArrayAtIndex25);
CPPUNIT_ASSERT_EQUAL(size_t(2), pArrayAtIndex25->GetElements().size());
{ auto pNumber1
= dynamic_cast<vcl::filter::PDFNumberElement*>(pArrayAtIndex25->GetElement(0));
CPPUNIT_ASSERT(pNumber1);
CPPUNIT_ASSERT_EQUAL(303.0, pNumber1->GetValue());
// Tests that at export the PDF has the PDF/UA metadata properly set // when we enable PDF/UA support.
CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfUaMetadata)
{ // Enable PDF/UA
uno::Sequence<beans::PropertyValue> aFilterData(
comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
aMediaDescriptor[u"FilterData"_ustr] <<= aFilterData;
enum
{ Default,
Artifact,
Tagged
} state
= Default;
int nLine(0); int nTagged(0); int nArtifacts(0); while (true)
{
++nLine; autoconst pLine = ::std::find(pStart, pEnd, '\n'); if (pLine == pEnd)
{ break;
}
std::string_view const line(pStart, pLine - pStart);
pStart = pLine + 1; if (!line.empty() && line[0] != '%')
{
::std::cerr << nLine << ": " << line << "\n"; if (line == "/Artifact BMC")
{
CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
state = Artifact;
++nArtifacts;
} elseif (o3tl::starts_with(line, "/Standard<))
{
CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
state = Tagged;
++nTagged;
} elseif (line == "EMC")
{
CPPUNIT_ASSERT_MESSAGE("unexpected end", state != Default);
state = Default;
} elseif (nLine > 1) // first line is expected "0.1 w"
{
CPPUNIT_ASSERT_MESSAGE("unexpected content outside MCS", state != Default);
}
}
}
CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state);
CPPUNIT_ASSERT_GREATEREQUAL(12, nTagged); // text in body // 1 annotation
CPPUNIT_ASSERT_GREATEREQUAL(1, nArtifacts);
int nPara(0); for (constauto& rDocElement : aDocument.GetElements())
{ auto pObject = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get()); if (!pObject) continue; auto pType = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("Type"_ostr)); if (pType && pType->GetValue() == "StructElem")
{ auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"_ostr));
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.26 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.