sw/source/core/text/EnhancedPDFExportHelper.cxx |   38 ++
 vcl/qa/cppunit/pdfexport/data/tdf157816.fodt    |  175 ++++++++++
 vcl/qa/cppunit/pdfexport/pdfexport.cxx          |  389 ++++++++++++++++++++++++
 3 files changed, 598 insertions(+), 4 deletions(-)

New commits:
commit 6593d680e21c24501a58bac216de4a7c71541959
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Oct 27 18:00:14 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu Nov 2 10:46:30 2023 +0100

    tdf#157816 sw: PDF export: filter out links on empty space, fields
    
    If there is a fly overlapping a paragraph, it may happen (depending on
    wrap settings and position) that there's an empty space on one side of
    the fly; the cursor selection region has the flys removed, and this
    region is used here for the PDF export.
    
    So there is a rectangle on the text on one side of the fly, turned into
    the desired Link annotation, and another rectangle on the other side of
    the fly, turned into another undesired Link annotation that isn't
    connected to any SE because without text there is no SE.
    
    This is a tricky problem, and the only idea to fix it is to try to see
    if there is text in the rectangle by first GetModelPositionForViewPoint()
    resulting in a SwPosition and a SwSpecialPos with an index inside the
    field; then see if GetCharRect() for this position returns a cursor
    rectangle that intersects the original selection rectangle.
    
    Change-Id: I6918eac16690e7194208a828108bfa968d28d12a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158571
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/source/core/text/EnhancedPDFExportHelper.cxx 
b/sw/source/core/text/EnhancedPDFExportHelper.cxx
index decdd4215f0b..946def82f719 100644
--- a/sw/source/core/text/EnhancedPDFExportHelper.cxx
+++ b/sw/source/core/text/EnhancedPDFExportHelper.cxx
@@ -345,6 +345,35 @@ bool lcl_TryMoveToNonHiddenField(SwEditShell& rShell, 
const SwTextNode& rNd, con
     return true;
 };
 
+// tdf#157816: try to check if the rectangle contains actual text
+::std::vector<SwRect> GetCursorRectsContainingText(SwCursorShell const& rShell)
+{
+    ::std::vector<SwRect> ret;
+    for (SwRect const& rRect : *rShell.GetCursor_())
+    {
+        Point center(rRect.Center());
+        SwSpecialPos special;
+        SwCursorMoveState cms(CursorMoveState::NONE);
+        cms.m_pSpecialPos = &special;
+        cms.m_bFieldInfo = true;
+        SwPosition pos(rShell.GetDoc()->GetNodes());
+        auto const [pStart, pEnd] = rShell.GetCursor_()->StartEnd();
+        if (rShell.GetLayout()->GetModelPositionForViewPoint(&pos, center, 
&cms)
+            && *pStart <= pos && pos <= *pEnd)
+        {
+            SwRect charRect;
+            if (rShell.GetCurrFrame(false)->GetCharRect(charRect, pos, &cms, 
false)
+                && rRect.Overlaps(charRect))
+            {
+                ret.push_back(rRect);
+            }
+        }
+        // reset stupid static var that may have gotten set now
+        SwTextCursor::SetRightMargin(false); // WTF is this crap
+    }
+    return ret;
+}
+
 } // end namespace
 
 SwTaggedPDFHelper::SwTaggedPDFHelper( const Num_Info* pNumInfo,
@@ -2396,8 +2425,7 @@ void 
SwEnhancedPDFExportHelper::EnhancedPDFExport(LanguageType const eLanguageDe
                 mrSh.SwCursorShell::Right( 1, SwCursorSkipMode::Chars );
 
                 // Link Rectangles
-                SwRects aTmp;
-                aTmp.insert( aTmp.begin(), 
mrSh.SwCursorShell::GetCursor_()->begin(), 
mrSh.SwCursorShell::GetCursor_()->end() );
+                SwRects const aTmp(GetCursorRectsContainingText(mrSh));
                 OSL_ENSURE( !aTmp.empty(), "Enhanced pdf export - rectangles 
are missing" );
 
                 mrSh.SwCursorShell::ClearMark();
@@ -2819,7 +2847,8 @@ void 
SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks()
             mrSh.SwCursorShell::Right(1, SwCursorSkipMode::Chars);
 
             // Create the links.
-            for (const auto& rLinkRect : *mrSh.SwCursorShell::GetCursor_())
+            SwRects const rects(GetCursorRectsContainingText(mrSh));
+            for (const auto& rLinkRect : rects)
             {
                 for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect))
                 {
@@ -2869,7 +2898,8 @@ void 
SwEnhancedPDFExportHelper::ExportAuthorityEntryLinks()
             mrSh.SwCursorShell::Right(1, SwCursorSkipMode::Chars);
 
             // Create the links.
-            for (const auto& rLinkRect : *mrSh.SwCursorShell::GetCursor_())
+            SwRects const rects(GetCursorRectsContainingText(mrSh));
+            for (const auto& rLinkRect : rects)
             {
                 for (const auto& rLinkPageNum : CalcOutputPageNums(rLinkRect))
                 {
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf157816.fodt 
b/vcl/qa/cppunit/pdfexport/data/tdf157816.fodt
new file mode 100644
index 000000000000..5288f3aa75ca
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf157816.fodt
@@ -0,0 +1,175 @@
+<?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:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
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:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
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:tableooo="http://openoffice.org/2009/table"; 
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:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ 
<office:meta><meta:creation-date>2020-12-04T17:01:40.586000000</meta:creation-date><dc:title>LibreOffice</dc:title><meta:editing-duration>P18DT13H30M55S</meta:editing-duration><meta:editing-cycles>102</meta:editing-cycles><meta:generator>LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64
 
LibreOffice_project/70bf29987ceb90cd3988fc2dfc4cad2a0163fe17</meta:generator><dc:date>2023-10-18T20:11:26.174000000</dc:date><meta:print-date>2023-10-18T20:36:10.265000000</meta:print-date><meta:printed-by>PDF
 files</meta:printed-by><meta:document-statistic meta:table-count="0" 
meta:image-count="5" meta:object-count="0" meta:page-count="1" 
meta:paragraph-count="12" meta:word-count="61" meta:character-count="412" 
meta:non-whitespace-character-count="347"/><meta:template xlink:type="simple" 
xlink:actuate="onRequest" xlink:title="+1.Fit_Vorlage_V0.04" 
xlink:href="../H:/AppData/Local/Microsoft/Windows/INetCache/AppData/Roaming/LibreOffice/4/user/template/SH/+1.Fit_Vorlage_V0.04.ott"
 meta:date="2020-12-15T11:1
 2:58.522000000"/></office:meta>
+ <office:font-face-decls>
+  <style:font-face style:name="Arial" svg:font-family="Arial" 
style:font-adornments="Standard" style:font-family-generic="swiss" 
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"/>
+  <style:font-face style:name="Trebuchet MS" svg:font-family="'Trebuchet MS'" 
style:font-family-generic="swiss"/>
+ </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" loext:tab-stop-distance="0cm" 
style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Trebuchet MS" fo:font-size="12pt" 
fo:language="de" fo:country="DE" 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.249cm" style:writing-mode="lr-tb"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Trebuchet MS" fo:font-size="12pt" 
fo:language="de" fo:country="DE" 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" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="no-limit" loext:hyphenation-zone="no-limit"/>
+  </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:paragraph-properties fo:orphans="2" fo:widows="2"/>
+   <style:text-properties style:font-name="Arial" fo:font-family="Arial" 
style:font-style-name="Standard" style:font-family-generic="swiss" 
style:font-pitch="variable"/>
+  </style:style>
+  <style:style style:name="Text_20_body" style:display-name="Text body" 
style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+   <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.247cm" 
style:contextual-spacing="false" fo:line-height="100%"/>
+  </style:style>
+  <style:style style:name="Caption" style:family="paragraph" 
style:parent-style-name="Standard" style:class="extra">
+   <style:paragraph-properties fo:margin-top="0.212cm" 
fo:margin-bottom="0.212cm" style:contextual-spacing="false" 
text:number-lines="false" text:line-number="0"/>
+   <style:text-properties fo:font-size="10pt"/>
+  </style:style>
+  <style:style style:name="Illustration" style:family="paragraph" 
style:parent-style-name="Caption" style:class="extra" style:master-page-name="">
+   <style:paragraph-properties style:page-number="auto"/>
+   <style:text-properties fo:font-size="8pt"/>
+  </style:style>
+  <style:style style:name="Line_20_numbering" style:display-name="Line 
numbering" style:family="text"/>
+  <style:style style:name="Frame" style:family="graphic">
+   <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" 
svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" 
fo:margin-top="0.199cm" fo:margin-bottom="0.499cm" style:wrap="parallel" 
style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" 
style:vertical-pos="top" style:vertical-rel="paragraph-content" 
style:horizontal-pos="center" style:horizontal-rel="paragraph-content" 
fo:background-color="transparent" draw:fill="none" draw:fill-color="#729fcf" 
fo:padding="0.15cm" fo:border="0.06pt solid #000000" 
draw:wrap-influence-on-position="once-concurrent" loext:allow-overlap="true">
+    <style:columns fo:column-count="1" fo:column-gap="0cm"/>
+   </style:graphic-properties>
+  </style:style>
+  <text:outline-style style:name="Outline">
+   <text:outline-level-style text:level="1" loext:num-list-format="%1%" 
style:num-format="1">
+    <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" loext:num-list-format="%1%.%2%" 
style:num-format="1" text:display-levels="2">
+    <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" 
loext:num-list-format="%1%.%2%.%3%" style:num-format="1" 
text:display-levels="3">
+    <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" 
loext:num-list-format="%1%.%2%.%3%.%4%" style:num-format="1" 
text:display-levels="4">
+    <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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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:style-name="Line_20_numbering" 
text:number-lines="false" text:offset="0.499cm" style:num-format="1" 
text:number-position="left" text:increment="5"/>
+  <style:default-page-layout>
+   <style:page-layout-properties style:writing-mode="lr-tb" 
style:layout-grid-standard-mode="true"/>
+  </style:default-page-layout>
+  </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P3" style:family="paragraph" 
style:parent-style-name="Text_20_body">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="P4" style:family="paragraph" 
style:parent-style-name="Text_20_body">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="P5" style:family="paragraph" 
style:parent-style-name="Text_20_body" 
style:master-page-name="_2b_1.Fit_5f_ErsteSeite">
+   <style:paragraph-properties style:page-number="auto"/>
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T6" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T7" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T8" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T9" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="fr3" style:family="graphic" 
style:parent-style-name="Frame">
+   <style:graphic-properties fo:margin-left="0cm" fo:margin-right="0cm" 
fo:margin-top="0cm" fo:margin-bottom="1cm" style:vertical-pos="from-top" 
style:vertical-rel="paragraph" style:horizontal-pos="from-left" 
style:horizontal-rel="paragraph" fo:padding="0cm" fo:border="none"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21.001cm" 
fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" 
fo:margin-top="2cm" fo:margin-bottom="1cm" fo:margin-left="2.499cm" 
fo:margin-right="1.499cm" style:writing-mode="lr-tb" 
style:layout-grid-color="#c0c0c0" style:layout-grid-lines="44" 
style:layout-grid-base-height="0.55cm" style:layout-grid-ruby-height="0cm" 
style:layout-grid-mode="none" style:layout-grid-ruby-below="false" 
style:layout-grid-print="true" style:layout-grid-display="true" 
style:layout-grid-base-width="0.37cm" style:layout-grid-snap-to="true" 
style:footnote-max-height="0cm" loext:margin-gutter="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:page-layout style:name="pm2">
+   <style:page-layout-properties fo:page-width="21.001cm" 
fo:page-height="29.7cm" 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="44" 
style:layout-grid-base-height="0.55cm" style:layout-grid-ruby-height="0cm" 
style:layout-grid-mode="none" style:layout-grid-ruby-below="false" 
style:layout-grid-print="true" style:layout-grid-display="true" 
style:layout-grid-base-width="0.37cm" style:layout-grid-snap-to="true" 
style:footnote-max-height="0cm" loext:margin-gutter="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"/>
+  <style:master-page style:name="_2b_1.Fit_5f_ErsteSeite" 
style:display-name="+1.Fit_ErsteSeite" style:page-layout-name="pm2" 
draw:style-name="dp1"/>
+  </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:sequence-decls>
+    <text:sequence-decl text:display-outline-level="1" 
text:separation-character="." 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-decl text:display-outline-level="1" 
text:separation-character="." text:name="TippNr"/>
+   </text:sequence-decls>
+   <text:p text:style-name="P5"><draw:frame draw:style-name="fr3" 
draw:name="Rahmen13" text:anchor-type="char" svg:x="5.142cm" svg:y="0.079cm" 
svg:width="11.829cm" draw:z-index="0">
+     <draw:text-box fo:min-height="9.114cm">
+      <text:p text:style-name="Illustration">Abbildung <text:sequence 
text:ref-name="refIllustration0" text:name="Illustration" 
text:formula="ooow:Illustration+1" style:num-format="1">1</text:sequence>: 
<text:span text:style-name="T7">Haus!</text:span></text:p>
+     </draw:text-box>
+    </draw:frame><text:span text:style-name="T6">Extras </text:span><text:span 
text:style-name="T8">fdsfsdf dfs sdf dsfsd fs fsd sdfsd fsgf gfhf gfhgfrt fd 
fdg ddfg dfgd fdfg df dfg <text:s/></text:span></text:p>
+   <text:p text:style-name="P4"><text:span 
text:style-name="T9">szíj</text:span><text:span text:style-name="T8">fdgdf 
</text:span><text:span text:style-name="T9">f</text:span><text:span 
text:style-name="T8">dfg dfg gdfgdfg dggdf fd</text:span></text:p>
+   <text:p text:style-name="P3"><text:span 
text:style-name="T7">aa</text:span><text:span text:style-name="T9">ds fsdfsd 
sdf sd fsd sdffsdf</text:span><text:span text:style-name="T7"> 
</text:span><text:bookmark-ref text:reference-format="chapter" 
text:ref-name="__RefHeading___Toc1501_2152971747">Error: Reference source not 
found</text:bookmark-ref><text:bookmark-ref text:reference-format="text" 
text:ref-name="__RefHeading___Toc1501_2152971747">Error: Reference source not 
found</text:bookmark-ref><text:s/><text:span text:style-name="T7">bb 
</text:span><text:span text:style-name="T9">dsfsd sdfsdfsd</text:span>.</text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index 192d559f9c74..0849248dce2a 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -1990,6 +1990,395 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf139065)
     CPPUNIT_ASSERT_EQUAL(15, pPdfPage->getObjectCount());
 }
 
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816)
+{
+    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"tdf157816.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());
+
+    vcl::filter::PDFObjectElement* pDocument(nullptr);
+    for (const auto& rDocElement : aDocument.GetElements())
+    {
+        auto pObject1 = 
dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+        if (!pObject1)
+            continue;
+        auto pType1 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject1->Lookup("Type"));
+        if (pType1 && pType1->GetValue() == "StructElem")
+        {
+            auto pS1 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObject1->Lookup("S"));
+            if (pS1 && pS1->GetValue() == "Document")
+            {
+                pDocument = pObject1;
+            }
+        }
+    }
+    CPPUNIT_ASSERT(pDocument);
+
+    auto pKidsD = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pDocument->Lookup("K"));
+    CPPUNIT_ASSERT(pKidsD);
+    // assume there are no MCID ref at this level
+    auto pKidsDv = pKidsD->GetElements();
+    auto pRefKidD2 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsDv[2]);
+    CPPUNIT_ASSERT(pRefKidD2);
+    auto pObjectD2 = pRefKidD2->LookupObject();
+    CPPUNIT_ASSERT(pObjectD2);
+    auto pTypeD2 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD2->Lookup("Type"));
+    CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pTypeD2->GetValue());
+    auto pSD2 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD2->Lookup("S"));
+    CPPUNIT_ASSERT_EQUAL(OString("Text#20body"), pSD2->GetValue());
+
+    auto pKidsD2 = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObjectD2->Lookup("K"));
+    CPPUNIT_ASSERT(pKidsD2);
+    auto pKidsD2v = pKidsD2->GetElements();
+    auto pRefKidD20 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[0]);
+    // MCID for text
+    CPPUNIT_ASSERT(!pRefKidD20);
+    auto pRefKidD21 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[1]);
+    // MCID for text
+    CPPUNIT_ASSERT(!pRefKidD21);
+
+    auto pRefKidD22 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[2]);
+    CPPUNIT_ASSERT(pRefKidD22);
+    auto pObjectD22 = pRefKidD22->LookupObject();
+    CPPUNIT_ASSERT(pObjectD22);
+    auto pTypeD22 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD22->Lookup("Type"));
+    CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pTypeD22->GetValue());
+    auto pSD22 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD22->Lookup("S"));
+    CPPUNIT_ASSERT_EQUAL(OString("Link"), pSD22->GetValue());
+    {
+        auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObjectD22->Lookup("K"));
+        auto nMCID(0);
+        auto nRef(0);
+        for (size_t i = 0; i < pKids->GetElements().size(); ++i)
+        {
+            auto pNum = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pKids->GetElement(i));
+            auto pRef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids->GetElement(i));
+            if (pNum)
+            {
+                ++nMCID;
+            }
+            if (pRef)
+            {
+                ++nRef;
+                auto pObjR = pRef->LookupObject();
+                auto pOType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjR->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("OBJR"), pOType->GetValue());
+                auto pAnnotRef
+                    = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObjR->Lookup("Obj"));
+                auto pAnnot = pAnnotRef->LookupObject();
+                auto pAType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("Annot"), pAType->GetValue());
+                auto pASubtype
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"));
+                CPPUNIT_ASSERT_EQUAL(OString("Link"), pASubtype->GetValue());
+                auto pAContents
+                    = 
dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"));
+                CPPUNIT_ASSERT_EQUAL(
+                    u"Error: Reference source not found"_ustr,
+                    
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents));
+                auto pStructParent
+                    = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pAnnot->Lookup("StructParent"));
+                CPPUNIT_ASSERT(pStructParent); // every link must have it!
+                auto pARect = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pAnnot->Lookup("Rect"));
+                CPPUNIT_ASSERT(pARect);
+                const auto& rElements = pARect->GetElements();
+                CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rElements.size());
+                const auto* pNumL = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[0]);
+                CPPUNIT_ASSERT(pNumL);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(95.143, pNumL->GetValue(), 1e-3);
+                const auto* pNumT = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[1]);
+                CPPUNIT_ASSERT(pNumT);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(674.589, pNumT->GetValue(), 1e-3);
+                const auto* pNumR = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[2]);
+                CPPUNIT_ASSERT(pNumR);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(202.457, pNumR->GetValue(), 1e-3);
+                const auto* pNumB = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[3]);
+                CPPUNIT_ASSERT(pNumB);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(688.389, pNumB->GetValue(), 1e-3);
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
+    }
+
+    auto pRefKidD23 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[3]);
+    CPPUNIT_ASSERT(pRefKidD23);
+    auto pObjectD23 = pRefKidD23->LookupObject();
+    CPPUNIT_ASSERT(pObjectD23);
+    auto pTypeD23 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD23->Lookup("Type"));
+    CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pTypeD23->GetValue());
+    auto pSD23 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD23->Lookup("S"));
+    CPPUNIT_ASSERT_EQUAL(OString("Link"), pSD23->GetValue());
+    {
+        auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObjectD23->Lookup("K"));
+        auto nMCID(0);
+        auto nRef(0);
+        for (size_t i = 0; i < pKids->GetElements().size(); ++i)
+        {
+            auto pNum = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pKids->GetElement(i));
+            auto pRef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids->GetElement(i));
+            if (pNum)
+            {
+                ++nMCID;
+            }
+            if (pRef)
+            {
+                ++nRef;
+                auto pObjR = pRef->LookupObject();
+                auto pOType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjR->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("OBJR"), pOType->GetValue());
+                auto pAnnotRef
+                    = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObjR->Lookup("Obj"));
+                auto pAnnot = pAnnotRef->LookupObject();
+                auto pAType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("Annot"), pAType->GetValue());
+                auto pASubtype
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"));
+                CPPUNIT_ASSERT_EQUAL(OString("Link"), pASubtype->GetValue());
+                auto pAContents
+                    = 
dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"));
+                CPPUNIT_ASSERT_EQUAL(
+                    u"Error: Reference source not found"_ustr,
+                    
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents));
+                auto pStructParent
+                    = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pAnnot->Lookup("StructParent"));
+                CPPUNIT_ASSERT(pStructParent); // every link must have it!
+                auto pARect = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pAnnot->Lookup("Rect"));
+                CPPUNIT_ASSERT(pARect);
+                const auto& rElements = pARect->GetElements();
+                CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rElements.size());
+                const auto* pNumL = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[0]);
+                CPPUNIT_ASSERT(pNumL);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3);
+                const auto* pNumT = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[1]);
+                CPPUNIT_ASSERT(pNumT);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(660.789, pNumT->GetValue(), 1e-3);
+                const auto* pNumR = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[2]);
+                CPPUNIT_ASSERT(pNumR);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(146.157, pNumR->GetValue(), 1e-3);
+                const auto* pNumB = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[3]);
+                CPPUNIT_ASSERT(pNumB);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(674.589, pNumB->GetValue(), 1e-3);
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
+    }
+
+    auto pRefKidD24 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[4]);
+    CPPUNIT_ASSERT(pRefKidD24);
+    auto pObjectD24 = pRefKidD24->LookupObject();
+    CPPUNIT_ASSERT(pObjectD24);
+    auto pTypeD24 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD24->Lookup("Type"));
+    CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pTypeD24->GetValue());
+    auto pSD24 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD24->Lookup("S"));
+    CPPUNIT_ASSERT_EQUAL(OString("Link"), pSD24->GetValue());
+    {
+        auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObjectD24->Lookup("K"));
+        auto nMCID(0);
+        auto nRef(0);
+        for (size_t i = 0; i < pKids->GetElements().size(); ++i)
+        {
+            auto pNum = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pKids->GetElement(i));
+            auto pRef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids->GetElement(i));
+            if (pNum)
+            {
+                ++nMCID;
+            }
+            if (pRef)
+            {
+                ++nRef;
+                auto pObjR = pRef->LookupObject();
+                auto pOType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjR->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("OBJR"), pOType->GetValue());
+                auto pAnnotRef
+                    = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObjR->Lookup("Obj"));
+                auto pAnnot = pAnnotRef->LookupObject();
+                auto pAType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("Annot"), pAType->GetValue());
+                auto pASubtype
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"));
+                CPPUNIT_ASSERT_EQUAL(OString("Link"), pASubtype->GetValue());
+                auto pAContents
+                    = 
dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"));
+                CPPUNIT_ASSERT_EQUAL(
+                    u"Error: Reference source not found"_ustr,
+                    
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents));
+                auto pStructParent
+                    = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pAnnot->Lookup("StructParent"));
+                CPPUNIT_ASSERT(pStructParent); // every link must have it!
+                auto pARect = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pAnnot->Lookup("Rect"));
+                CPPUNIT_ASSERT(pARect);
+                const auto& rElements = pARect->GetElements();
+                CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rElements.size());
+                const auto* pNumL = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[0]);
+                CPPUNIT_ASSERT(pNumL);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(146.093, pNumL->GetValue(), 1e-3);
+                const auto* pNumT = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[1]);
+                CPPUNIT_ASSERT(pNumT);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(660.789, pNumT->GetValue(), 1e-3);
+                const auto* pNumR = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[2]);
+                CPPUNIT_ASSERT(pNumR);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(202.457, pNumR->GetValue(), 1e-3);
+                const auto* pNumB = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[3]);
+                CPPUNIT_ASSERT(pNumB);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(674.589, pNumB->GetValue(), 1e-3);
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
+    }
+
+    auto pRefKidD25 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[5]);
+    CPPUNIT_ASSERT(pRefKidD25);
+    auto pObjectD25 = pRefKidD25->LookupObject();
+    CPPUNIT_ASSERT(pObjectD25);
+    auto pTypeD25 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD25->Lookup("Type"));
+    CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pTypeD25->GetValue());
+    auto pSD25 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD25->Lookup("S"));
+    CPPUNIT_ASSERT_EQUAL(OString("Link"), pSD25->GetValue());
+    {
+        auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObjectD25->Lookup("K"));
+        auto nMCID(0);
+        auto nRef(0);
+        for (size_t i = 0; i < pKids->GetElements().size(); ++i)
+        {
+            auto pNum = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pKids->GetElement(i));
+            auto pRef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids->GetElement(i));
+            if (pNum)
+            {
+                ++nMCID;
+            }
+            if (pRef)
+            {
+                ++nRef;
+                auto pObjR = pRef->LookupObject();
+                auto pOType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjR->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("OBJR"), pOType->GetValue());
+                auto pAnnotRef
+                    = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObjR->Lookup("Obj"));
+                auto pAnnot = pAnnotRef->LookupObject();
+                auto pAType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("Annot"), pAType->GetValue());
+                auto pASubtype
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"));
+                CPPUNIT_ASSERT_EQUAL(OString("Link"), pASubtype->GetValue());
+                auto pAContents
+                    = 
dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"));
+                CPPUNIT_ASSERT_EQUAL(
+                    u"Error: Reference source not found"_ustr,
+                    
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents));
+                auto pStructParent
+                    = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pAnnot->Lookup("StructParent"));
+                CPPUNIT_ASSERT(pStructParent); // every link must have it!
+                auto pARect = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pAnnot->Lookup("Rect"));
+                CPPUNIT_ASSERT(pARect);
+                const auto& rElements = pARect->GetElements();
+                CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rElements.size());
+                const auto* pNumL = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[0]);
+                CPPUNIT_ASSERT(pNumL);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3);
+                const auto* pNumT = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[1]);
+                CPPUNIT_ASSERT(pNumT);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(646.989, pNumT->GetValue(), 1e-3);
+                const auto* pNumR = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[2]);
+                CPPUNIT_ASSERT(pNumR);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(202.457, pNumR->GetValue(), 1e-3);
+                const auto* pNumB = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[3]);
+                CPPUNIT_ASSERT(pNumB);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(660.789, pNumB->GetValue(), 1e-3);
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
+    }
+
+    auto pRefKidD26 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[6]);
+    CPPUNIT_ASSERT(pRefKidD26);
+    auto pObjectD26 = pRefKidD26->LookupObject();
+    CPPUNIT_ASSERT(pObjectD26);
+    auto pTypeD26 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD26->Lookup("Type"));
+    CPPUNIT_ASSERT_EQUAL(OString("StructElem"), pTypeD26->GetValue());
+    auto pSD26 = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjectD26->Lookup("S"));
+    CPPUNIT_ASSERT_EQUAL(OString("Link"), pSD26->GetValue());
+    {
+        auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObjectD26->Lookup("K"));
+        auto nMCID(0);
+        auto nRef(0);
+        for (size_t i = 0; i < pKids->GetElements().size(); ++i)
+        {
+            auto pNum = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pKids->GetElement(i));
+            auto pRef = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids->GetElement(i));
+            if (pNum)
+            {
+                ++nMCID;
+            }
+            if (pRef)
+            {
+                ++nRef;
+                auto pObjR = pRef->LookupObject();
+                auto pOType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pObjR->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("OBJR"), pOType->GetValue());
+                auto pAnnotRef
+                    = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pObjR->Lookup("Obj"));
+                auto pAnnot = pAnnotRef->LookupObject();
+                auto pAType = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Type"));
+                CPPUNIT_ASSERT_EQUAL(OString("Annot"), pAType->GetValue());
+                auto pASubtype
+                    = 
dynamic_cast<vcl::filter::PDFNameElement*>(pAnnot->Lookup("Subtype"));
+                CPPUNIT_ASSERT_EQUAL(OString("Link"), pASubtype->GetValue());
+                auto pAContents
+                    = 
dynamic_cast<vcl::filter::PDFHexStringElement*>(pAnnot->Lookup("Contents"));
+                CPPUNIT_ASSERT_EQUAL(
+                    u"Error: Reference source not found"_ustr,
+                    
::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents));
+                auto pStructParent
+                    = 
dynamic_cast<vcl::filter::PDFNumberElement*>(pAnnot->Lookup("StructParent"));
+                CPPUNIT_ASSERT(pStructParent); // every link must have it!
+                auto pARect = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pAnnot->Lookup("Rect"));
+                CPPUNIT_ASSERT(pARect);
+                const auto& rElements = pARect->GetElements();
+                CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), rElements.size());
+                const auto* pNumL = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[0]);
+                CPPUNIT_ASSERT(pNumL);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3);
+                const auto* pNumT = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[1]);
+                CPPUNIT_ASSERT(pNumT);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(633.189, pNumT->GetValue(), 1e-3);
+                const auto* pNumR = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[2]);
+                CPPUNIT_ASSERT(pNumR);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(86.807, pNumR->GetValue(), 1e-3);
+                const auto* pNumB = 
dynamic_cast<vcl::filter::PDFNumberElement*>(rElements[3]);
+                CPPUNIT_ASSERT(pNumB);
+                CPPUNIT_ASSERT_DOUBLES_EQUAL(646.989, pNumB->GetValue(), 1e-3);
+            }
+        }
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nMCID)>(1), nMCID);
+        CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nRef)>(1), nRef);
+    }
+
+    auto pRefKidD27 = 
dynamic_cast<vcl::filter::PDFReferenceElement*>(pKidsD2v[7]);
+    // MCID for text
+    CPPUNIT_ASSERT(!pRefKidD27);
+
+    // the problem was that in addition to the 5 links with SE there were 3 
more
+    auto pAnnots = 
dynamic_cast<vcl::filter::PDFArrayElement*>(aPages[0]->Lookup("Annots"));
+    CPPUNIT_ASSERT(pAnnots);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), 
pAnnots->GetElements().size());
+}
+
 CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115967)
 {
     aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");

Reply via email to