With Tagged PDF on, a paragraph in a language other than the document's gets /Lang on its structure element. What is anchored in the paragraph is tagged inside that same element and inherits the attribute, so a frame's text and its description would be declared the paragraph's language. 0d2d9e656d87647f904f1a463ed9b879c2bfb10c (tdf#163272 sw: give a paragraph its own /Lang, 2026-09-21) avoided that by putting no /Lang on such a paragraph, on a check of one node of a text frame that can cover several. Its text still carried the language, on a Span, while what was anchored in it specified none and inherited the document's. In a German document that declared a shape's English text German. See https://gerrit.collaboraoffice.com/c/online/+/13117/comment/89a7866d_907a2957/ The paragraph specifies its own language now, and a frame anchored in it no longer inherits it. A Figure, a Formula and a frame's Division specify the document's where the paragraph's differs, which is what the frame's own paragraphs are measured against. A drawing shape's text is tagged by drawinglayer, which takes the locale of the drawn portions and specifies it where they agree; such a shape is nested in its anchor paragraph in Writer and in no such paragraph elsewhere, so there is nothing to compare against. A drawing shape's own element specifies the document's language too. svx anchors it under the anchor paragraph, drawinglayer opens it there, and it carries the shape's title and description. Without the attribute, a described shape in a paragraph that specifies one would have its description declared the paragraph's language, and its text likewise where the portions disagree. testParagraphLanguage compared a structure type against a language and quoted no text, so nothing identified the words affected. It lists every element holding text or a description now, against the language it specifies, an entry reading "P de-DE: Ein deutscher Absatz mit einem Bild."; one specifying none is listed without a language, so correct inheritance is asserted too. PDFiumPageObject gained getMarkedContentID to join a page object's text to its element. Signed-off-by: Mike Kaganski <mike.kaganski@collabora.com> Change-Id: I1eecf0b56f09fc6d144894910a9037d89884dd3b Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/13239 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins CPCI <releng@collaboraoffice.com> (cherry picked from commit 898a2e1b3a6fc07d7b43315b2f4781b32f1a20d3) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211609 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
649 lines
26 KiB
C++
649 lines
26 KiB
C++
/* -*- 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/.
|
|
*/
|
|
|
|
#include <string_view>
|
|
|
|
#include <cppunit/TestAssert.h>
|
|
#include <cppunit/extensions/HelperMacros.h>
|
|
|
|
#include <unotest/bootstrapfixturebase.hxx>
|
|
#include <unotest/directories.hxx>
|
|
#include <unotools/datetime.hxx>
|
|
|
|
#include <com/sun/star/util/DateTime.hpp>
|
|
|
|
#include <basegfx/vector/b2dsize.hxx>
|
|
#include <vcl/graph.hxx>
|
|
#include <vcl/graphicfilter.hxx>
|
|
#include <vcl/vectorgraphicdata.hxx>
|
|
#include <tools/stream.hxx>
|
|
|
|
#include <vcl/filter/PDFiumLibrary.hxx>
|
|
#include <vcl/pdf/PDFAnnotationMarker.hxx>
|
|
#include <vcl/pdf/PDFAnnotationSubType.hxx>
|
|
#include <vcl/pdf/PDFPageObjectType.hxx>
|
|
#include <vcl/pdf/PDFTextRenderMode.hxx>
|
|
#include <vcl/pdfread.hxx>
|
|
#include <vcl/BitmapReadAccess.hxx>
|
|
|
|
class PDFiumLibraryTest : public test::BootstrapFixtureBase
|
|
{
|
|
protected:
|
|
OUString getFullUrl(std::u16string_view sFileName)
|
|
{
|
|
return m_directories.getURLFromSrc(u"/vcl/qa/cppunit/data/") + sFileName;
|
|
}
|
|
};
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testDocument)
|
|
{
|
|
OUString aURL = getFullUrl(u"Pangram.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
aGraphic.makeAvailable();
|
|
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
CPPUNIT_ASSERT(pPdfium);
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto aSize = pDocument->getPageSize(0);
|
|
CPPUNIT_ASSERT_EQUAL(612.0, aSize.getWidth());
|
|
CPPUNIT_ASSERT_EQUAL(792.0, aSize.getHeight());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testPages)
|
|
{
|
|
OUString aURL = getFullUrl(u"Pangram.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
aGraphic.makeAvailable();
|
|
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testPageObjects)
|
|
{
|
|
OUString aURL = getFullUrl(u"Pangram.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
aGraphic.makeAvailable();
|
|
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(12, pPage->getObjectCount());
|
|
|
|
auto pPageObject = pPage->getObject(0);
|
|
auto pTextPage = pPage->getTextPage();
|
|
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Text, pPageObject->getType());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u"The quick, brown fox jumps over a lazy dog. DJs flock by when "
|
|
"MTV ax quiz prog. Junk MTV quiz "_ustr,
|
|
pPageObject->getText(pTextPage));
|
|
|
|
CPPUNIT_ASSERT_EQUAL(12.0, pPageObject->getFontSize());
|
|
CPPUNIT_ASSERT_EQUAL(u"Liberation Serif"_ustr, pPageObject->getFontName());
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFTextRenderMode::Fill, pPageObject->getTextRenderMode());
|
|
CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPageObject->getFillColor());
|
|
CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPageObject->getStrokeColor());
|
|
|
|
basegfx::B2DHomMatrix aMatrix = pPageObject->getMatrix();
|
|
// Ignore translation, ensure there is no rotate/scale.
|
|
aMatrix.set(0, 2, 0);
|
|
aMatrix.set(1, 2, 0);
|
|
CPPUNIT_ASSERT_EQUAL(true, aMatrix.isIdentity());
|
|
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(057.01, pPageObject->getBounds().getMinX(), 1E-2);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(721.51, pPageObject->getBounds().getMinY(), 1E-2);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(539.48, pPageObject->getBounds().getMaxX(), 1E-2);
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(732.54, pPageObject->getBounds().getMaxY(), 1E-2);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testAnnotationsMadeInEvince)
|
|
{
|
|
OUString aURL = getFullUrl(u"PangramWithAnnotations.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
aGraphic.makeAvailable();
|
|
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(2, pPage->getAnnotationCount());
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(0);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, pAnnotation->getSubType());
|
|
|
|
OUString aPopupString = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
|
|
CPPUNIT_ASSERT_EQUAL(u"quikee"_ustr, aPopupString);
|
|
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Annotation test"_ustr, aContentsString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyPopup));
|
|
auto pPopupAnnotation = pAnnotation->getLinked(vcl::pdf::constDictionaryKeyPopup);
|
|
CPPUNIT_ASSERT(pPopupAnnotation);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationIndex(pPopupAnnotation));
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pPopupAnnotation->getSubType());
|
|
|
|
OUString sDateTimeString
|
|
= pAnnotation->getString(vcl::pdf::constDictionaryKeyModificationDate);
|
|
CPPUNIT_ASSERT_EQUAL(u"D:20200612201322+02'00"_ustr, sDateTimeString);
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(1);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pAnnotation->getSubType());
|
|
}
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testAnnotationsMadeInAcrobat)
|
|
{
|
|
OUString aURL = getFullUrl(u"PangramAcrobatAnnotations.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
aGraphic.makeAvailable();
|
|
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(4, pPage->getAnnotationCount());
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(0);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, pAnnotation->getSubType());
|
|
|
|
OUString aPopupString = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
|
|
CPPUNIT_ASSERT_EQUAL(u"quikee"_ustr, aPopupString);
|
|
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"YEEEY"_ustr, aContentsString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyPopup));
|
|
auto pPopupAnnotation = pAnnotation->getLinked(vcl::pdf::constDictionaryKeyPopup);
|
|
CPPUNIT_ASSERT(pPopupAnnotation);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationIndex(pPopupAnnotation));
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pPopupAnnotation->getSubType());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(1);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pAnnotation->getSubType());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(2);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Text, pAnnotation->getSubType());
|
|
|
|
OUString aPopupString = pAnnotation->getString(vcl::pdf::constDictionaryKeyTitle);
|
|
CPPUNIT_ASSERT_EQUAL(u"quikee"_ustr, aPopupString);
|
|
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Note"_ustr, aContentsString);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyPopup));
|
|
auto pPopupAnnotation = pAnnotation->getLinked(vcl::pdf::constDictionaryKeyPopup);
|
|
CPPUNIT_ASSERT(pPopupAnnotation);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(3, pPage->getAnnotationIndex(pPopupAnnotation));
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pPopupAnnotation->getSubType());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(3);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Popup, pAnnotation->getSubType());
|
|
}
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(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<Bitmap> 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];
|
|
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());
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testAnnotationsDifferentTypes)
|
|
{
|
|
OUString aURL = getFullUrl(u"PangramWithMultipleTypeOfAnnotations.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
aGraphic.makeAvailable();
|
|
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(6, pPage->getAnnotationCount());
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(0);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::FreeText, pAnnotation->getSubType());
|
|
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Inline Note"_ustr, aContentsString);
|
|
auto const aLineGeometry = pAnnotation->getLineGeometry();
|
|
CPPUNIT_ASSERT_EQUAL(true, aLineGeometry.empty());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(1);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Ink, pAnnotation->getSubType());
|
|
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Freehand Text"_ustr, aContentsString);
|
|
CPPUNIT_ASSERT_EQUAL(size_t(1), pAnnotation->getInkStrokes().size());
|
|
auto const aInkStrokes = pAnnotation->getInkStrokes();
|
|
auto const& aPoints = aInkStrokes[0];
|
|
CPPUNIT_ASSERT_EQUAL(size_t(74), aPoints.size());
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0f, pAnnotation->getBorderWidth(), 1E-2);
|
|
auto const aLineGeometry = pAnnotation->getLineGeometry();
|
|
CPPUNIT_ASSERT_EQUAL(true, aLineGeometry.empty());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(2);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Line, pAnnotation->getSubType());
|
|
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Line Text"_ustr, aContentsString);
|
|
auto const aLineGeometry = pAnnotation->getLineGeometry();
|
|
CPPUNIT_ASSERT_EQUAL(false, aLineGeometry.empty());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(3);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Polygon, pAnnotation->getSubType());
|
|
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
|
|
CPPUNIT_ASSERT_EQUAL(true, pAnnotation->hasKey("Vertices"_ostr));
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Polygon Text"_ustr, aContentsString);
|
|
auto const aVertices = pAnnotation->getVertices();
|
|
CPPUNIT_ASSERT_EQUAL(size_t(3), aVertices.size());
|
|
CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0f, pAnnotation->getBorderWidth(), 1E-2);
|
|
auto const aLineGeometry = pAnnotation->getLineGeometry();
|
|
CPPUNIT_ASSERT_EQUAL(true, aLineGeometry.empty());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(4);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Circle, pAnnotation->getSubType());
|
|
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Ellipse Text"_ustr, aContentsString);
|
|
auto const aLineGeometry = pAnnotation->getLineGeometry();
|
|
CPPUNIT_ASSERT_EQUAL(true, aLineGeometry.empty());
|
|
}
|
|
|
|
{
|
|
auto pAnnotation = pPage->getAnnotation(5);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::Square, pAnnotation->getSubType());
|
|
CPPUNIT_ASSERT_EQUAL(0, pAnnotation->getObjectCount());
|
|
OUString aContentsString = pAnnotation->getString(vcl::pdf::constDictionaryKeyContents);
|
|
CPPUNIT_ASSERT_EQUAL(u"Rectangle Text"_ustr, aContentsString);
|
|
CPPUNIT_ASSERT_EQUAL(Color(0xFF, 0xE0, 0x00), pAnnotation->getColor());
|
|
CPPUNIT_ASSERT_EQUAL(false, pAnnotation->hasKey(vcl::pdf::constDictionaryKeyInteriorColor));
|
|
auto const aLineGeometry = pAnnotation->getLineGeometry();
|
|
CPPUNIT_ASSERT_EQUAL(true, aLineGeometry.empty());
|
|
}
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testAnnotationsFreeText)
|
|
{
|
|
OUString aURL = getFullUrl(u"Annotations_Adobe_FreeText.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
|
|
std::vector<vcl::PDFGraphicResult> aResults;
|
|
CPPUNIT_ASSERT_EQUAL(size_t(1), vcl::ImportPDFUnloaded(aURL, aResults));
|
|
|
|
vcl::PDFGraphicResult& rResult = aResults[0];
|
|
|
|
Graphic aGraphic = rResult.GetGraphic();
|
|
aGraphic.makeAvailable();
|
|
|
|
OUString aDefaultStyle;
|
|
OUString aRichContent;
|
|
|
|
{
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pPage->getAnnotationCount());
|
|
|
|
auto pAnnotation = pPage->getAnnotation(0);
|
|
CPPUNIT_ASSERT(pAnnotation);
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::FreeText, pAnnotation->getSubType());
|
|
|
|
aDefaultStyle = pAnnotation->getString(vcl::pdf::constDictionaryKey_DefaultStyle);
|
|
CPPUNIT_ASSERT_EQUAL(false, aDefaultStyle.isEmpty());
|
|
|
|
aRichContent = pAnnotation->getString(vcl::pdf::constDictionaryKey_RichContent);
|
|
CPPUNIT_ASSERT_EQUAL(false, aRichContent.isEmpty());
|
|
}
|
|
|
|
auto const& rAnnotations = rResult.GetAnnotations();
|
|
CPPUNIT_ASSERT_EQUAL(size_t(1), rAnnotations.size());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFAnnotationSubType::FreeText, rAnnotations[0].meSubType);
|
|
|
|
auto* pMarker
|
|
= static_cast<vcl::pdf::PDFAnnotationMarkerFreeText*>(rAnnotations[0].mpMarker.get());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(aDefaultStyle, pMarker->maDefaultStyle);
|
|
CPPUNIT_ASSERT_EQUAL(aRichContent, pMarker->maRichContent);
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testTools)
|
|
{
|
|
OUString sConverted = vcl::pdf::convertPdfDateToISO8601(u"D:20200612201322+02'00");
|
|
|
|
css::util::DateTime aDateTime;
|
|
CPPUNIT_ASSERT(utl::ISO8601parseDateTime(sConverted, aDateTime));
|
|
CPPUNIT_ASSERT_EQUAL(sal_Int16(2020), aDateTime.Year);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uInt16(6), aDateTime.Month);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uInt16(12), aDateTime.Day);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uInt16(20), aDateTime.Hours);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uInt16(13), aDateTime.Minutes);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uInt16(22), aDateTime.Seconds);
|
|
CPPUNIT_ASSERT_EQUAL(sal_uInt32(0), aDateTime.NanoSeconds);
|
|
CPPUNIT_ASSERT_EQUAL(false, bool(aDateTime.IsUTC));
|
|
}
|
|
|
|
CPPUNIT_TEST_FIXTURE(PDFiumLibraryTest, testStructureTree)
|
|
{
|
|
OUString aURL = getFullUrl(u"StructureTreeExampleDocument.pdf");
|
|
SvFileStream aStream(aURL, StreamMode::READ);
|
|
GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
|
|
Graphic aGraphic = rGraphicFilter.ImportUnloadedGraphic(aStream);
|
|
auto pVectorGraphicData = aGraphic.getVectorGraphicData();
|
|
CPPUNIT_ASSERT(pVectorGraphicData);
|
|
CPPUNIT_ASSERT_EQUAL(VectorGraphicDataType::Pdf, pVectorGraphicData->getType());
|
|
auto& rDataContainer = pVectorGraphicData->getBinaryDataContainer();
|
|
|
|
auto pPdfium = vcl::pdf::PDFiumLibrary::get();
|
|
CPPUNIT_ASSERT(pPdfium);
|
|
|
|
auto pDocument
|
|
= pPdfium->openDocument(rDataContainer.getData(), rDataContainer.getSize(), OString());
|
|
CPPUNIT_ASSERT(pDocument);
|
|
|
|
CPPUNIT_ASSERT_EQUAL(1, pDocument->getPageCount());
|
|
|
|
auto pPage = pDocument->openPage(0);
|
|
CPPUNIT_ASSERT(pPage);
|
|
|
|
// the page object side of the marked content ids the structure tree references
|
|
bool bFoundFirstMark = false;
|
|
for (int i = 0; !bFoundFirstMark && i < pPage->getObjectCount(); ++i)
|
|
bFoundFirstMark = pPage->getObject(i)->getMarkedContentID() == 0;
|
|
CPPUNIT_ASSERT(bFoundFirstMark);
|
|
|
|
auto pTree = pPage->getStructureTree();
|
|
CPPUNIT_ASSERT(pTree);
|
|
CPPUNIT_ASSERT_EQUAL(1, pTree->getNumberOfChildren());
|
|
|
|
// Check the structure
|
|
{
|
|
auto pChildDocument = pTree->getChild(0);
|
|
CPPUNIT_ASSERT(pChildDocument);
|
|
CPPUNIT_ASSERT_EQUAL(5, pChildDocument->getNumberOfChildren());
|
|
|
|
CPPUNIT_ASSERT_EQUAL(u""_ustr, pChildDocument->getAltText());
|
|
CPPUNIT_ASSERT_EQUAL(u""_ustr, pChildDocument->getActualText());
|
|
CPPUNIT_ASSERT_EQUAL(u""_ustr, pChildDocument->getID());
|
|
CPPUNIT_ASSERT_EQUAL(u""_ustr, pChildDocument->getLang());
|
|
CPPUNIT_ASSERT_EQUAL(u""_ustr, pChildDocument->getTitle());
|
|
CPPUNIT_ASSERT_EQUAL(u"Document"_ustr, pChildDocument->getType());
|
|
CPPUNIT_ASSERT_EQUAL(u"StructElem"_ustr, pChildDocument->getObjectType());
|
|
|
|
{
|
|
auto pThis = pChildDocument->getChild(0);
|
|
CPPUNIT_ASSERT(pThis);
|
|
CPPUNIT_ASSERT_EQUAL(u"P"_ustr, pThis->getType());
|
|
CPPUNIT_ASSERT_EQUAL(1, pThis->getNumberOfChildren());
|
|
CPPUNIT_ASSERT_EQUAL(0, pThis->getChildMarkedContentID(0));
|
|
}
|
|
|
|
{
|
|
auto pThis = pChildDocument->getChild(1);
|
|
CPPUNIT_ASSERT(pThis);
|
|
CPPUNIT_ASSERT_EQUAL(u"H1"_ustr, pThis->getType());
|
|
CPPUNIT_ASSERT_EQUAL(2, pThis->getNumberOfChildren());
|
|
CPPUNIT_ASSERT_EQUAL(1, pThis->getChildMarkedContentID(0));
|
|
CPPUNIT_ASSERT_EQUAL(2, pThis->getChildMarkedContentID(1));
|
|
}
|
|
|
|
{
|
|
auto pThis = pChildDocument->getChild(2);
|
|
CPPUNIT_ASSERT(pThis);
|
|
CPPUNIT_ASSERT_EQUAL(u"P"_ustr, pThis->getType());
|
|
CPPUNIT_ASSERT_EQUAL(13, pThis->getNumberOfChildren());
|
|
CPPUNIT_ASSERT_EQUAL(3, pThis->getChildMarkedContentID(0));
|
|
{
|
|
auto pChild = pThis->getChild(1);
|
|
CPPUNIT_ASSERT_EQUAL(u"Code"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(4, pChild->getChildMarkedContentID(0));
|
|
|
|
// Check getParent
|
|
auto pThis2 = pChild->getParent();
|
|
CPPUNIT_ASSERT_EQUAL(u"P"_ustr, pThis2->getType());
|
|
CPPUNIT_ASSERT_EQUAL(13, pThis2->getNumberOfChildren());
|
|
}
|
|
CPPUNIT_ASSERT_EQUAL(5, pThis->getChildMarkedContentID(2));
|
|
CPPUNIT_ASSERT_EQUAL(6, pThis->getChildMarkedContentID(3));
|
|
{
|
|
auto pChild = pThis->getChild(4);
|
|
CPPUNIT_ASSERT_EQUAL(u"Span"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(7, pChild->getChildMarkedContentID(0));
|
|
}
|
|
CPPUNIT_ASSERT_EQUAL(8, pThis->getChildMarkedContentID(5));
|
|
CPPUNIT_ASSERT_EQUAL(9, pThis->getChildMarkedContentID(6));
|
|
{
|
|
auto pChild = pThis->getChild(7);
|
|
CPPUNIT_ASSERT_EQUAL(u"Span"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(10, pChild->getChildMarkedContentID(0));
|
|
}
|
|
CPPUNIT_ASSERT_EQUAL(11, pThis->getChildMarkedContentID(8));
|
|
CPPUNIT_ASSERT_EQUAL(12, pThis->getChildMarkedContentID(9));
|
|
{
|
|
auto pChild = pThis->getChild(10);
|
|
CPPUNIT_ASSERT_EQUAL(u"Span"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(13, pChild->getChildMarkedContentID(0));
|
|
}
|
|
CPPUNIT_ASSERT_EQUAL(14, pThis->getChildMarkedContentID(11));
|
|
{
|
|
auto pChild = pThis->getChild(12);
|
|
CPPUNIT_ASSERT_EQUAL(u"Span"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(15, pChild->getChildMarkedContentID(0));
|
|
}
|
|
}
|
|
|
|
{
|
|
auto pThis = pChildDocument->getChild(3);
|
|
CPPUNIT_ASSERT(pThis);
|
|
CPPUNIT_ASSERT_EQUAL(u"P"_ustr, pThis->getType());
|
|
CPPUNIT_ASSERT_EQUAL(4, pThis->getNumberOfChildren());
|
|
CPPUNIT_ASSERT_EQUAL(16, pThis->getChildMarkedContentID(0));
|
|
{
|
|
auto pChild = pThis->getChild(1);
|
|
CPPUNIT_ASSERT_EQUAL(u"Quote"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(17, pChild->getChildMarkedContentID(0));
|
|
}
|
|
CPPUNIT_ASSERT_EQUAL(18, pThis->getChildMarkedContentID(2));
|
|
{
|
|
auto pChild = pThis->getChild(3);
|
|
// Rectangle
|
|
CPPUNIT_ASSERT_EQUAL(u"Div"_ustr, pChild->getType());
|
|
CPPUNIT_ASSERT_EQUAL(u"Only Text! - The Alt Text!"_ustr, pChild->getAltText());
|
|
CPPUNIT_ASSERT_EQUAL(20, pChild->getChildMarkedContentID(0));
|
|
{
|
|
// Text in rectangle
|
|
auto pRectangleElement = pChild->getChild(1);
|
|
CPPUNIT_ASSERT_EQUAL(u"P"_ustr, pRectangleElement->getType());
|
|
CPPUNIT_ASSERT_EQUAL(21, pRectangleElement->getChildMarkedContentID(0));
|
|
}
|
|
}
|
|
}
|
|
|
|
{
|
|
auto pThis = pChildDocument->getChild(4);
|
|
CPPUNIT_ASSERT(pThis);
|
|
CPPUNIT_ASSERT_EQUAL(u"P"_ustr, pThis->getType());
|
|
CPPUNIT_ASSERT_EQUAL(1, pThis->getNumberOfChildren());
|
|
CPPUNIT_ASSERT_EQUAL(19, pThis->getChildMarkedContentID(0));
|
|
}
|
|
|
|
{
|
|
auto pThis = pChildDocument->getChild(5);
|
|
CPPUNIT_ASSERT(!pThis);
|
|
}
|
|
}
|
|
}
|
|
|
|
CPPUNIT_PLUGIN_IMPLEMENT();
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|