tdf#135638 drawinglayer,svx,sw: PDF/UA export: put SdrObjects on anchor

... frame in the structure tree.

The problem is that in sw, the anchored objects are painted
outside of the call to paint the page frame, which is what generates the
/Document structure element.

For Writer fly frames, this is handled via their SwFlyDrawObj painting,
where SwTaggedPDFHelper::CheckReopenTag() finds the anchor frame and
temporarily sets it as the structure parent, even if it's on a previous
page.

But all the SdrObjects on a page are painted by 2 calls to PaintLayer()
and there isn't a call back into Writer now.

Somehow this even causes a spurious line like "/Document<</MCID 7>>BDC"
to be emitted outside any PDF object, which looks clearly wrong.

Try to extend the SdrObjUserCall to get a way to retrieve the anchor
frame's structure element index.

Another option would be to extend ViewObjectContactRedirector to return
the PDF Id in its subclass SwViewObjectContactRedirector, and it seems
possible since its only one caller is
ViewObjectContact::getPrimitive2DSequence(), but Armin adivses that the
ViewObjectContactRedirector might go away in the future so it's better
to use SdrObjUserCall.

It's annoying that the mapping is a static members of
SwEnhancedPDFExportHelper; possibly it could be in OutputDevice's
PDFExtOutDevData instead?

Change-Id: Id61faae469aba4f0bd278ab2324aae06c1fdde64
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143027
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
This commit is contained in:
Michael Stahl
2022-11-22 13:05:07 +01:00
parent 3d5e3cb4c0
commit 6e5d59c2ca
10 changed files with 309 additions and 12 deletions
@@ -30,11 +30,13 @@ namespace drawinglayer::primitive2d
const vcl::PDFWriter::StructElement& rStructureElement,
bool bBackground,
bool bIsImage,
Primitive2DContainer&& aChildren)
Primitive2DContainer&& aChildren,
sal_Int32 const nAnchorStructureElementId)
: GroupPrimitive2D(std::move(aChildren)),
maStructureElement(rStructureElement),
mbBackground(bBackground),
mbIsImage(bIsImage)
, m_nAnchorStructureElementId(nAnchorStructureElementId)
{
}
@@ -2364,12 +2364,27 @@ void VclMetafileProcessor2D::processStructureTagPrimitive2D(
// structured tag primitive
const vcl::PDFWriter::StructElement& rTagElement(rStructureTagCandidate.getStructureElement());
bool bTagUsed((vcl::PDFWriter::NonStructElement != rTagElement));
sal_Int32 nPreviousElement(-1);
if (mpPDFExtOutDevData && bTagUsed)
{
// foreground object: tag as regular structure element
if (!rStructureTagCandidate.isBackground())
{
if (rStructureTagCandidate.GetAnchorStructureElementId() != -1)
{
auto const nTemp = mpPDFExtOutDevData->GetCurrentStructureElement();
bool const bSuccess = mpPDFExtOutDevData->SetCurrentStructureElement(
rStructureTagCandidate.GetAnchorStructureElementId());
if (bSuccess)
{
nPreviousElement = nTemp;
}
else
{
SAL_WARN("drawinglayer", "anchor structure element not found?");
}
}
mpPDFExtOutDevData->BeginStructureElement(rTagElement);
switch (rTagElement)
{
@@ -2434,6 +2449,14 @@ void VclMetafileProcessor2D::processStructureTagPrimitive2D(
{
// write end tag
mpPDFExtOutDevData->EndStructureElement();
if (nPreviousElement != -1)
{
#ifndef NDEBUG
bool const bSuccess =
#endif
mpPDFExtOutDevData->SetCurrentStructureElement(nPreviousElement);
assert(bSuccess);
}
}
}
@@ -49,6 +49,8 @@ namespace drawinglayer::primitive2d
bool mbBackground;
/// flag for image (OBJ_GRAF)
bool mbIsImage;
/// anchor structure element (Writer)
sal_Int32 m_nAnchorStructureElementId;
public:
/// constructor
@@ -56,12 +58,14 @@ namespace drawinglayer::primitive2d
const vcl::PDFWriter::StructElement& rStructureElement,
bool bBackground,
bool bIsImage,
Primitive2DContainer&& aChildren);
Primitive2DContainer&& aChildren,
sal_Int32 nAnchorStructureElementId = -1);
/// data read access
const vcl::PDFWriter::StructElement& getStructureElement() const { return maStructureElement; }
bool isBackground() const { return mbBackground; }
bool isImage() const { return mbIsImage; }
sal_Int32 GetAnchorStructureElementId() const { return m_nAnchorStructureElementId; }
/// compare operator
virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
+1
View File
@@ -130,6 +130,7 @@ class SVXCORE_DLLPUBLIC SdrObjUserCall
public:
virtual ~SdrObjUserCall();
virtual void Changed(const SdrObject& rObj, SdrUserCallType eType, const tools::Rectangle& rOldBoundRect);
virtual sal_Int32 GetPDFAnchorStructureElementId(SdrObject const& rObj, OutputDevice const&);
};
class SVXCORE_DLLPUBLIC SdrObjMacroHitRec
+9 -1
View File
@@ -412,13 +412,21 @@ drawinglayer::primitive2d::Primitive2DContainer const & ViewObjectContact::getPr
{
const bool bBackground(pSdrPage->IsMasterPage());
const bool bImage(SdrObjKind::Graphic == pSdrObj->GetObjIdentifier());
// note: there must be output device here, in PDF export
sal_Int32 nAnchorId(-1);
if (auto const pUserCall = pSdrObj->GetUserCall())
{
nAnchorId = pUserCall->GetPDFAnchorStructureElementId(
*pSdrObj, *GetObjectContact().TryToGetOutputDevice());
}
drawinglayer::primitive2d::Primitive2DReference xReference(
new drawinglayer::primitive2d::StructureTagPrimitive2D(
eElement,
bBackground,
bImage,
std::move(xNewPrimitiveSequence)));
std::move(xNewPrimitiveSequence),
nAnchorId));
xNewPrimitiveSequence = drawinglayer::primitive2d::Primitive2DContainer { xReference };
}
}
+5
View File
@@ -136,6 +136,11 @@ void SdrObjUserCall::Changed(const SdrObject& /*rObj*/, SdrUserCallType /*eType*
{
}
sal_Int32 SdrObjUserCall::GetPDFAnchorStructureElementId(SdrObject const&, OutputDevice const&)
{
return -1;
}
SdrObjMacroHitRec::SdrObjMacroHitRec() :
pVisiLayer(nullptr),
pPageView(nullptr),
+1
View File
@@ -389,6 +389,7 @@ class SAL_DLLPUBLIC_RTTI SwDrawContact final : public SwContact
/// Virtual methods of SdrObjUserCall.
virtual void Changed(const SdrObject& rObj, SdrUserCallType eType, const tools::Rectangle& rOldBoundRect) override;
virtual sal_Int32 GetPDFAnchorStructureElementId(SdrObject const& rObj, OutputDevice const&) override;
/** Used by Changed() and by UndoDraw.
Notifies paragraphs that have to get out of the way. */
@@ -81,6 +81,7 @@
#include <strings.hrc>
#include <frameformats.hxx>
#include <authfld.hxx>
#include <dcontact.hxx>
#include <tools/globname.hxx>
#include <svx/svdobj.hxx>
@@ -337,6 +338,28 @@ SwTaggedPDFHelper::~SwTaggedPDFHelper()
#endif
}
static auto GetReopenTagFromFrame(SwFrame const& rFrame) -> sal_Int32
{
void const*const pKey = lcl_GetKeyFromFrame(rFrame);
if (pKey)
{
FrameTagIdMap const& rFrameTagIdMap(SwEnhancedPDFExportHelper::GetFrameTagIdMap());
auto const it(rFrameTagIdMap.find(pKey));
if (it != rFrameTagIdMap.end())
{
return (*it).second;
}
}
return -1;
}
sal_Int32 SwDrawContact::GetPDFAnchorStructureElementId(SdrObject const& rObj, OutputDevice const&)
{
SwFrame const*const pAnchorFrame(GetAnchoredObj(&rObj)->GetAnchorFrame());
return pAnchorFrame ? GetReopenTagFromFrame(*pAnchorFrame) : -1;
}
bool SwTaggedPDFHelper::CheckReopenTag()
{
bool bRet = false;
@@ -377,15 +400,7 @@ bool SwTaggedPDFHelper::CheckReopenTag()
if ( pKeyFrame )
{
void* pKey = lcl_GetKeyFromFrame( *pKeyFrame );
if ( pKey )
{
FrameTagIdMap& rFrameTagIdMap = SwEnhancedPDFExportHelper::GetFrameTagIdMap();
const FrameTagIdMap::const_iterator aIter = rFrameTagIdMap.find( pKey );
if ( aIter != rFrameTagIdMap.end() )
nReopenTag = (*aIter).second;
}
nReopenTag = GetReopenTagFromFrame(*pKeyFrame);
}
}
@@ -0,0 +1,141 @@
<?xml version='1.0' encoding='UTF-8'?>
<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
<office:meta><meta:initial-creator>Gabor Kelemen LO</meta:initial-creator><meta:creation-date>2022-10-12T16:49:07.114000000</meta:creation-date><dc:date>2022-11-18T15:28:13.568307995</dc:date><meta:editing-duration>PT3M39S</meta:editing-duration><meta:editing-cycles>2</meta:editing-cycles><meta:generator>LibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/867afb8f1cc153fba2c28c85deedda74bd077cf0</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="1" meta:object-count="0" meta:page-count="1" meta:paragraph-count="2" meta:word-count="291" meta:character-count="1541" meta:non-whitespace-character-count="1250"/></office:meta>
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
<style:font-face style:name="Lucida Sans1" svg:font-family="'Lucida Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
<style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="system" style:font-pitch="variable"/>
</office:font-face-decls>
<office:styles>
<style:default-style style:family="graphic">
<style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
<style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false">
<style:tab-stops/>
</style:paragraph-properties>
<style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
</style:default-style>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
<style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="NSimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
</style:default-style>
<style:default-style style:family="table">
<style:table-properties table:border-model="collapsing"/>
</style:default-style>
<style:default-style style:family="table-row">
<style:table-row-properties fo:keep-together="auto"/>
</style:default-style>
<style:style style:name="Standard" style:family="paragraph" style:class="text"/>
<style:style style:name="Graphics" style:family="graphic">
<style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
</style:style>
<text:outline-style style:name="Outline">
<text:outline-level-style text:level="1" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="2" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="3" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="4" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="5" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="6" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="7" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="8" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="9" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
<text:outline-level-style text:level="10" style:num-format="">
<style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
<style:list-level-label-alignment text:label-followed-by="listtab"/>
</style:list-level-properties>
</text:outline-level-style>
</text:outline-style>
<text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
<text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
<text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
</office:styles>
<office:automatic-styles>
<style:style style:name="fr1" style:family="graphic" style:parent-style-name="Graphics">
<style:graphic-properties style:horizontal-pos="center" style:horizontal-rel="paragraph" style:mirror="none" fo:clip="rect(0cm, 0cm, 0cm, 0cm)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard" draw:wrap-influence-on-position="once-concurrent"/>
</style:style>
<style:style style:name="gr1" style:family="graphic">
<style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="2.249cm" fo:min-width="5.212cm" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/>
</style:style>
<style:page-layout style:name="pm1">
<style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm">
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
</style:page-layout-properties>
<style:header-style/>
<style:footer-style/>
</style:page-layout>
<style:style style:name="dp1" style:family="drawing-page">
<style:drawing-page-properties draw:background-size="full"/>
</style:style>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
</office:master-styles>
<office:body>
<office:text>
<text:sequence-decls>
<text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
<text:sequence-decl text:display-outline-level="0" text:name="Table"/>
<text:sequence-decl text:display-outline-level="0" text:name="Text"/>
<text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
<text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
</text:sequence-decls>
<text:p text:style-name="Standard"><draw:custom-shape text:anchor-type="paragraph" draw:z-index="1" draw:name="Shape 1" draw:style-name="gr1" svg:width="5.213cm" svg:height="2.25cm" svg:x="4.299cm" svg:y="12.448cm">
<svg:title>This is a blue...</svg:title>
<svg:desc>...rectangle</svg:desc>
<text:p/>
<draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/>
</draw:custom-shape><draw:frame draw:style-name="fr1" draw:name="Image1" text:anchor-type="char" svg:width="11.748cm" svg:height="8.996cm" draw:z-index="0"><draw:image draw:mime-type="image/png">
<office:binary-data>iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAANbY1E9YMgAAABl0
RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFpSURBVHjaYvz//z8DtQBAADER
o+jjZGuibAQIICZiDOK/cgzFwEnrV/4HYXS1AAHERIxBR58yMiAb2DtzM1b1AAHERIxBIIBu
IDYAEEBMxBjE0bgdxcBL3vcZLl16jaEPIICYiDFIU9MSw8BeoeUYhgEEEBMxBnFx8WE1EN3L
AAHERIxBIECMgQABxAhKtPgM+vbtE9xmGP/69eMMP+o9wWLW0kD9OlYM/LlHGQECiAndoKg/
USgGgTTmdS8C0yA+zIUgdeguBAggljtWdQwMVkDXACWMjd0ZXRun/Id5DWTA9C23GSaVxoEN
zISoARvoamnBYF2/hPHs2Z3/z0JdDhBADCBvIuPkhsn/QeDr14//QWwQjY0PVYeiFyCA8OaA
3cdPoEQAiI8PAAQQEwMVAUAAsWATBAX0jx9fsWrAJQ4CAAGE1TBQwOMC9+9fwikHEEBYDQPF
IAzIe8TglEMHAAHESM2SFiDAADEwCe4BJwcYAAAAAElFTkSuQmCC
</office:binary-data>
</draw:image>
<svg:title>Image of a house</svg:title>
<svg:desc>nice drawing, isn't it?</svg:desc>
</draw:frame>He heard quiet steps behind him. That didn't bode well.</text:p>
<text:p text:style-name="Standard"><text:s/></text:p>
<text:p text:style-name="Standard"/>
</office:text>
</office:body>
</office:document>
+97
View File
@@ -3180,6 +3180,103 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf149140)
CPPUNIT_ASSERT_EQUAL(int(6), nTH);
}
CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf135638)
{
aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
// Enable PDF/UA
uno::Sequence<beans::PropertyValue> aFilterData(
comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
aMediaDescriptor["FilterData"] <<= aFilterData;
saveAsPDF(u"image-shape.fodt");
vcl::filter::PDFDocument aDocument;
SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
CPPUNIT_ASSERT(aDocument.Read(aStream));
// The document has one page.
std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
int nFigure(0);
for (const auto& 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"));
if (pType && pType->GetValue() == "StructElem")
{
auto pS = dynamic_cast<vcl::filter::PDFNameElement*>(pObject->Lookup("S"));
if (pS && pS->GetValue() == "Figure")
{
auto pARef = dynamic_cast<vcl::filter::PDFReferenceElement*>(pObject->Lookup("A"));
CPPUNIT_ASSERT(pARef != nullptr);
auto pAttr = pARef->LookupObject();
CPPUNIT_ASSERT(pAttr != nullptr);
auto pAttrDict = pAttr->GetDictionary();
CPPUNIT_ASSERT(pAttrDict != nullptr);
auto pOwner
= dynamic_cast<vcl::filter::PDFNameElement*>(pAttrDict->LookupElement("O"));
CPPUNIT_ASSERT(pOwner != nullptr);
CPPUNIT_ASSERT_EQUAL(OString("Layout"), pOwner->GetValue());
auto pBBox
= dynamic_cast<vcl::filter::PDFArrayElement*>(pAttrDict->LookupElement("BBox"));
CPPUNIT_ASSERT(pBBox != nullptr);
if (nFigure == 0)
{
CPPUNIT_ASSERT_DOUBLES_EQUAL(
139.5,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[0])
->GetValue(),
0.01);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
480.3,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[1])
->GetValue(),
0.01);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
472.5,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[2])
->GetValue(),
0.01);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
735.3,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[3])
->GetValue(),
0.01);
}
else
{
CPPUNIT_ASSERT_DOUBLES_EQUAL(
178.45,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[0])
->GetValue(),
0.01);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
318.65,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[1])
->GetValue(),
0.01);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
326.35,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[2])
->GetValue(),
0.01);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
382.55,
dynamic_cast<vcl::filter::PDFNumberElement*>(pBBox->GetElements()[3])
->GetValue(),
0.01);
}
++nFigure;
}
}
}
// the first one is a Writer image, 2nd one SdrRectObj
CPPUNIT_ASSERT_EQUAL(int(2), nFigure);
}
CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf142129)
{
loadFromURL(u"master.odm");