include/vcl/gdimtf.hxx                       |    1 
 sw/source/core/view/vprint.cxx               |   65 ++------
 sw/source/uibase/docvw/AnnotationWin2.cxx    |   13 +
 vcl/inc/pdf/pdfwriter_impl.hxx               |    3 
 vcl/qa/cppunit/pdfexport/data/tdf152231.fodt |  208 +++++++++++++++++++++++++++
 vcl/qa/cppunit/pdfexport/pdfexport.cxx       |  110 ++++++++++++++
 vcl/source/gdi/gdimtf.cxx                    |    7 
 vcl/source/gdi/pdfwriter_impl.cxx            |   13 -
 8 files changed, 365 insertions(+), 55 deletions(-)

New commits:
commit 3f504e684560be7038a68e0941fad9cbcfc58fc6
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Jun 30 14:56:48 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Tue Jul 4 15:20:16 2023 +0200

    tdf#152231 vcl: PDF/UA export: content of comments in the margin
    
    ... is also Artifact.
    
    The problem is that ImpEditEngine::Paint() always produces tags,
    it can't easily check if it's inside a layout environment that is an
    Artifact.
    
    But it looks like PDFWriterImpl::beginStructureElement() already wants
    to handle and suppress a structure element inside a NonStruct, except
    that it calls endStructureElementMCSeq() before checkEmitStructure(),
    so no structure marked content sequence is produced, but the content is
    outside the Artifact marked content sequence, and possibly a second
    Artifact marked content sequence will be opened once the structure
    element is finished.
    
    (btw, it's allowed to nest marked content sequences in PDF, but
    nesting a structure element inside an Artifact appears dubious)
    
    Change-Id: Ib3eef9c611e28242854c712ce974fd8cfecd8ac2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153810
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 9eacbf7874320d44b79966cac8fa59c52a191715)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153902

diff --git a/vcl/inc/pdf/pdfwriter_impl.hxx b/vcl/inc/pdf/pdfwriter_impl.hxx
index bad2d387511c..a9438be8fc13 100644
--- a/vcl/inc/pdf/pdfwriter_impl.hxx
+++ b/vcl/inc/pdf/pdfwriter_impl.hxx
@@ -1062,7 +1062,8 @@ i12626
     void endPage();
 
     void beginStructureElementMCSeq();
-    void endStructureElementMCSeq();
+    enum class EndMode { Default, OnlyStruct };
+    void endStructureElementMCSeq(EndMode = EndMode::Default);
     /** checks whether a non struct element lies in the ancestor hierarchy
         of the current structure element
 
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf152231.fodt 
b/vcl/qa/cppunit/pdfexport/data/tdf152231.fodt
new file mode 100644
index 000000000000..26b5d329b2aa
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf152231.fodt
@@ -0,0 +1,208 @@
+<?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:initial-creator>Gabor Kelemen 
LO</meta:initial-creator><meta:creation-date>2022-11-22T00:38:49.808000000</meta:creation-date><dc:date>2022-11-22T01:02:17.524000000</dc:date><dc:creator>Gabor
 Kelemen 
LO</dc:creator><meta:editing-duration>PT23M25S</meta:editing-duration><meta:editing-cycles>11</meta:editing-cycles><meta:generator>LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64
 
LibreOffice_project/3d1f9c90605623e5c7e7dd2d28f87aaa45fb9c86</meta:generator><dc:title>aaa</dc:title><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="12" meta:word-count="291" 
meta:character-count="1539" 
meta:non-whitespace-character-count="1250"/><meta:print-date>2023-06-30T17:07:42.601941685</meta:print-date><meta:printed-by>PDF
 files</meta:printed-by></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="NSimSun1" 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" 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="Liberation Serif" fo:font-size="12pt" 
fo:language="de" fo:country="DE" style:letter-kerning="true" 
style:font-name-asian="NSimSun1" 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" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="de" fo:country="DE" style:letter-kerning="true" 
style:font-name-asian="NSimSun1" 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="5" 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:style style:name="Line_20_numbering" style:display-name="Line 
numbering" style:family="text"/>
+  <text:outline-style style:name="Outline">
+   <text:outline-level-style text:level="1" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" 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"/>
+  <loext:theme loext:name="Office Theme">
+   <loext:theme-colors loext:name="LibreOffice">
+    <loext:color loext:name="dark1" loext:color="#000000"/>
+    <loext:color loext:name="light1" loext:color="#ffffff"/>
+    <loext:color loext:name="dark2" loext:color="#000000"/>
+    <loext:color loext:name="light2" loext:color="#ffffff"/>
+    <loext:color loext:name="accent1" loext:color="#18a303"/>
+    <loext:color loext:name="accent2" loext:color="#0369a3"/>
+    <loext:color loext:name="accent3" loext:color="#a33e03"/>
+    <loext:color loext:name="accent4" loext:color="#8e03a3"/>
+    <loext:color loext:name="accent5" loext:color="#c99c00"/>
+    <loext:color loext:name="accent6" loext:color="#c9211e"/>
+    <loext:color loext:name="hyperlink" loext:color="#0000ee"/>
+    <loext:color loext:name="followed-hyperlink" loext:color="#551a8b"/>
+   </loext:theme-colors>
+  </loext:theme>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="P2" style:family="paragraph">
+   <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" 
fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" 
fo:text-align="start" fo:text-indent="0cm" 
style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" 
style:line-break="strict" loext:tab-stop-distance="0cm" 
style:writing-mode="lr-tb">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties fo:hyphenate="false" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false"/>
+  </style:style>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T2" style:family="text">
+   <style:text-properties fo:font-variant="normal" fo:text-transform="none" 
style:use-window-font-color="true" loext:opacity="0%" 
style:text-outline="false" style:text-line-through-style="none" 
style:text-line-through-type="none" style:text-position="0% 100%" 
style:font-name="Liberation Serif" fo:font-size="10pt" 
fo:letter-spacing="normal" fo:language="de" fo:country="DE" 
fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" 
fo:font-weight="normal" style:text-underline-mode="continuous" 
style:text-overline-mode="continuous" style:text-line-through-mode="continuous" 
style:letter-kerning="true" fo:background-color="transparent" 
style:font-name-asian="NSimSun1" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-style-asian="normal" style:font-weight-asian="normal" 
style:font-name-complex="Lucida Sans1" style:font-size-complex="12pt" 
style:language-complex="hi" style:country-complex="IN" 
style:font-style-complex="normal"
  style:font-weight-complex="normal" style:text-emphasize="none" 
style:text-scale="100%" style:font-relief="none" 
style:text-overline-style="none" style:text-overline-color="font-color"/>
+  </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="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" 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: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="pm3" style:page-usage="left">
+   <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: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="pm4" style:page-usage="right">
+   <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: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="pm5">
+   <style:page-layout-properties fo:page-width="22.901cm" 
fo:page-height="11.4cm" style:num-format="1" 
style:print-orientation="landscape" fo:margin-top="0cm" fo:margin-bottom="0cm" 
fo:margin-left="0cm" fo:margin-right="0cm" style:writing-mode="lr-tb" 
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="pm6">
+   <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="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" 
fo:margin-right="1cm" style:writing-mode="lr-tb" 
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="pm7">
+   <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:footnote-max-height="0cm" loext:margin-gutter="0cm">
+    <style:footnote-sep 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="pm8">
+   <style:page-layout-properties fo:page-width="29.7cm" 
fo:page-height="21.001cm" style:num-format="1" 
style:print-orientation="landscape" fo:margin-top="2cm" fo:margin-bottom="2cm" 
fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" 
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"/>
+  </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">He heard quiet steps behind him. 
</text:p>
+   <text:p text:style-name="Standard">That didn't bode well. </text:p>
+   <text:p text:style-name="Standard">Who could be following him this late at 
night and in this deadbeat part of town?</text:p>
+   <text:p text:style-name="Standard"><text:span 
text:style-name="T1">A</text:span>nd at this particular moment, just after he 
pulled off the big time and was making off with the greenbacks. </text:p>
+   <text:p text:style-name="Standard">Was there another crook who'd had the 
same idea, and was now watching him and waiting for a chance to grab the fruit 
of his labor? </text:p>
+   <text:p text:style-name="Standard">Or did the steps behind him mean that 
one of many law officers in town was on to him and just waiting to pounce and 
snap those cuffs on his wrists? </text:p>
+   <text:p text:style-name="Standard"><office:annotation 
office:name="__Annotation__234_1396804301" loext:resolved="false">
+     <dc:creator>Gabor Kelemen LO</dc:creator>
+     <dc:date>2022-11-22T00:56:44.315000000</dc:date>
+     <meta:creator-initials>GK</meta:creator-initials>
+     <text:p text:style-name="P2"><text:span text:style-name="T2">This is a 
comment</text:span></text:p>
+    </office:annotation>He nervously looked all around.<office:annotation-end 
office:name="__Annotation__234_1396804301"/> </text:p>
+   <text:p text:style-name="Standard">Suddenly he saw the alley. </text:p>
+   <text:p text:style-name="Standard">Like lightning he darted off to the left 
and disappeared between the two warehouses almost falling </text:p>
+   <text:p text:style-name="Standard">over the trash can lying in the middle 
of the sidewalk. </text:p>
+   <text:p text:style-name="Standard">He tried to nervously tap his way along 
in the inky </text:p>
+   <text:p text:style-name="P1">darkness and suddenly stiffened: it was a 
dead-end, he would have to go back the way he had come. The steps got louder 
and louder, he saw the black outline of a figure coming around the corner. Is 
this the end of the line? he thought pressing himself back against the wall 
trying to make himself invisible in the dark, was all that planning and energy 
wasted? He was dripping with sweat now, cold and wet, he could smell the fear 
coming off his clothes. Suddenly next to him, with a barely noticeable squeak, 
a door swung quietly to and fro in the night's breeze. Could this be the haven 
he'd prayed for? Slowly he slid toward the door, pressing himself more and more 
into the wall, into the dark, away from his enemy. Would this door save his 
hide?</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 54f08de0a0ed..34492890fe7f 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -3204,6 +3204,116 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf139736)
     CPPUNIT_ASSERT(nArtifacts >= 3);
 }
 
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf152231)
+{
+    aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+
+    // Enable PDF/UA
+    uno::Sequence<beans::PropertyValue> aFilterData(
+        comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) 
},
+                                           { "ExportNotesInMargin", 
uno::Any(true) },
+                                           { "SelectPdfVersion", 
uno::Any(sal_Int32(17)) } }));
+    aMediaDescriptor["FilterData"] <<= aFilterData;
+    saveAsPDF(u"tdf152231.fodt");
+
+    vcl::filter::PDFDocument aDocument;
+    SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ);
+    CPPUNIT_ASSERT(aDocument.Read(aStream));
+
+    std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aPages.size());
+
+    vcl::filter::PDFObjectElement* pContents = 
aPages[0]->LookupObject("Contents");
+    CPPUNIT_ASSERT(pContents);
+    vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+    CPPUNIT_ASSERT(pStream);
+    SvMemoryStream& rObjectStream = pStream->GetMemory();
+    // Uncompress it.
+    SvMemoryStream aUncompressed;
+    ZCodec aZCodec;
+    aZCodec.BeginCompression();
+    rObjectStream.Seek(0);
+    aZCodec.Decompress(rObjectStream, aUncompressed);
+    CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+    auto pStart = static_cast<const char*>(aUncompressed.GetData());
+    const char* const pEnd = pStart + aUncompressed.GetSize();
+
+    enum
+    {
+        Default,
+        Artifact,
+        Tagged
+    } state
+        = Default;
+
+    auto nLine(0);
+    auto nTagged(0);
+    auto nArtifacts(0);
+    while (true)
+    {
+        ++nLine;
+        auto const pLine = ::std::find(pStart, pEnd, '\n');
+        if (pLine == pEnd)
+        {
+            break;
+        }
+        std::string_view const line(pStart, pLine - pStart);
+        pStart = pLine + 1;
+        if (!line.empty() && line[0] != '%')
+        {
+            ::std::cerr << nLine << ": " << line << "\n";
+            if (line == "/Artifact BMC")
+            {
+                CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, 
state);
+                state = Artifact;
+                ++nArtifacts;
+            }
+            else if (o3tl::starts_with(line, "/Standard<</MCID "))
+            {
+                CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, 
state);
+                state = Tagged;
+                ++nTagged;
+            }
+            else if (line == "EMC")
+            {
+                CPPUNIT_ASSERT_MESSAGE("unexpected end", state != Default);
+                state = Default;
+            }
+            else if (nLine > 1) // first line is expected "0.1 w"
+            {
+                CPPUNIT_ASSERT_MESSAGE("unexpected content outside MCS", state 
!= Default);
+            }
+        }
+    }
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state);
+    CPPUNIT_ASSERT(nTagged >= 12); // text in body
+    // 1 annotation
+    CPPUNIT_ASSERT(nArtifacts >= 1);
+
+    auto nPara(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() == "Standard")
+            {
+                ++nPara;
+                auto pKids = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pObject->Lookup("K"));
+                CPPUNIT_ASSERT(pKids);
+                // one problem was that that some StructElem were missing kids
+                CPPUNIT_ASSERT(!pKids->GetElements().empty());
+            }
+        }
+    }
+    CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nPara)>(12), nPara);
+}
+
 CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf149140)
 {
     aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index a15bf4ba0dc9..c65e004ca605 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -10772,12 +10772,13 @@ void PDFWriterImpl::beginStructureElementMCSeq()
     }
 }
 
-void PDFWriterImpl::endStructureElementMCSeq()
+void PDFWriterImpl::endStructureElementMCSeq(EndMode const endMode)
 {
-    if( m_nCurrentStructElement > 0 && // StructTreeRoot
-        ( m_bEmitStructure || m_aStructure[ m_nCurrentStructElement ].m_eType 
== PDFWriter::NonStructElement ) &&
-        m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq // must have an 
opened MC sequence
-        )
+    if (m_nCurrentStructElement > 0 // not StructTreeRoot
+        && (m_bEmitStructure
+            || (endMode != EndMode::OnlyStruct
+                && m_aStructure[m_nCurrentStructElement].m_eType == 
PDFWriter::NonStructElement))
+        && m_aStructure[m_nCurrentStructElement].m_bOpenMCSeq)
     {
         writeBuffer( "EMC\n" );
         m_aStructure[ m_nCurrentStructElement ].m_bOpenMCSeq = false;
@@ -10813,7 +10814,7 @@ sal_Int32 PDFWriterImpl::beginStructureElement( 
PDFWriter::StructElement eType,
         return -1;
 
     // close eventual current MC sequence
-    endStructureElementMCSeq();
+    endStructureElementMCSeq(EndMode::OnlyStruct);
 
     if( m_nCurrentStructElement == 0 &&
         eType != PDFWriter::Document && eType != PDFWriter::NonStructElement )
commit 81d9ca3015757f617c8420b079dfe1d5e1961c32
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Jun 30 14:54:18 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Tue Jul 4 15:20:10 2023 +0200

    tdf#152231 sw: PDF/UA export: tag comments in the margin as Artifact
    
    Comments aren't part of the document content.
    
    There is a separate option "Comments as PDF annotations" in the dialog
    that can be enabled even in addition to "Comments in margin" for getting
    something that's presumably accessible in PDF readers.
    
    This doesn't work completely yet, because EditEngine still produces tags.
    
    Change-Id: I66c020103a69f1d1fbbf317ae6b638158cd51868
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153809
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 20901a1a8633dc693cfd6354d0b660b81c242b70)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153901

diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx 
b/sw/source/uibase/docvw/AnnotationWin2.cxx
index 06efbfdb581f..c683e69b4204 100644
--- a/sw/source/uibase/docvw/AnnotationWin2.cxx
+++ b/sw/source/uibase/docvw/AnnotationWin2.cxx
@@ -56,6 +56,7 @@
 #include <vcl/decoview.hxx>
 #include <vcl/event.hxx>
 #include <vcl/gradient.hxx>
+#include <vcl/pdfextoutdevdata.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/ptrstyle.hxx>
@@ -160,6 +161,13 @@ void SwAnnotationWin::DrawForPage(OutputDevice* pDev, 
const Point& rPt)
     // of the SysObj can provide meaningful results
     UnclipVisibleSysObj();
 
+    vcl::PDFExtOutDevData *const pPDFExtOutDevData(
+        dynamic_cast<vcl::PDFExtOutDevData*>(pDev->GetExtOutDevData()));
+    if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
+    {
+        
pPDFExtOutDevData->BeginStructureElement(vcl::PDFWriter::NonStructElement, 
OUString());
+    }
+
     pDev->Push();
 
     pDev->SetFillColor(mColorDark);
@@ -237,6 +245,11 @@ void SwAnnotationWin::DrawForPage(OutputDevice* pDev, 
const Point& rPt)
     }
 
     pDev->Pop();
+
+    if (pPDFExtOutDevData && pPDFExtOutDevData->GetIsExportTaggedPDF())
+    {
+        pPDFExtOutDevData->EndStructureElement();
+    }
 }
 
 void SwAnnotationWin::SetPosSizePixelRect(tools::Long nX, tools::Long nY, 
tools::Long nWidth, tools::Long nHeight,
commit db97096e0f386881b7fecd868ba16def34a976ae
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Fri Jun 30 14:44:21 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Tue Jul 4 15:20:03 2023 +0200

    tdf#152231 vcl,sw: PDF/UA export: fix comments in the margin
    
    If enabled, the comments mess up the structure elements, because the
    PageSyncData::mActions stores indexes into the GDIMetaFile::m_aList
    vector, and in PageSyncData::PlaySyncPageAct() the indexes don't match.
    
    This is because SwViewShell::PrintOrPDFExport() replaces the GDIMetaFile
    with a temporary one, then records the page content, then applies
    scaling to the temporary one and replays it, recording with the original
    one; somehow replaying a temporary GDIMetaFile with 270 actions to one
    that already has 4 actions results in 392 actions.
    
    It's not obvious how this can work with the temporary GDIMetaFile, so
    try to get rid of it; not sure if there any drawbacks to this but the
    GDIMetaFile is freshly created by the caller in any case.
    
    Change-Id: Ic297367ea307aa8eee8d609751d06abf417e9629
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153808
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit a225b4dbd46897903b217969da5f97f2660022c9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153897

diff --git a/include/vcl/gdimtf.hxx b/include/vcl/gdimtf.hxx
index d62cd899623b..63bde564dcfd 100644
--- a/include/vcl/gdimtf.hxx
+++ b/include/vcl/gdimtf.hxx
@@ -115,6 +115,7 @@ public:
     void            Move( tools::Long nX, tools::Long nY );
     // additional Move method getting specifics how to handle MapMode( 
MapUnit::MapPixel )
     void            Move( tools::Long nX, tools::Long nY, tools::Long nDPIX, 
tools::Long nDPIY );
+    void            ScaleActions(double fScaleX, double fScaleY);
     void            Scale( double fScaleX, double fScaleY );
     void            Scale( const Fraction& rScaleX, const Fraction& rScaleY );
     void            Rotate( Degree10 nAngle10 );
diff --git a/sw/source/core/view/vprint.cxx b/sw/source/core/view/vprint.cxx
index 0ad22ccf5357..3cd0c524007e 100644
--- a/sw/source/core/view/vprint.cxx
+++ b/sw/source/core/view/vprint.cxx
@@ -446,32 +446,12 @@ bool SwViewShell::PrintOrPDFExport(
     // output device is now provided by a call from outside the Writer)
     pOutDev->Push();
 
-    // fdo#36815 for comments in margins print to a metafile
-    // and then scale that metafile down so that the comments
-    // will fit on the real page, and replay that scaled
-    // output to the real outputdevice
-    GDIMetaFile *pOrigRecorder(nullptr);
-    std::unique_ptr<GDIMetaFile> pMetaFile;
     SwPostItMode nPostItMode = rPrintData.GetPrintPostIts();
 
     // tdf#91680 Reserve space in margin for comments only if there are 
comments
     const bool bHasPostItsToPrintInMargins = ( nPostItMode == 
SwPostItMode::InMargins ) &&
                                 sw_GetPostIts( 
GetDoc()->getIDocumentFieldsAccess(), nullptr );
-
-    if ( bHasPostItsToPrintInMargins )
-    {
-        //get and disable the existing recorder
-        pOrigRecorder = pOutDev->GetConnectMetaFile();
-        pOutDev->SetConnectMetaFile(nullptr);
-        // turn off output to the device
-        pOutDev->EnableOutput(false);
-        // just record the rendering commands to the metafile
-        // instead
-        pMetaFile.reset(new GDIMetaFile);
-        pMetaFile->SetPrefSize(pOutDev->GetOutputSize());
-        pMetaFile->SetPrefMapMode(pOutDev->GetMapMode());
-        pMetaFile->Record(pOutDev);
-    }
+    ::std::optional<tools::Long> oOrigHeight;
 
     // Print/PDF export for (multi-)selection has already generated a
     // temporary document with the selected text.
@@ -535,32 +515,7 @@ bool SwViewShell::PrintOrPDFExport(
             pPostItManager->CalcRects();
             pPostItManager->LayoutPostIts();
             pPostItManager->DrawNotesForPage(pOutDev, nPage-1);
-
-            //Stop recording now
-            pMetaFile->Stop();
-            pMetaFile->WindStart();
-            //Enable output to the device again
-            pOutDev->EnableOutput();
-            //Restore the original recorder
-            pOutDev->SetConnectMetaFile(pOrigRecorder);
-
-            //Now scale the recorded page down so the notes
-            //will fit in the final page
-            double fScale = 0.75;
-            tools::Long nOrigHeight = pStPage->getFrameArea().Height();
-            tools::Long nNewHeight = nOrigHeight*fScale;
-            tools::Long nShiftY = (nOrigHeight-nNewHeight)/2;
-            pMetaFile->Scale( fScale, fScale );
-            pMetaFile->WindStart();
-            //Move the scaled page down to center it
-            //the other variant of Move does not map pixels
-            //back to the logical units correctly
-            pMetaFile->Move(0, convertTwipToMm100(nShiftY), 
pOutDev->GetDPIX(), pOutDev->GetDPIY());
-            pMetaFile->WindStart();
-
-            //play back the scaled page
-            pMetaFile->Play(*pOutDev);
-            pMetaFile.reset();
+            oOrigHeight.emplace(pStPage->getFrameArea().Height());
         }
     }
 
@@ -570,6 +525,22 @@ bool SwViewShell::PrintOrPDFExport(
     // output device is now provided by a call from outside the Writer)
     pOutDev->Pop();
 
+    // avoid a warning about unbalanced Push/Pop by doing this last:
+    if (oOrigHeight)
+    {
+        // fdo#36815 Now scale the recorded page down so the comments in
+        // margins will fit in the final page
+        double fScale = 0.75;
+        tools::Long nNewHeight = *oOrigHeight*fScale;
+        tools::Long nShiftY = (*oOrigHeight-nNewHeight)/2;
+        GDIMetaFile *const pMetaFile = pOutDev->GetConnectMetaFile();
+        pMetaFile->ScaleActions(fScale, fScale);
+        //Move the scaled page down to center it
+        //the other variant of Move does not map pixels
+        //back to the logical units correctly
+        pMetaFile->Move(0, convertTwipToMm100(nShiftY), pOutDev->GetDPIX(), 
pOutDev->GetDPIY());
+    }
+
     return true;
 }
 
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
index e8bb8ba7e0bd..313d03811780 100644
--- a/vcl/source/gdi/gdimtf.cxx
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -727,7 +727,7 @@ void GDIMetaFile::Move( tools::Long nX, tools::Long nY, 
tools::Long nDPIX, tools
     }
 }
 
-void GDIMetaFile::Scale( double fScaleX, double fScaleY )
+void GDIMetaFile::ScaleActions(double const fScaleX, double const fScaleY)
 {
     for( MetaAction* pAct = FirstAction(); pAct; pAct = NextAction() )
     {
@@ -743,6 +743,11 @@ void GDIMetaFile::Scale( double fScaleX, double fScaleY )
 
         pModAct->Scale( fScaleX, fScaleY );
     }
+}
+
+void GDIMetaFile::Scale( double fScaleX, double fScaleY )
+{
+    ScaleActions(fScaleX, fScaleY);
 
     m_aPrefSize.setWidth( FRound( m_aPrefSize.Width() * fScaleX ) );
     m_aPrefSize.setHeight( FRound( m_aPrefSize.Height() * fScaleY ) );

Reply via email to