summaryrefslogtreecommitdiffstats
path: root/sw/qa/extras/globalfilter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/qa/extras/globalfilter
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/qa/extras/globalfilter')
-rw-r--r--sw/qa/extras/globalfilter/data/BulletAsImage.odtbin0 -> 9113 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/SvgImageTest.odtbin0 -> 13608 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/char_background.odtbin0 -> 9737 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/char_background_editing.docxbin0 -> 12672 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/char_highlight.docxbin0 -> 13213 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/checkbox_form_field.odtbin0 -> 8258 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/date_form_field.odtbin0 -> 8830 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odtbin0 -> 8432 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/document_with_linked_graphic.odtbin0 -> 21466 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/document_with_two_images.odtbin0 -> 204546 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/dropdown_form_field.odtbin0 -> 8285 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.docxbin0 -> 13179 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.fodt133
-rw-r--r--sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.rtf249
-rw-r--r--sw/qa/extras/globalfilter/data/graphic_shape.odtbin0 -> 100009 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/images_with_special_IDs.odtbin0 -> 169464 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/linked_graphic.jpgbin0 -> 35738 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/multiple_identical_graphics.odtbin0 -> 13826 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/skipimages.docbin0 -> 19968 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/skipimages.docxbin0 -> 10925 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/tdf138345_charstyle_highlight.odtbin0 -> 13304 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/tdf143311-1.docxbin0 -> 34371 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/text13e.odtbin0 -> 9718 bytes
-rw-r--r--sw/qa/extras/globalfilter/data/text_form_field.odtbin0 -> 8376 bytes
-rw-r--r--sw/qa/extras/globalfilter/globalfilter.cxx2267
25 files changed, 2649 insertions, 0 deletions
diff --git a/sw/qa/extras/globalfilter/data/BulletAsImage.odt b/sw/qa/extras/globalfilter/data/BulletAsImage.odt
new file mode 100644
index 0000000000..27622aac4e
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/BulletAsImage.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/SvgImageTest.odt b/sw/qa/extras/globalfilter/data/SvgImageTest.odt
new file mode 100644
index 0000000000..3b37fe7998
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/SvgImageTest.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/char_background.odt b/sw/qa/extras/globalfilter/data/char_background.odt
new file mode 100644
index 0000000000..d2dcea0695
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/char_background.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/char_background_editing.docx b/sw/qa/extras/globalfilter/data/char_background_editing.docx
new file mode 100644
index 0000000000..5e92fe8bbd
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/char_background_editing.docx
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/char_highlight.docx b/sw/qa/extras/globalfilter/data/char_highlight.docx
new file mode 100644
index 0000000000..e601bac111
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/char_highlight.docx
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/checkbox_form_field.odt b/sw/qa/extras/globalfilter/data/checkbox_form_field.odt
new file mode 100644
index 0000000000..14c931ed37
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/checkbox_form_field.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/date_form_field.odt b/sw/qa/extras/globalfilter/data/date_form_field.odt
new file mode 100644
index 0000000000..2b786a4146
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/date_form_field.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt b/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt
new file mode 100644
index 0000000000..eb77026205
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/date_form_field_char_formatting.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/document_with_linked_graphic.odt b/sw/qa/extras/globalfilter/data/document_with_linked_graphic.odt
new file mode 100644
index 0000000000..e7aeda6e2e
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/document_with_linked_graphic.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/document_with_two_images.odt b/sw/qa/extras/globalfilter/data/document_with_two_images.odt
new file mode 100644
index 0000000000..54d3d666de
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/document_with_two_images.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/dropdown_form_field.odt b/sw/qa/extras/globalfilter/data/dropdown_form_field.odt
new file mode 100644
index 0000000000..caaa66acda
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/dropdown_form_field.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.docx b/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.docx
new file mode 100644
index 0000000000..9fbec01e0a
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.docx
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.fodt b/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.fodt
new file mode 100644
index 0000000000..86b17a15bb
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.fodt
@@ -0,0 +1,133 @@
+<?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:calcext="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>Michael Stahl</meta:initial-creator><dc:creator>Michael Stahl</dc:creator><meta:editing-cycles>2</meta:editing-cycles><meta:creation-date>2019-01-24T14:48:00</meta:creation-date><dc:date>2019-01-24T14:48:00</dc:date><meta:editing-duration>P0D</meta:editing-duration><meta:generator>LibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/be346d6cdc87b18dc861279187915de42722e970</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="13" meta:word-count="6" meta:character-count="24" meta:non-whitespace-character-count="18"/><meta:user-defined meta:name="AppVersion">15.0000</meta:user-defined><meta:template xlink:type="simple" xlink:actuate="onRequest" xlink:title="Normal.dotm" xlink:href=""/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="Calibri" svg:font-family="Calibri" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Calibri1" svg:font-family="Calibri" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" 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:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" style:font-name="Calibri" fo:font-size="10pt" fo:language="de" fo:country="DE" style:letter-kerning="false" style:font-name-asian="Calibri1" style:font-size-asian="10pt" style:language-asian="de" style:country-asian="DE" style:font-name-complex="Times New Roman" style:font-size-complex="10pt" style:language-complex="ar" style:country-complex="SA"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties 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="page"/>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Calibri" fo:font-size="10pt" fo:language="de" fo:country="DE" style:letter-kerning="false" style:font-name-asian="Calibri1" style:font-size-asian="10pt" style:language-asian="de" style:country-asian="DE" style:font-name-complex="Times New Roman" style:font-size-complex="10pt" style:language-complex="ar" style:country-complex="SA" 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:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.282cm" style:contextual-spacing="false" fo:line-height="108%" fo:text-align="start" style:justify-single-word="false" fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/>
+ <style:text-properties fo:font-size="11pt" style:font-size-asian="11pt" style:language-asian="en" style:country-asian="US" style:font-size-complex="11pt"/>
+ </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"/>
+ <style:default-page-layout>
+ <style:page-layout-properties style:layout-grid-standard-mode="true"/>
+ </style:default-page-layout>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:language="en" fo:country="IE"/>
+ </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="2.499cm" fo:margin-bottom="2cm" fo:margin-left="2.499cm" fo:margin-right="2.499cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.388cm" 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"/>
+ </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"><field:fieldmark-start text:name="Bookmark1" field:type="vnd.oasis.opendocument.field.UNHANDLED"><field:param field:name="vnd.oasis.opendocument.field.code" field:value=""/></field:fieldmark-start><text:s/>QUOTE <text:s/>"foo </text:p>
+ <text:p text:style-name="Standard"><text:s/><field:fieldmark-start text:name="Bookmark" field:type="vnd.oasis.opendocument.field.UNHANDLED"><field:param field:name="vnd.oasis.opendocument.field.code" field:value=""/></field:fieldmark-start><text:s/>QUOTE <text:s/>"foo </text:p>
+ <text:p text:style-name="Standard"><text:s/>bar </text:p>
+ <text:p text:style-name="Standard">baz" <field:fieldmark-separator/>foo </text:p>
+ <text:p text:style-name="Standard"><text:s/>bar </text:p>
+ <text:p text:style-name="Standard">baz<field:fieldmark-end/></text:p>
+ <text:p text:style-name="Standard">bar </text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1">baz" </text:span><field:fieldmark-separator/><text:span text:style-name="T1">foo </text:span></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1"><text:s/>foo </text:span></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1"><text:s/>bar </text:span></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1">baz</text:span></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1">bar </text:span></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1">baz</text:span><field:fieldmark-end/></text:p>
+ <text:p text:style-name="Standard"/>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.rtf b/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.rtf
new file mode 100644
index 0000000000..04c8384fd6
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/fieldmark_QUOTE_nest.rtf
@@ -0,0 +1,249 @@
+{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch37\stshfloch37\stshfhich37\stshfbi0\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
+{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;}{\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}{\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman{\*\falt Times New Roman};}
+{\f279\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\f280\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\f282\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\f283\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\f284\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\f285\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\f286\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\f287\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\f619\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}
+{\f620\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}{\f622\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f623\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f626\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}
+{\f627\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}{\f649\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f650\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f652\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}
+{\f653\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\f654\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}{\f655\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\f656\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}
+{\f657\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}
+{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}
+{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;}{\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}
+{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31533\fbidi \fswiss\fcharset177\fprq2 Calibri Light (Hebrew);}{\fhimajor\f31534\fbidi \fswiss\fcharset178\fprq2 Calibri Light (Arabic);}
+{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;}{\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
+{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}
+{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
+{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
+{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
+{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}
+{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
+{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
+{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}
+{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}
+{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}
+{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}
+{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}
+{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31573\fbidi \fswiss\fcharset177\fprq2 Calibri (Hebrew);}
+{\fhiminor\f31574\fbidi \fswiss\fcharset178\fprq2 Calibri (Arabic);}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}
+{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE{\*\falt Times New Roman};}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr{\*\falt Times New Roman};}
+{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek{\*\falt Times New Roman};}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur{\*\falt Times New Roman};}
+{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew){\*\falt Times New Roman};}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic){\*\falt Times New Roman};}
+{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic{\*\falt Times New Roman};}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese){\*\falt Times New Roman};}}{\colortbl;\red0\green0\blue0;
+\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;
+\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \loch\af37\hich\af37\dbch\af37 }{\*\defpap \ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }
+\noqfpromote {\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1031\langfe1033\loch\f37\hich\af37\dbch\af37\cgrid\langnp1031\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
+\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv
+\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs20\alang1025 \ltrch\fcs0 \fs20\lang1031\langfe1031\loch\f37\hich\af37\dbch\af37\cgrid\langnp1031\langfenp1031 \snext11 \ssemihidden \sunhideused
+Normal Table;}}{\*\pgptbl {\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid1061464\rsid1922412\rsid5796261\rsid12332008\rsid13762899\rsid16735927}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1
+\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\author Michael Stahl}{\operator Michael Stahl}{\creatim\yr2019\mo1\dy24\hr15\min48}{\revtim\yr2019\mo1\dy24\hr15\min48}{\version2}{\edmins0}{\nofpages1}{\nofwords13}{\nofchars89}{\nofcharsws101}{\vern57447}}
+{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\paperw11906\paperh16838\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect
+\deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont1\relyonvml0\donotembedlingdata0\grfdocevents0\validatexml1\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0
+\showxmlerrors1\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1417\dgvorigin1417\dghshow1\dgvshow1
+\jexpand\viewkind1\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct
+\asianbrkrule\rsidroot1061464\newtblstyruls\nogrowautofit\usenormstyforlist\noindnmbrts\felnbrelev\nocxsptable\indrlsweleven\noafcnsttbl\afelev\utinl\hwelev\spltpgpar\notcvasp\notbrkcnstfrctbl\notvatxbx\krnprsnet\cachedcolbal \nouicompat \fet0
+{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2
+\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6
+\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1031\langfe1033\loch\af37\hich\af37\dbch\af37\cgrid\langnp1031\langfenp1033 {\field{\*\fldinst {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1061464 \hich\af37\dbch\af37\loch\f37 \hich\af37\dbch\af37\loch\f37 QUOTE "foo
+\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13762899 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1061464 \hich\af37\dbch\af37\loch\f37 }{\field{\*\fldinst {\rtlch\fcs1 \af0
+\ltrch\fcs0 \insrsid13762899 \hich\af37\dbch\af37\loch\f37 \hich\af37\dbch\af37\loch\f37 QUOTE "foo
+\par \hich\af37\dbch\af37\loch\f37 bar
+\par \hich\af37\dbch\af37\loch\f37 baz"\hich\af37\dbch\af37\loch\f37 }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid13762899 \hich\af37\dbch\af37\loch\f37 foo
+\par \hich\af37\dbch\af37\loch\f37 bar
+\par \hich\af37\dbch\af37\loch\f37 baz}}}\sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid13762899
+\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af0 \ltrch\fcs0 \insrsid1061464 \hich\af37\dbch\af37\loch\f37 bar
+\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang6153\langfe1033\langnp6153\insrsid1061464\charrsid13762899 \hich\af37\dbch\af37\loch\f37 baz"\hich\af37\dbch\af37\loch\f37 }}{\fldrslt {\rtlch\fcs1 \af0 \ltrch\fcs0
+\lang6153\langfe1033\langnp6153\insrsid13762899\charrsid13762899 \hich\af37\dbch\af37\loch\f37 foo
+\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid13762899 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang6153\langfe1033\langnp6153\insrsid13762899\charrsid13762899
+\hich\af37\dbch\af37\loch\f37 }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang6153\langfe1033\langnp6153\insrsid13762899\charrsid13762899 \hich\af37\dbch\af37\loch\f37 foo
+\par \hich\af37\dbch\af37\loch\f37 bar
+\par \hich\af37\dbch\af37\loch\f37 baz
+\par }\pard \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 {\rtlch\fcs1 \af0 \ltrch\fcs0 \lang6153\langfe1033\langnp6153\insrsid13762899\charrsid13762899 \hich\af37\dbch\af37\loch\f37 bar
+
+\par \hich\af37\dbch\af37\loch\f37 baz}}}\pard\plain \ltrpar\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0
+\fs22\lang1031\langfe1033\loch\af37\hich\af37\dbch\af37\cgrid\langnp1031\langfenp1033 \sectd \ltrsect\linex0\headery708\footery708\colsx708\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af0 \ltrch\fcs0
+\lang6153\langfe1033\langnp6153\insrsid5796261\charrsid13762899
+\par }{\rtlch\fcs1 \af0 \ltrch\fcs0 \lang6153\langfe1033\langnp6153\insrsid16735927\charrsid1061464
+\par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
+9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
+5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
+b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
+0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
+a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
+c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
+0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
+a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
+6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
+4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
+4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100aa5225dfc60600008b1a0000160000007468656d652f7468656d652f
+7468656d65312e786d6cec595d8bdb46147d2ff43f08bd3bfe92fcb1c41b6cd9ceb6d94d42eca4e4716c8fadc98e344633de8d0981923c160aa569e943037deb
+43691b48a02fe9afd936a54d217fa17746b63c638fbb9b2585a5640d8b343af7ce997bafce1d4997afdc8fa87384134e58dc708b970aae83e3211b9178d2706f
+f7bbb99aeb7081e211a22cc60d778eb97b65f7c30f2ea31d11e2083b601ff31dd4704321a63bf93c1fc230e297d814c7706dcc920809384d26f951828ec16f44
+f3a542a1928f10895d274611b8bd311e932176fad2a5bbbb74dea1701a0b2e078634e949d7d8b050d8d1615122f89c0734718e106db830cf881df7f17de13a14
+7101171a6e41fdb9f9ddcb79b4b330a2628bad66d7557f0bbb85c1e8b0a4e64c26836c52cff3bd4a33f3af00546ce23ad54ea553c9fc29001a0e61a52917dda7
+dfaab7dafe02ab81d2438bef76b55d2e1a78cd7f798373d3973f03af40a97f6f03dfed06104503af4029dedfc07b5eb51478065e81527c65035f2d34db5ed5c0
+2b5048497cb8812ef89572b05c6d061933ba6785d77daf5b2d2d9caf50500d5975c929c62c16db6a2d42f758d2058004522448ec88f9148fd110aa3840940c12
+e2ec93490885374531e3305c2815ba8532fc973f4f1da988a01d8c346bc90b98f08d21c9c7e1c3844c45c3fd18bcba1ae4cdcb1fdfbc7cee9c3c7a71f2e89793
+c78f4f1efd9c3a32acf6503cd1ad5e7fffc5df4f3f75fe7afeddeb275fd9f15cc7fffed367bffdfaa51d082b5d85e0d5d7cffe78f1ecd5379ffff9c3130bbc99
+a0810eef930873e73a3e766eb10816a6426032c783e4ed2cfa2122ba45339e701423398bc57f478406fafa1c5164c1b5b019c13b09488c0d787576cf20dc0b93
+9920168fd7c2c8001e30465b2cb146e19a9c4b0b737f164fec9327331d770ba123dbdc018a8dfc766653d05662731984d8a07993a258a0098eb170e4357688b1
+6575770931e27a408609e36c2c9cbbc46921620d499f0c8c6a5a19ed9108f232b711847c1bb139b8e3b418b5adba8d8f4c24dc15885ac8f73135c27815cd048a
+6c2efb28a27ac0f791086d247bf364a8e33a5c40a6279832a733c29cdb6c6e24b05e2de9d7405eec693fa0f3c84426821cda7cee23c674649b1d06218aa6366c
+8fc4a18efd881f428922e7261336f80133ef10790e7940f1d674df21d848f7e96a701b9455a7b42a107965965872791533a37e7b733a4658490d08bfa1e71189
+4f15f73559f7ff5b5907217df5ed53cbaa2eaaa0371362bda3f6d6647c1b6e5dbc03968cc8c5d7ee369ac53731dc2e9b0decbd74bf976ef77f2fdddbeee7772f
+d82b8d06f9965bc574abae36eed1d67dfb9850da13738af7b9daba73e84ca32e0c4a3bf5cc8ab3e7b8690887f24e86090cdc2441cac64998f88488b017a229ec
+ef8bae7432e10bd713ee4c19876dbf1ab6fa96783a8b0ed8287d5c2d16e5a3692a1e1c89d578c1cfc6e15143a4e84a75f50896b9576c27ea51794940dabe0d09
+6d329344d942a2ba1c9441520fe610340b09b5b277c2a26e615193ee97a9da6001d4b2acc0d6c9810d57c3f53d30012378a242148f649ed2542fb3ab92f92e33
+bd2d984605c03e625901ab4cd725d7adcb93ab4b4bed0c99364868e566925091513d8c87688417d52947cf42e36d735d5fa5d4a02743a1e683d25ad1a8d6fe8d
+c579730d76ebda40635d2968ec1c37dc4ad9879219a269c31dc3633f1c4653a81d2eb7bc884ee0ddd95024e90d7f1e6599265cb4110fd3802bd149d520220227
+0e2551c395cbcfd24063a5218a5bb104827061c9d541562e1a3948ba99643c1ee3a1d0d3ae8dc848a7a7a0f0a95658af2af3f383a5259b41ba7be1e8d819d059
+720b4189f9d5a20ce0887078fb534ca33922f03a3313b255fdad35a685eceaef13550da5e3884e43b4e828ba98a77025e5191d7596c5403b5bac1902aa8564d1
+080713d960f5a01add34eb1a2987ad5df7742319394d34573dd35015d935ed2a66ccb06c036bb13c5f93d7582d430c9aa677f854bad725b7bed4bab57d42d625
+20e059fc2c5df70c0d41a3b69acca026196fcab0d4ecc5a8d93b960b3c85da599a84a6fa95a5dbb5b8653dc23a1d0c9eabf383dd7ad5c2d078b9af549156df3d
+f44f136c700fc4a30d2f81675470954af8f09020d810f5d49e24950db845ee8bc5ad0147ce2c210df741c16f7a41c90f72859adfc97965af90abf9cd72aee9fb
+e562c72f16daadd243682c228c8a7efacda50bafa2e87cf1e5458d6f7c7d89966fdb2e0d599467eaeb4a5e11575f5f8aa5ed5f5f1c02a2f3a052ead6cbf55625
+572f37bb39afddaae5ea41a5956b57826abbdb0efc5abdfbd0758e14d86b9603afd2a9e52ac520c8799582a45fabe7aa5ea9d4f4aacd5ac76b3e5c6c6360e5a9
+7c2c6201e155bc76ff010000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f
+7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be
+9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980
+ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5b
+babac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000000000005b436f6e74656e
+745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f
+2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468656d652f7468656d652f74
+68656d654d616e616765722e786d6c504b01022d0014000600080000002100aa5225dfc60600008b1a00001600000000000000000000000000d6020000746865
+6d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b0100002700000000000000000000000000d00900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000cb0a00000000}
+{\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
+617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
+6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
+656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
+{\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;
+\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
+\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;
+\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9;
+\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3;
+\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6;
+\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;
+\lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Table;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 1;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Simple 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 2;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Classic 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 2;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Colorful 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 3;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Columns 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 2;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 6;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Grid 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 2;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 6;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table List 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 2;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table 3D effects 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Contemporary;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Elegant;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Professional;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Subtle 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 1;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 2;
+\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Web 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Table Theme;\lsdsemihidden1 \lsdlocked0 Placeholder Text;
+\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid;\lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;
+\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2;\lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;
+\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1;\lsdpriority61 \lsdlocked0 Light List Accent 1;
+\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdsemihidden1 \lsdlocked0 Revision;
+\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;
+\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;\lsdpriority72 \lsdlocked0 Colorful List Accent 1;
+\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
+\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;
+\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;
+\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
+\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;
+\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;
+\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
+\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;
+\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;\lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;
+\lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
+\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;
+\lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6;
+\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;
+\lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;
+\lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
+\lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography;
+\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4;
+\lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4;
+\lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1;
+\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1;
+\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2;
+\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2;
+\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3;
+\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4;
+\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4;
+\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5;
+\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5;
+\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6;
+\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6;
+\lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark;
+\lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1;
+\lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1;
+\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2;
+\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3;
+\lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3;
+\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4;
+\lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4;
+\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5;
+\lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5;
+\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6;
+\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000
+4d73786d6c322e534158584d4c5265616465722e362e30000000000000000000000e0000
+d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+fffffffffffffffffdffffff04000000feffffff05000000fefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000c6ad98892f1d411a65f0040963251e500000000000000000000000010aa
+78dbf3b3d4010300000080020000000000004d0073006f004400610074006100530074006f0072006500000000000000000000000000000000000000000000000000000000000000000000000000000000001a000101ffffffffffffffff02000000000000000000000000000000000000000000000010aa78dbf3b3d401
+10aa78dbf3b3d4010000000000000000000000004f00c600520049004f005800c7005400c700c40053003200d400c00033004b004100d800cc003000430041003d003d000000000000000000000000000000000032000101ffffffffffffffff03000000000000000000000000000000000000000000000010aa78dbf3b3
+d40110aa78dbf3b3d4010000000000000000000000004900740065006d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffff04000000ffffffff000000000000000000000000000000000000000000000000
+00000000000000000000000000000000f100000000000000010000000200000003000000feffffff0500000006000000070000000800000009000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3c623a536f757263657320786d6c6e733a623d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f6772617068792220786d6c6e733d
+22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222053656c65637465645374796c653d225c415041536978746845646974696f6e4f66666963654f6e6c696e652e78736c22205374796c654e616d
+653d22415041222056657273696f6e3d2236222f3e0000000000000000000000000000003c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d226e6f223f3e0d0a3c64733a6461746173746f72654974656d2064733a6974656d49443d227b33393438
+363433412d443337392d343439452d394344322d3037344130333842314130387d2220786d6c6e733a64733d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f637573746f6d586d6c223e3c64733a736368656d61526566733e3c
+64733a736368656d615265662064733a7572693d22687474703a2f2f736368656d61732e6f70656e500072006f007000650072007400690065007300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000200ffffffffffffffffffffffff000000000000
+0000000000000000000000000000000000000000000000000000000000000400000055010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000786d6c666f726d6174732e6f72672f6f6666696365446f63756d656e742f323030362f6269626c696f677261706879222f3e3c2f64733a736368656d61526566733e3c2f64733a6461746173746f
+72654974656d3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000105000000000000}} \ No newline at end of file
diff --git a/sw/qa/extras/globalfilter/data/graphic_shape.odt b/sw/qa/extras/globalfilter/data/graphic_shape.odt
new file mode 100644
index 0000000000..425e8c2f32
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/graphic_shape.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/images_with_special_IDs.odt b/sw/qa/extras/globalfilter/data/images_with_special_IDs.odt
new file mode 100644
index 0000000000..d4c62f5d2b
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/images_with_special_IDs.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/linked_graphic.jpg b/sw/qa/extras/globalfilter/data/linked_graphic.jpg
new file mode 100644
index 0000000000..2218cdd72d
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/linked_graphic.jpg
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/multiple_identical_graphics.odt b/sw/qa/extras/globalfilter/data/multiple_identical_graphics.odt
new file mode 100644
index 0000000000..20f40798ed
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/multiple_identical_graphics.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/skipimages.doc b/sw/qa/extras/globalfilter/data/skipimages.doc
new file mode 100644
index 0000000000..3c40599b08
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/skipimages.doc
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/skipimages.docx b/sw/qa/extras/globalfilter/data/skipimages.docx
new file mode 100644
index 0000000000..cc6a4f4cea
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/skipimages.docx
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/tdf138345_charstyle_highlight.odt b/sw/qa/extras/globalfilter/data/tdf138345_charstyle_highlight.odt
new file mode 100644
index 0000000000..6886ed8f71
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/tdf138345_charstyle_highlight.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/tdf143311-1.docx b/sw/qa/extras/globalfilter/data/tdf143311-1.docx
new file mode 100644
index 0000000000..b6b2d08981
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/tdf143311-1.docx
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/text13e.odt b/sw/qa/extras/globalfilter/data/text13e.odt
new file mode 100644
index 0000000000..bb16e0467e
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/text13e.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/data/text_form_field.odt b/sw/qa/extras/globalfilter/data/text_form_field.odt
new file mode 100644
index 0000000000..96af26f770
--- /dev/null
+++ b/sw/qa/extras/globalfilter/data/text_form_field.odt
Binary files differ
diff --git a/sw/qa/extras/globalfilter/globalfilter.cxx b/sw/qa/extras/globalfilter/globalfilter.cxx
new file mode 100644
index 0000000000..9d7c28b83f
--- /dev/null
+++ b/sw/qa/extras/globalfilter/globalfilter.cxx
@@ -0,0 +1,2267 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <swmodeltestbase.hxx>
+
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/graphic/GraphicType.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XDocumentIndex.hpp>
+#include <o3tl/safeint.hxx>
+#include <o3tl/string_view.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <tools/zcodec.hxx>
+#include <vcl/filter/pdfdocument.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <unotxdoc.hxx>
+#include <docsh.hxx>
+#include <editsh.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <doc.hxx>
+#include <ndgrf.hxx>
+#include <ndtxt.hxx>
+#include <ndindex.hxx>
+#include <pam.hxx>
+#include <unotools/fltrcfg.hxx>
+#include <xmloff/odffields.hxx>
+#include <IDocumentMarkAccess.hxx>
+#include <IMark.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <unotools/mediadescriptor.hxx>
+
+class Test : public SwModelTestBase
+{
+public:
+ Test() : SwModelTestBase("/sw/qa/extras/globalfilter/data/") {}
+
+ void testEmbeddedGraphicRoundtrip();
+ void testLinkedGraphicRT();
+ void testImageWithSpecialID();
+ void testGraphicShape();
+ void testMultipleIdenticalGraphics();
+ void testCharHighlight();
+ void testCharHighlightODF();
+ void testCharHighlightBody();
+ void testCharStyleHighlight();
+ void testMSCharBackgroundEditing();
+ void testCharBackgroundToHighlighting();
+#if !defined(_WIN32)
+ void testSkipImages();
+#endif
+ void testNestedFieldmark();
+ void verifyText13(char const*);
+ void testODF13();
+ void testRedlineFlags();
+ void testBulletAsImage();
+ void testTextFormField();
+ void testCheckBoxFormField();
+ void testDropDownFormField();
+ void testDateFormField();
+ void testDateFormFieldCharacterFormatting();
+ void testSvgImageSupport();
+
+ CPPUNIT_TEST_SUITE(Test);
+ CPPUNIT_TEST(testEmbeddedGraphicRoundtrip);
+ CPPUNIT_TEST(testLinkedGraphicRT);
+ CPPUNIT_TEST(testImageWithSpecialID);
+ CPPUNIT_TEST(testGraphicShape);
+ CPPUNIT_TEST(testMultipleIdenticalGraphics);
+ CPPUNIT_TEST(testCharHighlight);
+ CPPUNIT_TEST(testCharHighlightODF);
+ CPPUNIT_TEST(testMSCharBackgroundEditing);
+ CPPUNIT_TEST(testCharBackgroundToHighlighting);
+#if !defined(_WIN32)
+ CPPUNIT_TEST(testSkipImages);
+#endif
+ CPPUNIT_TEST(testNestedFieldmark);
+ CPPUNIT_TEST(testODF13);
+ CPPUNIT_TEST(testRedlineFlags);
+ CPPUNIT_TEST(testBulletAsImage);
+ CPPUNIT_TEST(testTextFormField);
+ CPPUNIT_TEST(testCheckBoxFormField);
+ CPPUNIT_TEST(testDropDownFormField);
+ CPPUNIT_TEST(testDateFormField);
+ CPPUNIT_TEST(testDateFormFieldCharacterFormatting);
+ CPPUNIT_TEST(testSvgImageSupport);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void Test::testEmbeddedGraphicRoundtrip()
+{
+ OUString aFilterNames[] = {
+ "writer8",
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ // Check whether the export code swaps in the image which was swapped out before by auto mechanism
+
+ createSwDoc("document_with_two_images.odt");
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check whether graphic exported well after it was swapped out
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 2, getShapes());
+
+ // First image
+ uno::Reference<drawing::XShape> xImage(getShape(1), uno::UNO_QUERY);
+ uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
+
+ // Check graphic, size
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), graphic::GraphicType::PIXEL, xGraphic->getType());
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height);
+ }
+
+ // Second Image
+ xImage.set(getShape(2), uno::UNO_QUERY);
+ XPropSet.set( xImage, uno::UNO_QUERY_THROW );
+
+ // Check graphic, size
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), graphic::GraphicType::PIXEL, xGraphic->getType());
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height);
+ }
+ }
+}
+
+void Test::testLinkedGraphicRT()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+// "Rich Text Format", Note: picture is there, but SwGrfNode is not found?
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("document_with_linked_graphic.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pDoc);
+ SwNodes& aNodes = pDoc->GetNodes();
+
+ // Find the image
+ bool bImageFound = false;
+ Graphic aGraphic;
+ for (SwNodeOffset nIndex(0); nIndex < aNodes.Count(); ++nIndex)
+ {
+ if (aNodes[nIndex]->IsGrfNode())
+ {
+ SwGrfNode* pGrfNode = aNodes[nIndex]->GetGrfNode();
+ CPPUNIT_ASSERT(pGrfNode);
+
+ const GraphicObject& rGraphicObj = pGrfNode->GetGrfObj(true);
+ aGraphic = rGraphicObj.GetGraphic();
+ bImageFound = true;
+ }
+ }
+
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), bImageFound);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_uLong(864900), aGraphic.GetSizeBytes());
+
+ // Check if linked graphic is registered in LinkManager
+ sfx2::LinkManager& rLinkManager = pTextDoc->GetDocShell()->GetDoc()->GetEditShell()->GetLinkManager();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), size_t(1), rLinkManager.GetLinks().size());
+ const tools::SvRef<sfx2::SvBaseLink> & rLink = rLinkManager.GetLinks()[0];
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), rLink->GetLinkSourceName().indexOf("linked_graphic.jpg") >= 0);
+ }
+}
+
+void Test::testImageWithSpecialID()
+{
+ // Check how LO handles when the imported graphic's ID is different from that one
+ // which is generated by LO.
+
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("images_with_special_IDs.odt");
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check whether graphic exported well
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 2, getShapes());
+
+ uno::Reference<drawing::XShape> xImage = getShape(1);
+ uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY_THROW );
+
+ // Check graphic, size
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), graphic::GraphicType::PIXEL, xGraphic->getType());
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height);
+ }
+
+ // Second Image
+ xImage.set(getShape(2), uno::UNO_QUERY);
+ XPropSet.set( xImage, uno::UNO_QUERY_THROW );
+
+ // Check graphic, size
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), graphic::GraphicType::PIXEL, xGraphic->getType());
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(900), xBitmap->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(600), xBitmap->getSize().Height);
+ }
+ }
+}
+
+/// Gives the first embedded or linked image in a document.
+static uno::Reference<drawing::XShape> lcl_getShape(const uno::Reference<lang::XComponent>& xComponent, bool bEmbedded)
+{
+ uno::Reference<drawing::XShape> xShape;
+
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i)
+ {
+ uno::Reference<beans::XPropertySet> xShapeProperties(xDrawPage->getByIndex(i), uno::UNO_QUERY);
+ uno::Reference<graphic::XGraphic> xGraphic;
+ xShapeProperties->getPropertyValue("Graphic") >>= xGraphic;
+ if (xGraphic.is())
+ {
+ Graphic aGraphic(xGraphic);
+
+ if (bEmbedded == aGraphic.getOriginURL().isEmpty())
+ {
+ xShape.set(xShapeProperties, uno::UNO_QUERY);
+ return xShape;
+ }
+ }
+ }
+
+ return xShape;
+}
+
+void Test::testGraphicShape()
+{
+ // There are two kind of images in Writer: 1) Writer specific handled by SwGrfNode and
+ // 2) graphic shape handled by SdrGrafObj (e.g. after copy&paste from Impress).
+
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("graphic_shape.odt");
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check whether graphic exported well
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 2, getShapes());
+
+ uno::Reference<drawing::XShape> xImage = lcl_getShape(mxComponent, true);
+ CPPUNIT_ASSERT_MESSAGE("Couldn't load the shape/image", xImage.is());
+ uno::Reference< beans::XPropertySet > XPropSet( xImage, uno::UNO_QUERY );
+ // First image is embedded
+ // Check size
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(610), xBitmap->getSize().Width );
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(381), xBitmap->getSize().Height );
+ }
+
+ // MS filters make this kind of linked images broken !?
+ if (rFilterName != "writer8")
+ return;
+
+ // Second image is a linked one
+ xImage = lcl_getShape(mxComponent, false);
+ XPropSet.set(xImage, uno::UNO_QUERY);
+ const OString sFailedImageLoad = OString::Concat("Couldn't load the shape/image for ") + rFilterName.toUtf8();
+ CPPUNIT_ASSERT_MESSAGE(sFailedImageLoad.getStr(), xImage.is());
+
+ // Check size
+ {
+ uno::Reference<graphic::XGraphic> xGraphic;
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+
+ Graphic aGraphic(xGraphic);
+ OUString sURL = aGraphic.getOriginURL();
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), sURL.endsWith("linked_graphic.jpg"));
+
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(620), xBitmap->getSize().Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(465), xBitmap->getSize().Height);
+ }
+ }
+}
+
+namespace
+{
+
+std::vector<uno::Reference<graphic::XGraphic>>
+ lcl_getGraphics(const uno::Reference<lang::XComponent>& xComponent)
+{
+ std::vector<uno::Reference<graphic::XGraphic>> aGraphics;
+
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(xComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage();
+ for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i)
+ {
+ uno::Reference<beans::XPropertySet> xShapeProperties(xDrawPage->getByIndex(i), uno::UNO_QUERY);
+ uno::Reference<graphic::XGraphic> xGraphic;
+ xShapeProperties->getPropertyValue("Graphic") >>= xGraphic;
+ if (xGraphic.is())
+ {
+ aGraphics.push_back(xGraphic);
+ }
+ }
+
+ return aGraphics;
+}
+
+}
+
+void Test::testMultipleIdenticalGraphics()
+{
+ // We have multiple identical graphics. When we save them we want
+ // them to be saved de-duplicated and the same should still be true
+ // after loading them again. This test check that the de-duplication
+ // works as expected.
+
+ const OUString aFilterNames[] {
+ "writer8",
+ //"Rich Text Format", // doesn't work correctly for now
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("multiple_identical_graphics.odt");
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check whether graphic exported well
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+ auto aGraphics = lcl_getGraphics(mxComponent);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), size_t(5), aGraphics.size());
+
+ // Get all GfxLink addresses, we expect all of them to be the same
+ // indicating we use the same graphic instance for all shapes
+ std::vector<sal_Int64> aGfxLinkAddresses;
+ for (auto const & rxGraphic : aGraphics)
+ {
+ GfxLink* pLink = Graphic(rxGraphic).GetSharedGfxLink().get();
+ aGfxLinkAddresses.emplace_back(reinterpret_cast<sal_Int64>(pLink));
+ }
+
+ // Check all addresses are the same
+ bool bResult = std::equal(aGfxLinkAddresses.begin() + 1, aGfxLinkAddresses.end(), aGfxLinkAddresses.begin());
+ const OString sGraphicNotTheSameFailedMessage = OString::Concat("Graphics not the same for filter: '") +
+ rFilterName.toUtf8() + OString::Concat("'");
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sGraphicNotTheSameFailedMessage.getStr(), true, bResult);
+ }
+}
+
+void Test::testCharHighlightBody()
+{
+ // MS Word has two kind of character backgrounds called character shading and highlighting
+ // MS filters handle these attributes separately, but ODF export merges them into one background attribute
+
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("char_highlight.docx");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ const uno::Reference< text::XTextRange > xPara = getParagraph(1);
+ // Both highlight and background
+ const Color nBackColor(0x4F81BD);
+ for( int nRun = 1; nRun <= 16; ++nRun )
+ {
+ const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,nRun), uno::UNO_QUERY);
+ Color nHighlightColor;
+ switch( nRun )
+ {
+ case 1: nHighlightColor = COL_BLACK; break; //black 0x000000
+ case 2: nHighlightColor = COL_LIGHTBLUE; break; //light blue 0x0000ff
+ case 3: nHighlightColor = COL_LIGHTCYAN; break; //light cyan 0x00ffff
+ case 4: nHighlightColor = COL_LIGHTGREEN; break; //light green 0x00ff00
+ case 5: nHighlightColor = COL_LIGHTMAGENTA; break; //light magenta 0xff00ff
+ case 6: nHighlightColor = COL_LIGHTRED; break; //light red 0xff0000
+ case 7: nHighlightColor = COL_YELLOW; break; //yellow 0xffff00
+ case 8: nHighlightColor = COL_WHITE; break; //white 0xffffff
+ case 9: nHighlightColor = COL_BLUE; break;//blue 0x000080
+ case 10: nHighlightColor = COL_CYAN; break; //cyan 0x008080
+ case 11: nHighlightColor = COL_GREEN; break; //green 0x008000
+ case 12: nHighlightColor = COL_MAGENTA; break; //magenta 0x800080
+ case 13: nHighlightColor = COL_RED; break; //red 0x800000
+ case 14: nHighlightColor = COL_BROWN; break; //brown 0x808000
+ case 15: nHighlightColor = COL_GRAY; break; //dark gray 0x808080
+ case 16: nHighlightColor = COL_LIGHTGRAY; break; //light gray 0xC0C0C0
+ }
+
+ if (rFilterName == "writer8")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nHighlightColor, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ else // MS filters
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nHighlightColor, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nBackColor, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ }
+
+ // Only highlight
+ {
+ const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,18), uno::UNO_QUERY);
+ if (rFilterName == "writer8")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTRED, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTRED, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ }
+
+ // Only background
+ {
+ const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,19), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTBLUE, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ }
+}
+
+void Test::testCharStyleHighlight()
+{
+ // MS Word has two kind of character backgrounds called character shading and highlighting.
+ // However, their character style can only accept shading. It ignores the highlighting value.
+
+ const OUString aFilterNames[] = {
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("tdf138345_charstyle_highlight.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ uno::Reference<beans::XPropertySet> xCharStyle;
+ getStyles("CharacterStyles")->getByName("charBackground") >>= xCharStyle;
+ const Color nBackColor(0xFFDBB6); //orange-y
+
+ // Always export character style's background colour as shading, never as highlighting.
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xCharStyle,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nBackColor, getProperty<Color>(xCharStyle,"CharBackColor"));
+ }
+}
+
+void Test::testCharHighlight()
+{
+ SvtFilterOptions& rOpt = SvtFilterOptions::Get();
+ rOpt.SetCharBackground2Shading();
+
+ testCharHighlightBody();
+ testCharStyleHighlight();
+
+ rOpt.SetCharBackground2Highlighting();
+
+ testCharHighlightBody();
+ testCharStyleHighlight();
+}
+
+void Test::testCharHighlightODF()
+{
+ createSwDoc("char_background_editing.docx");
+
+ // don't check import, testMSCharBackgroundEditing already does that
+
+ uno::Reference<text::XTextRange> xPara = getParagraph(1);
+ for (int i = 1; i <= 4; ++i)
+ {
+ uno::Reference<beans::XPropertySet> xRun(getRun(xPara,i), uno::UNO_QUERY);
+ switch (i)
+ {
+ case 1: // non-transparent highlight
+ xRun->setPropertyValue("CharBackColor", uno::Any(static_cast<sal_Int32>(128)));
+ xRun->setPropertyValue("CharBackTransparent", uno::Any(true));
+ xRun->setPropertyValue("CharHighlight", uno::Any(static_cast<sal_Int32>(64)));
+ break;
+
+ case 2: // transparent backcolor
+ xRun->setPropertyValue("CharBackColor", uno::Any(static_cast<sal_Int32>(128)));
+ xRun->setPropertyValue("CharBackTransparent", uno::Any(true));
+ xRun->setPropertyValue("CharHighlight", uno::Any(static_cast<sal_Int32>(COL_TRANSPARENT)));
+ break;
+
+ case 3: // non-transparent backcolor
+ xRun->setPropertyValue("CharBackColor", uno::Any(static_cast<sal_Int32>(128)));
+ xRun->setPropertyValue("CharBackTransparent", uno::Any(false));
+ xRun->setPropertyValue("CharHighlight", uno::Any(static_cast<sal_Int32>(COL_TRANSPARENT)));
+ break;
+
+ case 4: // non-transparent highlight again
+ xRun->setPropertyValue("CharBackColor", uno::Any(static_cast<sal_Int32>(128)));
+ xRun->setPropertyValue("CharBackTransparent", uno::Any(false));
+ xRun->setPropertyValue("CharHighlight", uno::Any(static_cast<sal_Int32>(64)));
+ break;
+ }
+ }
+
+ saveAndReload("writer8");
+
+ xPara.set(getParagraph(1));
+ for (int i = 1; i <= 4; ++i)
+ {
+ uno::Reference<beans::XPropertySet> xRun(getRun(xPara,i), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(COL_TRANSPARENT), getProperty<sal_Int32>(xRun, "CharHighlight"));
+ switch (i)
+ {
+ case 1: // non-transparent highlight
+ CPPUNIT_ASSERT_EQUAL(Color(0x000040), getProperty<Color>(xRun, "CharBackColor"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xRun, "CharBackTransparent"));
+ break;
+ case 2: // transparent backcolor
+ CPPUNIT_ASSERT_EQUAL(COL_TRANSPARENT, getProperty<Color>(xRun, "CharBackColor"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(xRun, "CharBackTransparent"));
+ break;
+ case 3: // non-transparent backcolor
+ CPPUNIT_ASSERT_EQUAL(COL_BLUE, getProperty<Color>(xRun, "CharBackColor"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xRun, "CharBackTransparent"));
+ break;
+ case 4: // non-transparent highlight again
+ CPPUNIT_ASSERT_EQUAL(Color(0x000040), getProperty<Color>(xRun, "CharBackColor"));
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xRun, "CharBackTransparent"));
+ break;
+ }
+ }
+}
+
+void Test::testMSCharBackgroundEditing()
+{
+ // Simulate the editing process of imported MSO character background attributes
+ // and check how export behaves.
+
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("char_background_editing.docx");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Check whether import was done on the right way
+ uno::Reference< text::XTextRange > xPara = getParagraph(1);
+ {
+ uno::Reference<beans::XPropertySet> xRun(getRun(xPara,1), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTRED, getProperty<Color>(xRun,"CharBackColor"));
+
+ xRun.set(getRun(xPara,2), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTBLUE, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharBackColor"));
+
+ xRun.set(getRun(xPara,3), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTBLUE, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_LIGHTRED, getProperty<Color>(xRun,"CharBackColor"));
+
+ xRun.set(getRun(xPara,4), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharBackColor"));
+ }
+
+ // Simulate editing
+ for( int i = 1; i <= 4; ++i )
+ {
+ uno::Reference<beans::XPropertySet> xRun(getRun(xPara,i), uno::UNO_QUERY);
+ // Change background
+ Color nBackColor;
+ switch( i )
+ {
+ case 1: nBackColor = COL_BLACK; break; //black 0x000000
+ case 2: nBackColor = COL_LIGHTCYAN; break; //cyan 0x00ffff
+ case 3: nBackColor = COL_LIGHTGREEN; break; //green 0x00ff00
+ case 4: nBackColor = COL_LIGHTMAGENTA; break; //magenta 0xff00ff
+ }
+ xRun->setPropertyValue("CharBackColor", uno::Any(nBackColor));
+ // Remove highlighting
+ xRun->setPropertyValue("CharHighlight", uno::Any(COL_TRANSPARENT));
+ // Remove shading marker
+ uno::Sequence<beans::PropertyValue> aGrabBag = getProperty<uno::Sequence<beans::PropertyValue> >(xRun,"CharInteropGrabBag");
+ for (beans::PropertyValue& rProp : asNonConstRange(aGrabBag))
+ {
+ if (rProp.Name == "CharShadingMarker")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), true, rProp.Value.get<bool>());
+ rProp.Value <<= false;
+ }
+ }
+ xRun->setPropertyValue("CharInteropGrabBag", uno::Any(aGrabBag));
+ }
+
+ SvtFilterOptions& rOpt = SvtFilterOptions::Get();
+ rOpt.SetCharBackground2Highlighting();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check whether background was exported as highlighting
+ xPara.set(getParagraph(1));
+ for( int i = 1; i <= 4; ++i )
+ {
+ Color nBackColor;
+ switch( i )
+ {
+ case 1: nBackColor = COL_BLACK; break; //black 0x000000
+ case 2: nBackColor = COL_LIGHTCYAN; break; //light cyan 0x00ffff
+ case 3: nBackColor = COL_LIGHTGREEN; break; //light green 0x00ff00
+ case 4: nBackColor = COL_LIGHTMAGENTA; break; //light magenta 0xff00ff
+ }
+ const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,i), uno::UNO_QUERY);
+ if (rFilterName == "writer8")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nBackColor, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ else
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), nBackColor, getProperty<Color>(xRun,"CharHighlight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_TRANSPARENT, getProperty<Color>(xRun,"CharBackColor"));
+ }
+ }
+ }
+}
+
+void Test::testCharBackgroundToHighlighting()
+{
+ // MSO highlighting has less kind of values so let's see how LO character background is converted
+ // to these values
+
+ const OUString aFilterNames[] = {
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ createSwDoc("char_background.odt");
+
+ OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+
+ SvtFilterOptions& rOpt = SvtFilterOptions::Get();
+ rOpt.SetCharBackground2Highlighting();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check highlight color
+ const uno::Reference< text::XTextRange > xPara = getParagraph(1);
+ for( int nRun = 1; nRun <= 19; ++nRun )
+ {
+ const uno::Reference<beans::XPropertySet> xRun(getRun(xPara,nRun), uno::UNO_QUERY);
+ Color nHighlightColor;
+ switch( nRun )
+ {
+ case 1: nHighlightColor = COL_BLACK; break; //black 0x000000
+ case 2: nHighlightColor = COL_YELLOW; break; //yellow 0xffff00
+ case 3: nHighlightColor = COL_LIGHTMAGENTA; break; //light magenta 0xff00ff
+ case 4: nHighlightColor = COL_LIGHTCYAN; break; //light cyan 0x00ffff
+ case 5: nHighlightColor = COL_YELLOW; break; //yellow 0xffff00
+ case 6: nHighlightColor = COL_LIGHTRED; break; //light red 0xff0000
+ case 7: nHighlightColor = COL_LIGHTBLUE; break; //light blue 0x0000ff
+ case 8: nHighlightColor = COL_LIGHTGREEN; break; //light green 0x00ff00
+ case 9: nHighlightColor = COL_GREEN; break; //dark green 0x008000
+ case 10: nHighlightColor = COL_MAGENTA; break; //dark magenta 0x800080
+ case 11: nHighlightColor = COL_BLUE; break; //dark blue 0x000080
+ case 12: nHighlightColor = COL_BROWN; break; //brown 0x808000
+ case 13: nHighlightColor = COL_GRAY; break; //dark gray 0x808080
+ case 14: nHighlightColor = COL_BLACK; break; //black 0x000000
+ case 15: nHighlightColor = COL_LIGHTRED; break; //light red 0xff0000
+ case 16: nHighlightColor = COL_LIGHTGRAY; break; //light gray 0xC0C0C0
+ case 17: nHighlightColor = COL_RED; break; //dark red 0x800000
+ case 18: nHighlightColor = COL_GRAY; break; //dark gray 0x808080
+ case 19: nHighlightColor = COL_YELLOW; break; //yellow 0xffff00
+ }
+ const OString sMessage = sFailedMessage +". Index of run with unmatched color: " + OString::number(nRun);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), nHighlightColor, getProperty<Color>(xRun,"CharHighlight"));
+ }
+ }
+}
+
+#if !defined(_WIN32)
+void Test::testSkipImages()
+{
+ // Check how LO skips image loading (but not texts of textboxes and custom shapes)
+ // during DOC and DOCX import, using the "SkipImages" FilterOptions.
+
+ std::pair<OUString, OUString> aFilterNames[] = {
+ { "skipimages.doc", "" },
+ { "skipimages.doc", "SkipImages" },
+ { "skipimages.docx", "" },
+ { "skipimages.docx", "SkipImages" }
+ };
+
+ for (auto const & rFilterNamePair : aFilterNames)
+ {
+ bool bSkipImages = !rFilterNamePair.second.isEmpty();
+ OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterNamePair.first.toUtf8();
+
+ setImportFilterOptions(rFilterNamePair.second);
+ createSwDoc(rFilterNamePair.first.toUtf8().getStr());
+ sFailedMessage += " - " + rFilterNamePair.second.toUtf8();
+
+ // Check shapes (images, textboxes, custom shapes)
+ uno::Reference<drawing::XShape> xShape;
+ uno::Reference<graphic::XGraphic> xGraphic;
+ uno::Reference< beans::XPropertySet > XPropSet;
+ uno::Reference<awt::XBitmap> xBitmap;
+
+ bool bHasTextboxText = false;
+ bool bHasCustomShapeText = false;
+ sal_Int32 nImageCount = 0;
+
+ for (int i = 1; i<= getShapes(); i++)
+ {
+ xShape = getShape(i);
+ XPropSet.set( xShape, uno::UNO_QUERY_THROW );
+ try
+ {
+ XPropSet->getPropertyValue("Graphic") >>= xGraphic;
+ xBitmap.set(xGraphic, uno::UNO_QUERY);
+ if (xBitmap.is())
+ nImageCount++;
+ }
+ catch (beans::UnknownPropertyException &)
+ { /* ignore */ }
+
+ uno::Reference<text::XTextRange> xText(xShape, uno::UNO_QUERY);
+ if (xText.is())
+ {
+ OUString shapeText = xText->getString();
+ if (shapeText.startsWith("Lorem ipsum"))
+ bHasTextboxText = true;
+ else if (shapeText.startsWith("Nam pretium"))
+ bHasCustomShapeText = true;
+ }
+ }
+
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), bHasTextboxText);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), bHasCustomShapeText);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), static_cast<sal_Int32>(bSkipImages ? 0 : 3), nImageCount );
+ }
+}
+#endif
+
+static auto verifyNestedFieldmark(OUString const& rTestName,
+ uno::Reference<lang::XComponent> const& xComponent) -> void
+{
+ SwDoc const*const pDoc(dynamic_cast<SwXTextDocument&>(*xComponent).GetDocShell()->GetDoc());
+ IDocumentMarkAccess const& rIDMA(*pDoc->getIDocumentMarkAccess());
+
+ // no spurious bookmarks have been created
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(rTestName.toUtf8().getStr(),
+ sal_Int32(0), rIDMA.getBookmarksCount());
+
+ // check inner fieldmark
+ SwNodeIndex const node1(*pDoc->GetNodes().GetEndOfContent().StartOfSectionNode(), +2);
+ SwPosition const innerPos(*node1.GetNode().GetTextNode(),
+ node1.GetNode().GetTextNode()->GetText().indexOf(CH_TXT_ATR_FIELDSTART));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(rTestName.toUtf8().getStr(),
+ sal_Int32(1), innerPos.GetContentIndex());
+ ::sw::mark::IFieldmark *const pInner(rIDMA.getFieldmarkAt(innerPos));
+ CPPUNIT_ASSERT_MESSAGE(rTestName.toUtf8().getStr(), pInner);
+ OUString const innerString(SwPaM(pInner->GetMarkPos(), pInner->GetOtherMarkPos()).GetText());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(rTestName.toUtf8().getStr(), OUString(
+ OUStringChar(CH_TXT_ATR_FIELDSTART) + u" QUOTE \"foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz\" " + OUStringChar(CH_TXT_ATR_FIELDSEP) + u"foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz" + OUStringChar(CH_TXT_ATR_FIELDEND)), innerString);
+
+ // check outer fieldmark
+ SwNodeIndex const node2(node1, -1);
+ SwPosition const outerPos(*node2.GetNode().GetTextNode(),
+ node2.GetNode().GetTextNode()->GetText().indexOf(CH_TXT_ATR_FIELDSTART));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(rTestName.toUtf8().getStr(),
+ sal_Int32(0), outerPos.GetContentIndex());
+ ::sw::mark::IFieldmark const*const pOuter(rIDMA.getFieldmarkAt(outerPos));
+ CPPUNIT_ASSERT_MESSAGE(rTestName.toUtf8().getStr(), pOuter);
+ OUString const outerString(SwPaM(pOuter->GetMarkPos(), pOuter->GetOtherMarkPos()).GetText());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(rTestName.toUtf8().getStr(), OUString(
+ OUStringChar(CH_TXT_ATR_FIELDSTART) + u" QUOTE \"foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" " + OUStringChar(CH_TXT_ATR_FIELDSTART) + u" QUOTE \"foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz\" " + OUStringChar(CH_TXT_ATR_FIELDSEP) + u"foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz" + OUStringChar(CH_TXT_ATR_FIELDEND) + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz\" " + OUStringChar(CH_TXT_ATR_FIELDSEP) + u"foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" foo " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u" bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz" + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"bar " + OUStringChar(CH_TXTATR_NEWLINE)
+ + u"baz" + OUStringChar(CH_TXT_ATR_FIELDEND)), outerString);
+
+ // must return innermost mark
+ CPPUNIT_ASSERT_EQUAL(pInner, rIDMA.getInnerFieldmarkFor(innerPos));
+}
+
+void Test::testNestedFieldmark()
+{
+ // experimental config setting
+ Resetter resetter(
+ [] () {
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Filter::Microsoft::Import::ForceImportWWFieldsAsGenericFields::set(false, pBatch);
+ return pBatch->commit();
+ });
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Filter::Microsoft::Import::ForceImportWWFieldsAsGenericFields::set(true, pBatch);
+ pBatch->commit();
+
+ std::pair<OUString, OUString> const aFilterNames[] = {
+ {"writer8", "fieldmark_QUOTE_nest.fodt"},
+ {"Office Open XML Text", "fieldmark_QUOTE_nest.docx"},
+ {"Rich Text Format", "fieldmark_QUOTE_nest.rtf"},
+ };
+
+ for (auto const & rFilterName : aFilterNames)
+ {
+ createSwDoc(rFilterName.second.toUtf8().getStr());
+
+ verifyNestedFieldmark(rFilterName.first + ", load", mxComponent);
+
+ // Export the document and import again
+ saveAndReload(rFilterName.first);
+
+ verifyNestedFieldmark(rFilterName.first + " exported-reload", mxComponent);
+ }
+}
+
+auto Test::verifyText13(char const*const pTestName) -> void
+{
+ // OFFICE-3789 style:header-first/style:footer-first
+ uno::Reference<beans::XPropertySet> xPageStyle;
+ getStyles("PageStyles")->getByName("Standard") >>= xPageStyle;
+ uno::Reference<text::XText> xHF(getProperty<uno::Reference<text::XText>>(xPageStyle, "HeaderTextFirst"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("Header first"), xHF->getString());
+ uno::Reference<text::XText> xFF(getProperty<uno::Reference<text::XText>>(xPageStyle, "FooterTextFirst"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("Footer first"), xFF->getString());
+ // OFFICE-3767 text:contextual-spacing
+ uno::Reference<text::XTextRange> xPara(getParagraph(1));
+ CPPUNIT_ASSERT_MESSAGE(pTestName, getProperty<bool>(xPara, "ParaContextMargin"));
+ // OFFICE-3776 meta:creator-initials
+ uno::Reference<text::XTextRange> xRun(getRun(xPara, 1));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("Annotation"), getProperty<OUString>(xRun, "TextPortionType"));
+ uno::Reference<beans::XPropertySet> xComment(getProperty<uno::Reference<beans::XPropertySet>>(xRun, "TextField"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("dj"), getProperty<OUString>(xComment, "Initials"));
+ // OFFICE-3941 text:index-entry-link-start/text:index-entry-link-end
+ uno::Reference<text::XDocumentIndexesSupplier> xDIS(mxComponent, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xIndexes(xDIS->getDocumentIndexes());
+ uno::Reference<text::XDocumentIndex> xIndex(xIndexes->getByIndex(0), uno::UNO_QUERY);
+ uno::Reference<container::XIndexReplace> xLevels(getProperty<uno::Reference<container::XIndexReplace>>(xIndex, "LevelFormat"));
+ uno::Sequence<beans::PropertyValues> format;
+ xLevels->getByIndex(1) >>= format; // 1-based?
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("TokenType"), format[0][0].Name);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("TokenHyperlinkStart"), format[0][0].Value.get<OUString>());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("TokenType"), format[4][0].Name);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(pTestName, OUString("TokenHyperlinkEnd"), format[4][0].Value.get<OUString>());
+}
+
+// test ODF 1.3 new text document features
+void Test::testODF13()
+{
+ // import
+ createSwDoc("text13e.odt");
+
+ // check model
+ verifyText13("import");
+
+ Resetter _([]() {
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Save::ODF::DefaultVersion::set(3, pBatch);
+ return pBatch->commit();
+ });
+
+ {
+ // export ODF 1.3
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Save::ODF::DefaultVersion::set(10, pBatch);
+ pBatch->commit();
+
+ saveAndReload("writer8");
+
+ // check XML
+ xmlDocUniquePtr pContentXml = parseExport("content.xml");
+ assertXPath(pContentXml, "/office:document-content/office:automatic-styles/style:style/style:paragraph-properties[@style:contextual-spacing='true']"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:p/office:annotation/meta:creator-initials"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:p/office:annotation/loext:sender-initials"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/text:index-entry-link-start"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/loext:index-entry-link-start"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/text:index-entry-link-end"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/loext:index-entry-link-end"_ostr, 0);
+ xmlDocUniquePtr pStylesXml = parseExport("styles.xml");
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/style:header-first"_ostr);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/loext:header-first"_ostr, 0);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/style:footer-first"_ostr);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/loext:footer-first"_ostr, 0);
+
+ // check model
+ verifyText13("1.3 reload");
+ }
+ {
+ // export ODF 1.2 extended
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Save::ODF::DefaultVersion::set(9, pBatch);
+ pBatch->commit();
+
+ // FIXME: it's not possible to use 'reload' here because the validation fails with
+ // Error: unexpected attribute "loext:contextual-spacing"
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer8");
+
+ uno::Reference<frame::XStorable> const xStorable(mxComponent, uno::UNO_QUERY);
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // check XML
+ xmlDocUniquePtr pContentXml = parseExport("content.xml");
+ assertXPath(pContentXml, "/office:document-content/office:automatic-styles/style:style/style:paragraph-properties[@loext:contextual-spacing='true']"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:p/office:annotation/loext:sender-initials"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:p/office:annotation/meta:creator-initials"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/loext:index-entry-link-start"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/text:index-entry-link-start"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/loext:index-entry-link-end"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/text:index-entry-link-end"_ostr, 0);
+ xmlDocUniquePtr pStylesXml = parseExport("styles.xml");
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/loext:header-first"_ostr);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/style:header-first"_ostr, 0);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/loext:footer-first"_ostr);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/style:footer-first"_ostr, 0);
+
+ // reload
+ mxComponent->dispose();
+ mxComponent = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument");
+
+ // check model
+ verifyText13("1.2 Extended reload");
+ }
+ {
+ // export ODF 1.2
+ std::shared_ptr<comphelper::ConfigurationChanges> pBatch(
+ comphelper::ConfigurationChanges::create());
+ officecfg::Office::Common::Save::ODF::DefaultVersion::set(4, pBatch);
+ pBatch->commit();
+
+ // don't reload - no point
+ save("writer8");
+
+ // check XML
+ xmlDocUniquePtr pContentXml = parseExport("content.xml");
+ assertXPathNoAttribute(pContentXml, "/office:document-content/office:automatic-styles/style:style/style:paragraph-properties"_ostr, "contextual-spacing"_ostr);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:p/office:annotation/meta:creator-initials"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:p/office:annotation/loext:sender-initials"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/text:index-entry-link-start"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/loext:index-entry-link-start"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/text:index-entry-link-end"_ostr, 0);
+ assertXPath(pContentXml, "/office:document-content/office:body/office:text/text:illustration-index/text:illustration-index-source/text:illustration-index-entry-template/loext:index-entry-link-end"_ostr, 0);
+ xmlDocUniquePtr pStylesXml = parseExport("styles.xml");
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/style:header-first"_ostr, 0);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/loext:header-first"_ostr, 0);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/style:footer-first"_ostr, 0);
+ assertXPath(pStylesXml, "/office:document-styles/office:master-styles/style:master-page/loext:footer-first"_ostr, 0);
+ }
+}
+
+void Test::testRedlineFlags()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Rich Text Format",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ createSwDoc();
+ SwDoc* pDoc = getSwDoc();
+
+ SwPaM pam(SwPosition(pDoc->GetNodes().GetEndOfContent(), SwNodeOffset(-1)));
+ pDoc->getIDocumentContentOperations().InsertString(pam, "foo bar baz");
+
+ IDocumentRedlineAccess & rIDRA(pDoc->getIDocumentRedlineAccess());
+ // enable change tracking
+ rIDRA.SetRedlineFlags(rIDRA.GetRedlineFlags()
+ | RedlineFlags::On | RedlineFlags::ShowDelete);
+
+ // need a delete redline to trigger mode switching
+ pam.Move(fnMoveForward, GoInDoc);
+ pam.SetMark();
+ pam.Move(fnMoveBackward, GoInDoc);
+ pDoc->getIDocumentContentOperations().DeleteAndJoin(pam);
+
+ // hide delete redlines
+ RedlineFlags const nRedlineFlags =
+ rIDRA.GetRedlineFlags() & ~RedlineFlags::ShowDelete;
+ rIDRA.SetRedlineFlags(nRedlineFlags);
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ // export the document
+ save(rFilterName);
+
+ // tdf#97103 check that redline mode is properly restored
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(
+ OString(OString::Concat("redline mode not restored in ") + rFilterName.toUtf8()).getStr(),
+ static_cast<int>(nRedlineFlags), static_cast<int>(rIDRA.GetRedlineFlags()));
+ }
+}
+
+void Test::testBulletAsImage()
+{
+ OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ "Rich Text Format",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ createSwDoc("BulletAsImage.odt");
+
+ // Check if import was successful
+ {
+ uno::Reference<text::XTextRange> xPara(getParagraph(1));
+ uno::Reference<beans::XPropertySet> xPropertySet(xPara, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xLevels;
+ xLevels.set(xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aProperties;
+ xLevels->getByIndex(0) >>= aProperties;
+ uno::Reference<awt::XBitmap> xBitmap;
+ awt::Size aSize;
+ sal_Int16 nNumberingType = -1;
+
+ for (beans::PropertyValue const & rProperty : std::as_const(aProperties))
+ {
+ if (rProperty.Name == "NumberingType")
+ {
+ nNumberingType = rProperty.Value.get<sal_Int16>();
+ }
+ else if (rProperty.Name == "GraphicBitmap")
+ {
+ if (rProperty.Value.has<uno::Reference<awt::XBitmap>>())
+ {
+ xBitmap = rProperty.Value.get<uno::Reference<awt::XBitmap>>();
+ }
+ }
+ else if (rProperty.Name == "GraphicSize")
+ {
+ aSize = rProperty.Value.get<awt::Size>();
+ }
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), style::NumberingType::BITMAP, nNumberingType);
+
+ // Graphic Bitmap
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ Graphic aGraphic(uno::Reference<graphic::XGraphic>(xBitmap, uno::UNO_QUERY));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), aGraphic.GetSizeBytes() > o3tl::make_unsigned(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), tools::Long(16), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), tools::Long(16), aGraphic.GetSizePixel().Height());
+
+ // Graphic Size
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(400), aSize.Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(400), aSize.Height);
+ }
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ {
+ uno::Reference<text::XTextRange> xPara(getParagraph(1));
+ uno::Reference<beans::XPropertySet> xPropertySet(xPara, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xLevels;
+ xLevels.set(xPropertySet->getPropertyValue("NumberingRules"), uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aProperties;
+ xLevels->getByIndex(0) >>= aProperties;
+ uno::Reference<awt::XBitmap> xBitmap;
+ awt::Size aSize;
+ sal_Int16 nNumberingType = -1;
+
+ for (beans::PropertyValue const & rProperty : std::as_const(aProperties))
+ {
+ if (rProperty.Name == "NumberingType")
+ {
+ nNumberingType = rProperty.Value.get<sal_Int16>();
+ }
+ else if (rProperty.Name == "GraphicBitmap")
+ {
+ if (rProperty.Value.has<uno::Reference<awt::XBitmap>>())
+ {
+ xBitmap = rProperty.Value.get<uno::Reference<awt::XBitmap>>();
+ }
+ }
+ else if (rProperty.Name == "GraphicSize")
+ {
+ aSize = rProperty.Value.get<awt::Size>();
+ }
+ }
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), style::NumberingType::BITMAP, nNumberingType);
+
+ // Graphic Bitmap
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xBitmap.is());
+ Graphic aGraphic(uno::Reference<graphic::XGraphic>(xBitmap, uno::UNO_QUERY));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), GraphicType::Bitmap, aGraphic.GetType());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), aGraphic.GetSizeBytes() > o3tl::make_unsigned(0));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), tools::Long(16), aGraphic.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), tools::Long(16), aGraphic.GetSizePixel().Height());
+
+ // Graphic Size
+ if (rFilterName == "write8") // ODT is correct
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(400), aSize.Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(400), aSize.Height);
+ }
+ // FIXME: MS Filters don't work correctly for graphic bullet size
+ else if (rFilterName == "Office Open XML Text" || rFilterName == "Rich Text Format")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(279), aSize.Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(279), aSize.Height);
+ }
+ else if (rFilterName == "MS Word 97")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(296), aSize.Width);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(296), aSize.Height);
+ }
+ }
+ }
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testListLabelPDFExport)
+{
+ createSwDoc();
+
+ uno::Reference<text::XTextDocument> xDoc(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<text::XText> xText(xDoc->getText());
+ uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<container::XIndexReplace> xNumRule(
+ xFactory->createInstance("com.sun.star.text.NumberingRules"),
+ uno::UNO_QUERY_THROW);
+ OUString listFormat;
+ for (sal_Int32 i = 0; i < xNumRule->getCount(); ++i)
+ {
+ uno::Sequence<beans::PropertyValue> format;
+ format.getArray();
+ xNumRule->getByIndex(i) >>= format;
+ {
+ auto it(::std::find_if(format.begin(), format.end(),
+ [](auto const& r) { return r.Name == "NumberingType"; }));
+ // need something RTL
+ const_cast<uno::Any&>(it->Value) <<= style::NumberingType::CHARS_ARABIC;
+ }
+ {
+#if 0
+ // this doesn't work any more
+ auto it(::std::find_if(format.begin(), format.end(),
+ [](auto const& r) { return r.Name == "ParentNumbering"; }));
+ const_cast<uno::Any&>(it->Value) <<= sal_Int16(i + 1);
+#endif
+ listFormat += "%" + OUString::number(i+1) + "%.";
+ auto it(::std::find_if(format.begin(), format.end(),
+ [](auto const& r) { return r.Name == "ListFormat"; }));
+ const_cast<uno::Any&>(it->Value) <<= listFormat;
+ }
+ xNumRule->replaceByIndex(i, uno::Any(format));
+ }
+ uno::Reference<beans::XPropertySet>(getParagraph(1), uno::UNO_QUERY_THROW)->setPropertyValue("NumberingRules", uno::Any(xNumRule));
+ xText->insertControlCharacter(xText->getEnd(), text::ControlCharacter::PARAGRAPH_BREAK, false);
+ uno::Reference<beans::XPropertySet>(getParagraph(2), uno::UNO_QUERY_THROW)->setPropertyValue("NumberingLevel", uno::Any(sal_Int16(1)));
+ xText->insertControlCharacter(xText->getEnd(), text::ControlCharacter::PARAGRAPH_BREAK, false);
+ uno::Reference<beans::XPropertySet>(getParagraph(3), uno::UNO_QUERY_THROW)->setPropertyValue("NumberingLevel", uno::Any(sal_Int16(2)));
+
+ // check PDF export of the list items (label in particular)
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ css::uno::Reference<frame::XStorable> xStorable(mxComponent, css::uno::UNO_QUERY_THROW);
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Parse the export result with pdfium.
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument = parsePDFExport();
+
+ // Non-NULL pPdfDocument means pdfium is available.
+ if (pPdfDocument != nullptr)
+ {
+ // The document has one page.
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPdfPage = pPdfDocument->openPage(/*nIndex=*/0);
+ CPPUNIT_ASSERT(pPdfPage);
+
+ std::unique_ptr<vcl::pdf::PDFiumTextPage> pPdfTextPage = pPdfPage->getTextPage();
+ CPPUNIT_ASSERT(pPdfTextPage);
+
+ int nChars = pPdfTextPage->countChars();
+ CPPUNIT_ASSERT_EQUAL(22, nChars);
+
+ // Check that the label strings were exported correctly
+ std::vector<sal_uInt32> aChars(nChars);
+ for (int i = 0; i < nChars; i++)
+ aChars[i] = pPdfTextPage->getUnicode(i);
+ OUString aText(aChars.data(), aChars.size());
+ CPPUNIT_ASSERT_EQUAL(u"\u0623\r\n.\r\n\u0623.\u0623\r\n.\r\n\u0623.\u0623.\u0623\r\n."_ustr, aText);
+ }
+
+ // Parse the document again to get its raw content
+ // TODO: get the content from PDFiumPage somehow
+ 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* pContents = aPages[0]->LookupObject("Contents"_ostr);
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ auto pStart = static_cast<const char*>(aUncompressed.GetData());
+ const char* const pEnd = pStart + aUncompressed.GetSize();
+
+ enum
+ {
+ Default,
+ Lbl,
+ LblFoundText
+ } state
+ = Default;
+
+ auto nLine(0);
+ auto nLbl(0);
+ auto nLblTj(0);
+ auto nLblTJ(0);
+ std::vector<int> mcids;
+ 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 (o3tl::starts_with(line, "/Lbl<</MCID") && o3tl::ends_with(line, ">>BDC"))
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state);
+ mcids.push_back(o3tl::toInt32(line.substr(12)));
+ state = Lbl;
+ ++nLbl;
+ }
+ else if (state == Lbl)
+ {
+ auto const endj(line.find(">Tj"));
+ if (endj != ::std::string_view::npos)
+ {
+ state = LblFoundText;
+ ++nLblTj;
+ }
+ else
+ {
+ auto const endJ(line.find("]TJ"));
+ if (endJ != ::std::string_view::npos)
+ {
+ state = LblFoundText;
+ ++nLblTJ;
+ }
+ }
+ }
+ else if (state != Default && line == "EMC")
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("missing text", LblFoundText, state);
+ state = Default;
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state);
+ // ideally there should be 3 but apparently every text portion gets its own
+ // tag - this should not be a problem if these are grouped in the structure
+ // tree into 3 Lbl.
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nLbl)>(6), nLbl);
+ // these are quite arbitrary?
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nLbl)>(6), nLblTJ + nLblTj);
+
+ auto nL(0);
+ for (const auto& rDocElement : aDocument.GetElements())
+ {
+ auto pObject0 = dynamic_cast<vcl::filter::PDFObjectElement*>(rDocElement.get());
+ if (!pObject0)
+ continue;
+ auto pType0 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject0->Lookup("Type"_ostr));
+ if (!pType0 || pType0->GetValue() != "StructElem")
+ {
+ continue;
+ }
+ auto pS0 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject0->Lookup("S"_ostr));
+ if (!pS0 || pS0->GetValue() != "Document")
+ {
+ continue;
+ }
+ auto pKids0 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject0->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids0);
+
+ for (const auto& pKid0 : pKids0->GetElements())
+ {
+ auto pRefKid0 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKid0);
+ CPPUNIT_ASSERT(pRefKid0);
+ auto pObject1 = pRefKid0->LookupObject();
+ CPPUNIT_ASSERT(pObject1);
+ auto pType1 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType1);
+
+ if (pType1 && pType1->GetValue() == "StructElem")
+ {
+ auto pS1 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1->Lookup("S"_ostr));
+ if (pS1 && pS1->GetValue() == "L")
+ {
+ ++nL;
+ auto pKids1 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject1->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids1);
+ // this is purely structural so there should be 1 child
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pKids1->GetElements().size());
+
+ auto pRefKid11 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids1->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid11);
+ auto pObject11 = pRefKid11->LookupObject();
+ CPPUNIT_ASSERT(pObject11);
+ auto pType11 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject11->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType11);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType11->GetValue());
+ auto pS11 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject11->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS11);
+ CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS11->GetValue());
+ // LI has 2 children: Lbl and LBody
+ auto pKids11 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject11->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids11);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids11->GetElements().size());
+
+ auto pRefKid111 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids11->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid111);
+ auto pObject111 = pRefKid111->LookupObject();
+ CPPUNIT_ASSERT(pObject111);
+ auto pType111 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject111->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType111);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType111->GetValue());
+ auto pS111 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject111->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS111);
+ CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS111->GetValue());
+ // Lbl has 2 children: the first 2 mcids (in order)
+ auto pKids111 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject111->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids111);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids111->GetElements().size());
+
+ auto pRefKid1111 = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids111->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid1111);
+ CPPUNIT_ASSERT_EQUAL(mcids[0], int(pRefKid1111->GetValue()));
+ auto pRefKid1112 = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids111->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid1112);
+ CPPUNIT_ASSERT_EQUAL(mcids[1], int(pRefKid1112->GetValue()));
+
+ auto pRefKid112 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids11->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid112);
+ auto pObject112 = pRefKid112->LookupObject();
+ CPPUNIT_ASSERT(pObject112);
+ auto pType112 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType112);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType112->GetValue());
+ auto pS112 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS112);
+ CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS112->GetValue());
+ // LBody has 2 children: paragraph and nested L (in order)
+ auto pKids112 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject112->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids112);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids112->GetElements().size());
+
+ auto pRefKid1121 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids112->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid1121);
+ auto pObject1121 = pRefKid1121->LookupObject();
+ CPPUNIT_ASSERT(pObject1121);
+ auto pType1121 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1121->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType1121);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1121->GetValue());
+ auto pS1121 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1121->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS1121);
+ CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS1121->GetValue());
+
+ auto pRefKid1122 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids112->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid1122);
+ auto pObject1122 = pRefKid1122->LookupObject();
+ CPPUNIT_ASSERT(pObject1122);
+ auto pType1122 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType1122);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1122->GetValue());
+ auto pS1122 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS1122);
+ CPPUNIT_ASSERT_EQUAL("L"_ostr, pS1122->GetValue());
+ auto pKids1122 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject1122->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids1122);
+ // this is purely structural so there should be 1 child
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pKids1122->GetElements().size());
+
+ auto pRefKid11221 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids1122->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid11221);
+ auto pObject11221 = pRefKid11221->LookupObject();
+ CPPUNIT_ASSERT(pObject11221);
+ auto pType11221 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject11221->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType11221);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType11221->GetValue());
+ auto pS11221 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject11221->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS11221);
+ CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS11221->GetValue());
+ // LI has 2 children: Lbl and LBody
+ auto pKids11221 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject11221->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids11221);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids11221->GetElements().size());
+
+ auto pRefKid112211 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids11221->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid112211);
+ auto pObject112211 = pRefKid112211->LookupObject();
+ CPPUNIT_ASSERT(pObject112211);
+ auto pType112211 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112211->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType112211);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType112211->GetValue());
+ auto pS112211 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112211->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS112211);
+ CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS112211->GetValue());
+ // Lbl has 2 children: the first 2 mcids (in order)
+ auto pKids112211 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject112211->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids112211);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids112211->GetElements().size());
+
+ auto pRefKid1122111 = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids112211->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid1122111);
+ CPPUNIT_ASSERT_EQUAL(mcids[2], int(pRefKid1122111->GetValue()));
+ auto pRefKid1122112 = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids112211->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid1122112);
+ CPPUNIT_ASSERT_EQUAL(mcids[3], int(pRefKid1122112->GetValue()));
+
+ auto pRefKid112212 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids11221->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid112212);
+ auto pObject112212 = pRefKid112212->LookupObject();
+ CPPUNIT_ASSERT(pObject112212);
+ auto pType112212 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112212->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType112212);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType112212->GetValue());
+ auto pS112212 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112212->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS112212);
+ CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS112212->GetValue());
+ // LBody has 2 children: paragraph and nested L (in order)
+ auto pKids112212 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject112212->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids112212);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids112212->GetElements().size());
+
+ auto pRefKid1122121 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids112212->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid1122121);
+ auto pObject1122121 = pRefKid1122121->LookupObject();
+ CPPUNIT_ASSERT(pObject1122121);
+ auto pType1122121 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122121->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType1122121);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1122121->GetValue());
+ auto pS1122121 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122121->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS1122121);
+ CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS1122121->GetValue());
+
+ auto pRefKid1122122 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids112212->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid1122122);
+ auto pObject1122122 = pRefKid1122122->LookupObject();
+ CPPUNIT_ASSERT(pObject1122122);
+ auto pType1122122 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122122->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType1122122);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1122122->GetValue());
+ auto pS1122122 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122122->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS1122122);
+ CPPUNIT_ASSERT_EQUAL("L"_ostr, pS1122122->GetValue());
+ auto pKids1122122 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject1122122->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids1122122);
+ // this is purely structural so there should be 1 child
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pKids1122122->GetElements().size());
+
+ auto pRefKid11221221 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids1122122->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid11221221);
+ auto pObject11221221 = pRefKid11221221->LookupObject();
+ CPPUNIT_ASSERT(pObject11221221);
+ auto pType11221221 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject11221221->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType11221221);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType11221221->GetValue());
+ auto pS11221221 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject11221221->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS11221221);
+ CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS11221221->GetValue());
+ // LI has 2 children: Lbl and LBody
+ auto pKids11221221 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject11221221->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids11221221);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids11221221->GetElements().size());
+
+ auto pRefKid112212211 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids11221221->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid112212211);
+ auto pObject112212211 = pRefKid112212211->LookupObject();
+ CPPUNIT_ASSERT(pObject112212211);
+ auto pType112212211 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112212211->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType112212211);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType112212211->GetValue());
+ auto pS112212211 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112212211->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS112212211);
+ CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS112212211->GetValue());
+ // Lbl has 2 children: the first 2 mcids (in order)
+ auto pKids112212211 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject112212211->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids112212211);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), pKids112212211->GetElements().size());
+
+ auto pRefKid1122122111 = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids112212211->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid1122122111);
+ CPPUNIT_ASSERT_EQUAL(mcids[4], int(pRefKid1122122111->GetValue()));
+ auto pRefKid1122122112 = dynamic_cast<vcl::filter::PDFNumberElement*>(pKids112212211->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid1122122112);
+ CPPUNIT_ASSERT_EQUAL(mcids[5], int(pRefKid1122122112->GetValue()));
+
+ auto pRefKid112212212 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids11221221->GetElements()[1]);
+ CPPUNIT_ASSERT(pRefKid112212212);
+ auto pObject112212212 = pRefKid112212212->LookupObject();
+ CPPUNIT_ASSERT(pObject112212212);
+ auto pType112212212 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112212212->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType112212212);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType112212212->GetValue());
+ auto pS112212212 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject112212212->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS112212212);
+ CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS112212212->GetValue());
+ // inner LBody has 1 children: paragraph
+ auto pKids112212212 = dynamic_cast<vcl::filter::PDFArrayElement*>(pObject112212212->Lookup("K"_ostr));
+ CPPUNIT_ASSERT(pKids112212212);
+ CPPUNIT_ASSERT_EQUAL(size_t(1), pKids112212212->GetElements().size());
+
+ auto pRefKid1122122121 = dynamic_cast<vcl::filter::PDFReferenceElement*>(pKids112212212->GetElements()[0]);
+ CPPUNIT_ASSERT(pRefKid1122122121);
+ auto pObject1122122121 = pRefKid1122122121->LookupObject();
+ CPPUNIT_ASSERT(pObject1122122121);
+ auto pType1122122121 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122122121->Lookup("Type"_ostr));
+ CPPUNIT_ASSERT(pType1122122121);
+ CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1122122121->GetValue());
+ auto pS1122122121 = dynamic_cast<vcl::filter::PDFNameElement*>(pObject1122122121->Lookup("S"_ostr));
+ CPPUNIT_ASSERT(pS1122122121);
+ CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS1122122121->GetValue());
+ }
+ }
+ }
+ }
+ CPPUNIT_ASSERT_EQUAL(static_cast<decltype(nL)>(1), nL);
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf143311)
+{
+ createSwDoc("tdf143311-1.docx");
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+ {
+ // add another one that's a SdrObject
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xShape(
+ xFactory->createInstance("com.sun.star.drawing.RectangleShape"), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
+ xShapeProps->setPropertyValue("Decorative", uno::Any(true));
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPage> xDrawPage(xDrawPageSupplier->getDrawPage());
+ xDrawPage->add(xShape);
+ }
+ // check DOCX filters
+ saveAndReload("Office Open XML Text");
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(2), "Decorative"));
+ {
+ // tdf#153925 not imported - check default and set it to test ODF filters
+ uno::Reference<beans::XPropertySet> const xStyle(getStyles("FrameStyles")->getByName("Formula"), uno::UNO_QUERY_THROW);
+ CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xStyle, "Decorative"));
+ xStyle->setPropertyValue("Decorative", uno::Any(true));
+ }
+ // check ODF filters
+ saveAndReload("writer8");
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(1), "Decorative"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getShape(2), "Decorative"));
+ CPPUNIT_ASSERT_EQUAL(true, getProperty<bool>(getStyles("FrameStyles")->getByName("Formula"), "Decorative"));
+
+ // check PDF export
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export");
+ // Enable PDF/UA
+ uno::Sequence<beans::PropertyValue> aFilterData(
+ comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } }));
+ aMediaDescriptor["FilterData"] <<= aFilterData;
+ css::uno::Reference<frame::XStorable> xStorable(mxComponent, css::uno::UNO_QUERY_THROW);
+ xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList());
+
+ 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* pContents = aPages[0]->LookupObject("Contents"_ostr);
+ CPPUNIT_ASSERT(pContents);
+ vcl::filter::PDFStreamElement* pStream = pContents->GetStream();
+ CPPUNIT_ASSERT(pStream);
+ SvMemoryStream& rObjectStream = pStream->GetMemory();
+ // Uncompress it.
+ SvMemoryStream aUncompressed;
+ ZCodec aZCodec;
+ aZCodec.BeginCompression();
+ rObjectStream.Seek(0);
+ aZCodec.Decompress(rObjectStream, aUncompressed);
+ CPPUNIT_ASSERT(aZCodec.EndCompression());
+
+ 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") && o3tl::ends_with(line, ">>BDC"))
+ {
+ 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_EQUAL(static_cast<decltype(nTagged)>(25), nTagged); // text in body
+ // 1 decorative image + 1 decorative shape + 1 pre-existing rectangle border or something
+ CPPUNIT_ASSERT(nArtifacts >= 3);
+}
+
+void Test::testTextFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ createSwDoc("text_form_field.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check the document after round trip
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ // We have two text form fields
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+ // Check whether all fieldmarks are text form fields
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), ODF_FORMTEXT, pFieldmark->GetFieldname());
+ }
+
+ // In the first paragraph we have an empty text form field with the placeholder spaces
+ const uno::Reference< text::XTextRange > xPara = getParagraph(1);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("TextFieldStart"), getProperty<OUString>(getRun(xPara, 1), "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("TextFieldSeparator"), getProperty<OUString>(getRun(xPara, 2), "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("Text"), getProperty<OUString>(getRun(xPara, 3), "TextPortionType"));
+ sal_Unicode vEnSpaces[5] = {8194, 8194, 8194, 8194, 8194};
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), getRun(xPara, 3)->getString());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("TextFieldEnd"), getProperty<OUString>(getRun(xPara, 4), "TextPortionType"));
+
+ // In the second paragraph we have a set text
+ const uno::Reference< text::XTextRange > xPara2 = getParagraph(2);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("TextFieldStart"), getProperty<OUString>(getRun(xPara2, 1), "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("TextFieldSeparator"), getProperty<OUString>(getRun(xPara2, 2), "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("Text"), getProperty<OUString>(getRun(xPara2, 3), "TextPortionType"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("xxxxx"), getRun(xPara2, 3)->getString());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("TextFieldEnd"), getProperty<OUString>(getRun(xPara2, 4), "TextPortionType"));
+ }
+}
+
+void Test::testCheckBoxFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ createSwDoc("checkbox_form_field.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check the document after round trip
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ // We have two check box form fields
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+ int nIndex = 0;
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
+
+ if(rFilterName == "Office Open XML Text") // OOXML import also generates bookmarks
+ {
+ if(!pFieldmark)
+ continue;
+ }
+
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), ODF_FORMCHECKBOX, pFieldmark->GetFieldname());
+ ::sw::mark::ICheckboxFieldmark* pCheckBox = dynamic_cast< ::sw::mark::ICheckboxFieldmark* >(pFieldmark);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pCheckBox);
+
+ // The first one is unchecked, the other one is checked
+ if(nIndex == 0)
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !pCheckBox->IsChecked());
+ else
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pCheckBox->IsChecked());
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(2), nIndex);
+ }
+}
+
+void Test::testDropDownFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "MS Word 97",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ createSwDoc("dropdown_form_field.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check the document after round trip
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(2), pMarkAccess->getAllMarksCount());
+
+ int nIndex = 0;
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IFieldmark* pFieldmark = dynamic_cast<::sw::mark::IFieldmark*>(*aIter);
+
+ if(!pFieldmark)
+ continue;
+
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), ODF_FORMDROPDOWN, pFieldmark->GetFieldname());
+
+ // Check drop down field's parameters.
+ const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+ css::uno::Sequence<OUString> vListEntries;
+ sal_Int32 nSelection = -1;
+ auto pListEntries = pParameters->find(ODF_FORMDROPDOWN_LISTENTRY);
+ if (pListEntries != pParameters->end())
+ {
+ pListEntries->second >>= vListEntries;
+
+ if(vListEntries.hasElements())
+ {
+ auto pResult = pParameters->find(ODF_FORMDROPDOWN_RESULT);
+ if (pResult != pParameters->end())
+ {
+ pResult->second >>= nSelection;
+ }
+ }
+ }
+
+ // The first one is empty
+ if(nIndex == 0)
+ {
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), !vListEntries.hasElements());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(-1), nSelection);
+ }
+ else // The second one has list and also a selected item
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(4), vListEntries.getLength());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), nSelection);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("1000"), vListEntries[0]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2000"), vListEntries[1]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("3000"), vListEntries[2]);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("4000"), vListEntries[3]);
+ }
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(2), nIndex);
+ }
+}
+
+void Test::testDateFormField()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ createSwDoc("date_form_field.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check the document after round trip
+ if (rFilterName == "writer8")
+ {
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pMarkAccess->getAllMarksCount());
+
+ int nIndex = 0;
+ for(auto aIter = pMarkAccess->getAllMarksBegin(); aIter != pMarkAccess->getAllMarksEnd(); ++aIter)
+ {
+ ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*aIter);
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), ODF_FORMDATE, pFieldmark->GetFieldname());
+
+ // Check date form field's parameters.
+ const sw::mark::IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+ OUString sDateFormat;
+ auto pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT);
+ if (pResult != pParameters->end())
+ {
+ pResult->second >>= sDateFormat;
+ }
+
+ OUString sLang;
+ pResult = pParameters->find(ODF_FORMDATE_DATEFORMAT_LANGUAGE);
+ if (pResult != pParameters->end())
+ {
+ pResult->second >>= sLang;
+ }
+
+ OUString sCurrentDate = pFieldmark->GetContent();
+
+ // The first one has the default field content
+ if(nIndex == 0)
+ {
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+ sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), sCurrentDate);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), SwNodeOffset(9), pFieldmark->GetMarkStart().GetNodeIndex());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(5), pFieldmark->GetMarkStart().GetContentIndex());
+ }
+ else if (nIndex == 1) // The second has the default format
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("06/12/19"), sCurrentDate);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), SwNodeOffset(9), pFieldmark->GetMarkStart().GetNodeIndex());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(20), pFieldmark->GetMarkStart().GetContentIndex());
+ }
+ else if (nIndex == 2) // The third one has special format
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("[NatNum12 MMMM=abbreviation]YYYY\". \"MMMM D."), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("hu-HU"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2019. febr. 12."), sCurrentDate);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), SwNodeOffset(9), pFieldmark->GetMarkStart().GetNodeIndex());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(40), pFieldmark->GetMarkStart().GetContentIndex());
+
+ }
+ else if (nIndex == 3) // The fourth one has placeholder text
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("D, MMM YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("bm-ML"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("[select date]"), sCurrentDate);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), SwNodeOffset(9), pFieldmark->GetMarkStart().GetNodeIndex());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(62), pFieldmark->GetMarkStart().GetContentIndex());
+
+ }
+ else // The last one is really empty
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(""), sCurrentDate);
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), SwNodeOffset(9), pFieldmark->GetMarkStart().GetNodeIndex());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(82), pFieldmark->GetMarkStart().GetContentIndex());
+
+ }
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), nIndex);
+ }
+ else
+ {
+ // Import from DOCX, so the fieldmark is now a content control.
+ uno::Reference<container::XEnumerationAccess> xEnumAccess(getParagraph(1), uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xTextPortions = xEnumAccess->createEnumeration();
+
+ int nIndex = 0;
+ while (xTextPortions->hasMoreElements())
+ {
+ uno::Reference<beans::XPropertySet> xTextPortion(xTextPortions->nextElement(), uno::UNO_QUERY);
+ OUString aPortionType;
+ xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+ if (aPortionType != "ContentControl")
+ {
+ continue;
+ }
+
+ uno::Reference<text::XTextContent> xContentControl;
+ xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+ uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
+
+ bool bDate{};
+ xContentControlProps->getPropertyValue("Date") >>= bDate;
+ CPPUNIT_ASSERT(bDate);
+
+ // Check date form field's parameters.
+ OUString sDateFormat;
+ xContentControlProps->getPropertyValue("DateFormat") >>= sDateFormat;
+
+ OUString sLang;
+ xContentControlProps->getPropertyValue("DateLanguage") >>= sLang;
+
+ uno::Reference<container::XEnumerationAccess> xContentControlEnumAccess(xContentControl,
+ uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xContentControlEnum
+ = xContentControlEnumAccess->createEnumeration();
+ uno::Reference<text::XTextRange> xContentControlTextPortion(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+ OUString sCurrentDate = xContentControlTextPortion->getString();
+
+ // The first one has the default field content
+ if(nIndex == 0)
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+ sal_Unicode vEnSpaces[ODF_FORMFIELD_DEFAULT_LENGTH] = {8194, 8194, 8194, 8194, 8194};
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(vEnSpaces, 5), sCurrentDate);
+ }
+ else if (nIndex == 1) // The second has the default format
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("06/12/19"), sCurrentDate);
+ }
+ else if (nIndex == 2) // The third one has special format
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("[NatNum12 MMMM=abbreviation]YYYY\". \"MMMM D."), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("hu-HU"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("2019. febr. 12."), sCurrentDate);
+ }
+ else if (nIndex == 3) // The fourth one has placeholder text
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("D, MMM YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("bm-ML"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("[select date]"), sCurrentDate);
+ }
+ else // The last one is really empty
+ {
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("MM/DD/YY"), sDateFormat);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString("en-US"), sLang);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), OUString(""), sCurrentDate);
+ }
+ ++nIndex;
+ }
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), int(5), nIndex);
+ }
+ }
+}
+
+void Test::testDateFormFieldCharacterFormatting()
+{
+ const OUString aFilterNames[] = {
+ "writer8",
+ "Office Open XML Text",
+ };
+
+ for (const OUString& rFilterName : aFilterNames)
+ {
+ createSwDoc("date_form_field_char_formatting.odt");
+
+ const OString sFailedMessage = OString::Concat("Failed on filter: ") + rFilterName.toUtf8();
+
+ // Export the document and import again for a check
+ saveAndReload(rFilterName);
+
+ // Check the document after round trip
+ if (rFilterName == "writer8")
+ {
+ SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pTextDoc);
+ SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+ IDocumentMarkAccess* pMarkAccess = pDoc->getIDocumentMarkAccess();
+
+ // Check that we have the field at the right place
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(1), pMarkAccess->getAllMarksCount());
+ ::sw::mark::IDateFieldmark* pFieldmark = dynamic_cast<::sw::mark::IDateFieldmark*>(*pMarkAccess->getAllMarksBegin());
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pFieldmark);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), ODF_FORMDATE, pFieldmark->GetFieldname());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(0), pFieldmark->GetMarkStart().GetContentIndex());
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), sal_Int32(11), pFieldmark->GetMarkEnd().GetContentIndex());
+
+ // We have one date field, first half of the field has bold character weight and second part has red character color
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::BOLD, getProperty<float>(getRun(getParagraph(1), 3), "CharWeight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_AUTO, getProperty<Color>(getRun(getParagraph(1), 3), "CharColor"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::NORMAL, getProperty<float>(getRun(getParagraph(1), 4), "CharWeight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), Color(0xff0000), getProperty<Color>(getRun(getParagraph(1), 4), "CharColor"));
+ }
+ else
+ {
+ uno::Reference<beans::XPropertySet> xTextPortion(getRun(getParagraph(1), 1), uno::UNO_QUERY);
+ OUString aPortionType;
+ xTextPortion->getPropertyValue("TextPortionType") >>= aPortionType;
+ CPPUNIT_ASSERT_EQUAL(OUString("ContentControl"), aPortionType);
+
+ uno::Reference<text::XTextContent> xContentControl;
+ xTextPortion->getPropertyValue("ContentControl") >>= xContentControl;
+ uno::Reference<beans::XPropertySet> xContentControlProps(xContentControl, uno::UNO_QUERY);
+ bool bDate{};
+ xContentControlProps->getPropertyValue("Date") >>= bDate;
+ CPPUNIT_ASSERT(bDate);
+
+ uno::Reference<container::XEnumerationAccess> xContentControlEnumAccess(xContentControl,
+ uno::UNO_QUERY);
+ uno::Reference<container::XEnumeration> xContentControlEnum
+ = xContentControlEnumAccess->createEnumeration();
+ xTextPortion.set(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::BOLD, getProperty<float>(xTextPortion, "CharWeight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), COL_AUTO, getProperty<Color>(xTextPortion, "CharColor"));
+ xTextPortion.set(xContentControlEnum->nextElement(), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), awt::FontWeight::NORMAL, getProperty<float>(xTextPortion, "CharWeight"));
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), Color(0xff0000), getProperty<Color>(xTextPortion, "CharColor"));
+ }
+ }
+}
+
+void Test::testSvgImageSupport()
+{
+ OUString aFilterNames[] = {
+ "writer8",
+ "Office Open XML Text",
+ };
+
+ for (OUString const & rFilterName : aFilterNames)
+ {
+ // Use case to import a document containing a SVG image, export in target format, import and check if the
+ // SVG image is present and as expected in the document
+
+ // Import ODT file
+ createSwDoc("SvgImageTest.odt");
+
+ // Export the document in target format and import again
+ saveAndReload(rFilterName);
+
+ // Prepare fail message (writing which import/export filter was used)
+ const OString sFailedMessage = "Failed on filter: "_ostr + rFilterName.toUtf8();
+
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), 1, getShapes());
+
+ // Get the image
+ uno::Reference<drawing::XShape> xImage(getShape(1), uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropertySet(xImage, uno::UNO_QUERY_THROW);
+
+ // Convert to a XGraphic
+ uno::Reference<graphic::XGraphic> xGraphic;
+ xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), xGraphic.is());
+
+ // Access the Graphic
+ Graphic aGraphic(xGraphic);
+
+ // Check if it contian a VectorGraphicData struct
+ auto pVectorGraphic = aGraphic.getVectorGraphicData();
+ CPPUNIT_ASSERT_MESSAGE(sFailedMessage.getStr(), pVectorGraphic);
+
+ // Which should be of type SVG, which means we have a SVG file
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sFailedMessage.getStr(), VectorGraphicDataType::Svg, pVectorGraphic->getType());
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(Test);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */