From 267c6f2ac71f92999e969232431ba04678e7437e Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 15 Apr 2024 07:54:39 +0200 Subject: Adding upstream version 4:24.2.0. Signed-off-by: Daniel Baumann --- vcl/qa/cppunit/pdfexport/data/6m-wide.odg | Bin 0 -> 9146 bytes vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt | Bin 0 -> 12595 bytes .../pdfexport/data/ComplexContentDictionary.pdf | Bin 0 -> 29050 bytes .../data/Description PDF Export test .odt | Bin 0 -> 22599 bytes .../pdfexport/data/LO_Lbl_Lbody_bug_report.fodt | 125 + vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt | 137 + vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf | Bin 0 -> 4836 bytes .../data/PDF_export_with_formcontrol.fodt | 174 + .../cppunit/pdfexport/data/SimpleMultiPagePDF.pdf | Bin 0 -> 17693 bytes vcl/qa/cppunit/pdfexport/data/SimpleTOC.fodt | 323 ++ ...fficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt | 560 +++ vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt | Bin 0 -> 25317 bytes vcl/qa/cppunit/pdfexport/data/alternativeText.fodp | 489 ++ vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt | Bin 0 -> 13423 bytes .../pdfexport/data/content-control-rtl.docx | Bin 0 -> 5178 bytes .../pdfexport/data/flowframe_null_ptr_deref.sample | 654 +++ vcl/qa/cppunit/pdfexport/data/forcepoint71.key | Bin 0 -> 114022 bytes vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf | 1 + vcl/qa/cppunit/pdfexport/data/form-font-name.odt | Bin 0 -> 8548 bytes vcl/qa/cppunit/pdfexport/data/formcontrol.fodt | 192 + vcl/qa/cppunit/pdfexport/data/grouped-shape.fodt | 213 + .../pdfexport/data/image-hyperlink-alttext.fodt | 195 + vcl/qa/cppunit/pdfexport/data/image-shape.fodt | 141 + .../pdfexport/data/justified-arabic-kashida.odt | Bin 0 -> 12875 bytes .../pdfexport/data/link-wrong-page-partial.odg | Bin 0 -> 11175 bytes vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp | Bin 0 -> 12293 bytes vcl/qa/cppunit/pdfexport/data/master.odm | Bin 0 -> 22304 bytes vcl/qa/cppunit/pdfexport/data/nestedsection.fodt | 132 + vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg | Bin 0 -> 29714 bytes .../cppunit/pdfexport/data/pdf-image-hyperlink.odg | Bin 0 -> 28633 bytes .../data/pdf-image-resource-inline-xobject-ref.pdf | Bin 0 -> 1372 bytes .../pdfexport/data/pdf-image-rotate-180.pdf | Bin 0 -> 1319 bytes vcl/qa/cppunit/pdfexport/data/rectangles.pdf | 54 + vcl/qa/cppunit/pdfexport/data/reduce-image.fodt | 29 + .../cppunit/pdfexport/data/reduce-small-image.fodt | 21 + vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf | Bin 0 -> 2959 bytes vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt | Bin 0 -> 9071 bytes vcl/qa/cppunit/pdfexport/data/spanlist.fodt | 207 + vcl/qa/cppunit/pdfexport/data/tdf103492.odt | Bin 0 -> 11218 bytes vcl/qa/cppunit/pdfexport/data/tdf105093.odp | Bin 0 -> 211126 bytes vcl/qa/cppunit/pdfexport/data/tdf105461.odp | Bin 0 -> 10320 bytes vcl/qa/cppunit/pdfexport/data/tdf105954.odt | Bin 0 -> 74147 bytes vcl/qa/cppunit/pdfexport/data/tdf105972.fodt | 175 + vcl/qa/cppunit/pdfexport/data/tdf106059.odt | Bin 0 -> 13585 bytes vcl/qa/cppunit/pdfexport/data/tdf106206.odt | Bin 0 -> 74641 bytes vcl/qa/cppunit/pdfexport/data/tdf106693.odt | Bin 0 -> 13585 bytes vcl/qa/cppunit/pdfexport/data/tdf106702.odt | Bin 0 -> 42158 bytes vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt | Bin 0 -> 21561 bytes vcl/qa/cppunit/pdfexport/data/tdf106972.odt | Bin 0 -> 21376 bytes vcl/qa/cppunit/pdfexport/data/tdf107013.odt | Bin 0 -> 19823 bytes vcl/qa/cppunit/pdfexport/data/tdf107018.odt | Bin 0 -> 15787 bytes vcl/qa/cppunit/pdfexport/data/tdf107089.odt | Bin 0 -> 20171 bytes vcl/qa/cppunit/pdfexport/data/tdf107868.odt | Bin 0 -> 10567 bytes vcl/qa/cppunit/pdfexport/data/tdf108963.odp | Bin 0 -> 10369 bytes vcl/qa/cppunit/pdfexport/data/tdf109143.odt | Bin 0 -> 68155 bytes vcl/qa/cppunit/pdfexport/data/tdf113143.odp | Bin 0 -> 100637 bytes vcl/qa/cppunit/pdfexport/data/tdf114256.ods | Bin 0 -> 7716 bytes vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt | Bin 0 -> 8566 bytes vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt | Bin 0 -> 8629 bytes vcl/qa/cppunit/pdfexport/data/tdf115262.ods | Bin 0 -> 27638 bytes vcl/qa/cppunit/pdfexport/data/tdf115967.odt | Bin 0 -> 14621 bytes .../pdfexport/data/tdf118244_radioButtonGroup.odt | Bin 0 -> 12847 bytes vcl/qa/cppunit/pdfexport/data/tdf121615.odt | Bin 0 -> 10188 bytes vcl/qa/cppunit/pdfexport/data/tdf121962.odt | Bin 0 -> 14974 bytes vcl/qa/cppunit/pdfexport/data/tdf124272.odt | Bin 0 -> 10292 bytes vcl/qa/cppunit/pdfexport/data/tdf127217.odt | Bin 0 -> 9243 bytes vcl/qa/cppunit/pdfexport/data/tdf128445.odp | Bin 0 -> 41261 bytes vcl/qa/cppunit/pdfexport/data/tdf128630.odp | Bin 0 -> 17558 bytes vcl/qa/cppunit/pdfexport/data/tdf129085.docx | Bin 0 -> 44600 bytes vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp | 239 + vcl/qa/cppunit/pdfexport/data/tdf135346.ods | Bin 0 -> 10422 bytes vcl/qa/cppunit/pdfexport/data/tdf139065.odt | Bin 0 -> 13172 bytes vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt | Bin 0 -> 33041 bytes vcl/qa/cppunit/pdfexport/data/tdf141171.odt | Bin 0 -> 9512 bytes vcl/qa/cppunit/pdfexport/data/tdf144222.ods | Bin 0 -> 9410 bytes vcl/qa/cppunit/pdfexport/data/tdf145274.docx | Bin 0 -> 3788 bytes vcl/qa/cppunit/pdfexport/data/tdf145873.pptx | Bin 0 -> 48006 bytes vcl/qa/cppunit/pdfexport/data/tdf147027.ods | Bin 0 -> 16310 bytes vcl/qa/cppunit/pdfexport/data/tdf147164.odp | Bin 0 -> 17732 bytes vcl/qa/cppunit/pdfexport/data/tdf148442.odt | Bin 0 -> 10562 bytes vcl/qa/cppunit/pdfexport/data/tdf148706.odt | Bin 0 -> 9969 bytes vcl/qa/cppunit/pdfexport/data/tdf150846.txt | 1 + vcl/qa/cppunit/pdfexport/data/tdf150931.ods | Bin 0 -> 8605 bytes vcl/qa/cppunit/pdfexport/data/tdf152231.fodt | 208 + vcl/qa/cppunit/pdfexport/data/tdf154549.odt | Bin 0 -> 84740 bytes vcl/qa/cppunit/pdfexport/data/tdf154982.odt | Bin 0 -> 18250 bytes vcl/qa/cppunit/pdfexport/data/tdf155161.odt | Bin 0 -> 123319 bytes vcl/qa/cppunit/pdfexport/data/tdf155190.odt | Bin 0 -> 9628 bytes vcl/qa/cppunit/pdfexport/data/tdf156685.docx | Bin 0 -> 23687 bytes vcl/qa/cppunit/pdfexport/data/tdf157679.pptx | Bin 0 -> 15255 bytes vcl/qa/cppunit/pdfexport/data/tdf157816.fodt | 175 + vcl/qa/cppunit/pdfexport/data/tdf48707-1.fodt | 290 ++ vcl/qa/cppunit/pdfexport/data/tdf48707-2.fodt | 335 ++ vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt | Bin 0 -> 9286 bytes vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt | Bin 0 -> 8265 bytes vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt | Bin 0 -> 8251 bytes vcl/qa/cppunit/pdfexport/data/tdf84283.doc | Bin 0 -> 36352 bytes vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt | Bin 0 -> 215797 bytes vcl/qa/cppunit/pdfexport/data/tdf99680.odt | Bin 0 -> 30257 bytes vcl/qa/cppunit/pdfexport/data/toc-link.fodt | 45 + .../cppunit/pdfexport/data/transparentshape.fodp | 439 ++ vcl/qa/cppunit/pdfexport/data/vid.odt | Bin 0 -> 134265 bytes vcl/qa/cppunit/pdfexport/data/wide_page1.fodt | 40 + vcl/qa/cppunit/pdfexport/pdfexport.cxx | 2774 +++++++++++ vcl/qa/cppunit/pdfexport/pdfexport2.cxx | 4858 ++++++++++++++++++++ 105 files changed, 13226 insertions(+) create mode 100644 vcl/qa/cppunit/pdfexport/data/6m-wide.odg create mode 100644 vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt create mode 100644 vcl/qa/cppunit/pdfexport/data/LO_Lbl_Lbody_bug_report.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/SimpleTOC.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/alternativeText.fodp create mode 100644 vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/content-control-rtl.docx create mode 100644 vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample create mode 100644 vcl/qa/cppunit/pdfexport/data/forcepoint71.key create mode 100644 vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf create mode 100644 vcl/qa/cppunit/pdfexport/data/form-font-name.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/formcontrol.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/grouped-shape.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/image-hyperlink-alttext.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/image-shape.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/justified-arabic-kashida.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg create mode 100644 vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/master.odm create mode 100644 vcl/qa/cppunit/pdfexport/data/nestedsection.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg create mode 100644 vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg create mode 100644 vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/rectangles.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/reduce-image.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf create mode 100644 vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/spanlist.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf103492.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf105093.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf105461.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf105954.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf105972.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf106059.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf106206.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf106693.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf106702.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf106972.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf107013.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf107018.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf107089.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf107868.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf108963.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf109143.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf113143.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf114256.ods create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf115262.ods create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf115967.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf121615.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf121962.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf124272.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf127217.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf128445.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf128630.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf129085.docx create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf135346.ods create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf139065.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf141171.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf144222.ods create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf145274.docx create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf145873.pptx create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf147027.ods create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf147164.odp create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf148442.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf148706.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf150846.txt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf150931.ods create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf152231.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf154549.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf154982.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf155161.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf155190.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf156685.docx create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf157679.pptx create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf157816.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf48707-1.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf48707-2.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf84283.doc create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf99680.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/toc-link.fodt create mode 100644 vcl/qa/cppunit/pdfexport/data/transparentshape.fodp create mode 100644 vcl/qa/cppunit/pdfexport/data/vid.odt create mode 100644 vcl/qa/cppunit/pdfexport/data/wide_page1.fodt create mode 100644 vcl/qa/cppunit/pdfexport/pdfexport.cxx create mode 100644 vcl/qa/cppunit/pdfexport/pdfexport2.cxx (limited to 'vcl/qa/cppunit/pdfexport') diff --git a/vcl/qa/cppunit/pdfexport/data/6m-wide.odg b/vcl/qa/cppunit/pdfexport/data/6m-wide.odg new file mode 100644 index 0000000000..49fb9bfff9 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/6m-wide.odg differ diff --git a/vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt b/vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt new file mode 100644 index 0000000000..2e87c33c71 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/BrownFoxLazyDog.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf b/vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf new file mode 100644 index 0000000000..950eef1e1a Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/ComplexContentDictionary.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt b/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt new file mode 100644 index 0000000000..78f05b09e9 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/Description PDF Export test .odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/LO_Lbl_Lbody_bug_report.fodt b/vcl/qa/cppunit/pdfexport/data/LO_Lbl_Lbody_bug_report.fodt new file mode 100644 index 0000000000..ed4cf89584 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/LO_Lbl_Lbody_bug_report.fodt @@ -0,0 +1,125 @@ + + + Saku Seppälä2023-10-11T16:51:28.6180000002023-10-19T12:10:56.924262307PT7M5S5LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/0080580e754a3a080ae0b914945368307d5c29fe2023-10-11T17:00:34.425000000PDF files: Saku Seppälä + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This Is First Heading + Second level without label + + + diff --git a/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt b/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt new file mode 100644 index 0000000000..5c14cee1f2 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/LinkWithFly.fodt @@ -0,0 +1,137 @@ + + + 2023-10-25T14:48:54.649558008test2023-10-25T14:49:57.194410546PDF files2023-10-25T14:54:03.818423519PT4M6S2LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/70bf29987ceb90cd3988fc2dfc4cad2a0163fe17 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + https://www.mozilla.org/en-US + iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAANbY1E9YMgAAABl0 + RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFpSURBVHjaYvz//z8DtQBAADER + o+jjZGuibAQIICZiDOK/cgzFwEnrV/4HYXS1AAHERIxBR58yMiAb2DtzM1b1AAHERIxBIIBu + IDYAEEBMxBjE0bgdxcBL3vcZLl16jaEPIICYiDFIU9MSw8BeoeUYhgEEEBMxBnFx8WE1EN3L + AAHERIxBIECMgQABxAhKtPgM+vbtE9xmGP/69eMMP+o9wWLW0kD9OlYM/LlHGQECiAndoKg/ + USgGgTTmdS8C0yA+zIUgdeguBAggljtWdQwMVkDXACWMjd0ZXRun/Id5DWTA9C23GSaVxoEN + zISoARvoamnBYF2/hPHs2Z3/z0JdDhBADCBvIuPkhsn/QeDr14//QWwQjY0PVYeiFyCA8OaA + 3cdPoEQAiI8PAAQQEwMVAUAAsWATBAX0jx9fsWrAJQ4CAAGE1TBQwOMC9+9fwikHEEBYDQPF + IAzIe8TglEMHAAHESM2SFiDAADEwCe4BJwcYAAAAAElFTkSuQmCC + + + house + /firefox/119.0/releasenotes/ + https://www.mozilla.org/en-US/firefox/118.0/releasenotes/ + + + diff --git a/vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf b/vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf new file mode 100644 index 0000000000..315cdc36ef Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/PDFWithImages.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt b/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt new file mode 100644 index 0000000000..eda699e27f --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/PDF_export_with_formcontrol.fodt @@ -0,0 +1,174 @@ + + + A. Spielhoff2020-09-12T10:51:34.4381175712023-10-11T12:40:15.543658302PT7H23M50S98LibreOfficeDev/7.5.7.0.0$Linux_X86_64 LibreOffice_project/0325c0aa2d3e6df97ff554ca540d316273fd149a2023-09-23T14:07:35.317591779PDF-Dateien: A Spielhoff + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This text document contains some links and a text control. + When exporting the document to PDF in LO 7.5.3.2 or newer the links won't have the right target any more. First link to "Kläranlage" will open last link to "#pano=24", second link won't open anything and third link will open "Mechanische Vorreinigung" + https://klexikon.zum.de/wiki/Kläranlage + https://de.wikipedia.org/wiki/Kläranlage#Mechanische_Vorreinigung + https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24 + Here a form control for getting possibility to input content. + + When deleting the form control links will work as expected. + Up to LO 7.5.2.2 this bug won't appear. + + + diff --git a/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf new file mode 100644 index 0000000000..af665fcba8 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/SimpleMultiPagePDF.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/data/SimpleTOC.fodt b/vcl/qa/cppunit/pdfexport/data/SimpleTOC.fodt new file mode 100644 index 0000000000..6e7e88ffe9 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/SimpleTOC.fodt @@ -0,0 +1,323 @@ + + + Gabor LO-Dev2023-10-18T22:16:34.2010000002023-10-18T22:23:10.997000000Gabor LO-DevPT6M37S5LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/0080580e754a3a080ae0b914945368307d5c29fe2023-10-18T22:22:25.716000000PDF files: Gabor LO-DevMultipage-TOC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + One + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est orci. + Two + Integer sodales tincidunt tristique. Sed a metus posuere, adipiscing nunc et, viverra odio. Donec auctor molestie sem, sit amet tristique lectus hendrerit sed. Cras sodales nisl sed orci mattis iaculis. Nunc eget dolor accumsan, pharetra risus a, vestibulum mauris. Nunc vulputate lobortis mollis. Vivamus nec tellus faucibus, tempor magna nec, facilisis felis. Donec commodo enim a vehicula pellentesque. Nullam vehicula vestibulum est vel ultricies. + Three + Aliquam velit massa, laoreet vel leo nec, volutpat facilisis eros. Donec consequat arcu ut diam tempor luctus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent vitae lacus vel leo sodales pharetra a a nibh. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam luctus tempus nibh, fringilla dictum augue consectetur eget. Curabitur at ante sit amet tortor pharetra molestie eu nec ante. Mauris tincidunt, nibh eu sollicitudin molestie, dolor sapien congue tortor, a pulvinar sapien turpis sed ante. Donec nec est elementum, euismod nulla in, mollis nunc. + + + + + + + + + + + + + + + + + + + + + + Table of Contents + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Table of Contents + + One1 + Two1 + Three1 + + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt b/vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt new file mode 100644 index 0000000000..1b13a4fd50 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt @@ -0,0 +1,560 @@ + + + Christophe Strobbe2022-05-14T18:39:40.86800000018PT21M55STest File for Simple Tables With or Without a Properly Marked Header Row2022-05-17T16:43:48.919000000Christophe StrobbeLibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/54178896aba2ded7b57479dad435607b73dc89fa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test File for Simple Tables With or Without a Properly Marked Header Row + Table with Header Row (Repeat First Row) + + + + + + + + + Average starting score + + + Average improved score + + + + + + Images + + + 35% + + + 91% + + + + + + This table is fine and the LibreOffice Accessibility Checker does not flag it. + + + After exporting the file to PDF (PDF/UA), the first row is tagged as a TR with tree TH elements. This is as expected. + + + When the PDF file is checked with PAC2021, there is an error for each TH element because the scope attribute is set to “None” instead of “Column”. This is a bug in LibreOffice’s PDF export. + + + Table with Table Heading Style in First Row (Repeat First Row not set) + + + + + + + + Average starting score + + + Average improved score + + + + + Images + + + 35% + + + 91% + + + + + + For this table, the LibreOffice Accessibility Checker should warn the author that the first row should be marked as a repeatable row in the Table Properties. + + + After exporting the file to PDF (PDF/UA), the first row is tagged as a TR with tree TH elements. This is good, even though it is not what was expected. + + + When the PDF file is checked with PAC2021, there is an error for each TH element because the scope attribute is set to “None” instead of “Column”. This is a bug in LibreOffice’s PDF export. + + + Table with Heading 2 Style in First Row (Repeat First Row not set) + + + + + + + + Average starting score + + + Average improved score + + + + + Images + + + 35% + + + 91% + + + + + + Error flagged by the LibreOffice Accessibility Checker: “Tables must not contain headings.” This error is justified. + + + After exporting the file to PDF (PDF/UA), the first row is tagged as a TR with tree TD elements, each of which contains a H2 element. This is as expected: Heading x styles should not be used to mark table headings. + + + When the PDF file is checked with PAC2021, no errors are reported for this table. This is a shortcoming of PAC2021, which is outside the scope of LibreOffice. + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt b/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt new file mode 100644 index 0000000000..05e2bb1840 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/WG7100-Preface.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/alternativeText.fodp b/vcl/qa/cppunit/pdfexport/data/alternativeText.fodp new file mode 100644 index 0000000000..d77b631408 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/alternativeText.fodp @@ -0,0 +1,489 @@ + + + 2022-05-19T20:19:11.6101543782022-05-20T10:09:03.143295257PT4M52S5LibreOfficeDev/7.4.0.0.alpha1$Linux_X86_64 LibreOffice_project/5f2dac9510bb511eaf08418342218000945cf180 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQAAAAA3bvkkAAAAEElEQVR4nGJgAQAAAP//AwAA + BgAFV7+r1AAAAABJRU5ErkJggg== + + + + This is the text alternative + This is the description + + + + + + + + + + + + diff --git a/vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt b/vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt new file mode 100644 index 0000000000..da9b167fd9 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/bitmap-scaledown.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/content-control-rtl.docx b/vcl/qa/cppunit/pdfexport/data/content-control-rtl.docx new file mode 100644 index 0000000000..1b5fba4555 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/content-control-rtl.docx differ diff --git a/vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample b/vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample new file mode 100644 index 0000000000..4610ae5d18 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/flowframe_null_ptr_deref.sample @@ -0,0 +1,654 @@ + + + + + + + + + + KDE::Enterprise Homepage - Business Directory + + + + + + + + + + + + + + + + + KDE::Enterprise Homepage - Business Directory + + + + + + + + + + + + + + + + + KDE::Enterprise Homepage - Business Directory + + + + + + + + + + + + + + + + + KDE::Enterprise Homepage - Business Directory + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +
+
 
+ +
+ + +

Business Directory

+ +

A problem has been detected with your submission

+

In the Business Name box you did not enter a valid name.

+

Please correct the problem below and resubmit.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
--> Business Name + +
Contact Name + +
Email Address + + Publish e-mail address
Website + +
Address + +
+ +
+ +

+ If more than one address, please add your head office. +

Postcode / Zip Code + +
Country + +
Phone Number + +
Fax Number + +
Business Services + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
On Site Support
Phone Support
Distribution
Free software development
Commercial development
Consulting
Retail
Other + +
+
Comments + +
+ + +
+
+

+ Back to the Business Directory +

+ + +
+ +

Inform

+ +

KDE::Enterprise

+ + + + + + + +
+ +
+ + diff --git a/vcl/qa/cppunit/pdfexport/data/forcepoint71.key b/vcl/qa/cppunit/pdfexport/data/forcepoint71.key new file mode 100644 index 0000000000..716fe58480 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/forcepoint71.key differ diff --git a/vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf b/vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf new file mode 100644 index 0000000000..5d20b1e886 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/forcepoint80-1.rtf @@ -0,0 +1 @@ +{\rtf1\cnsi \ansicpg1252\stshfloch0{\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\green102\blue204;\red102\green99\blue98;\red143\green142\blue142;\red75\green60\blue52;}{\fonttbl{\f0\froman\cpg1257\fcharset186 DejaVu Serif;}{\f1\froman\cpg0\fcharset0 DejaVu Serif;}{\f2\froman\cpg1252\fcharset0 DejaVu Serif;}{\f3\fswiss\cpg1257\fcharset186 DejaVu Sans;}{\f4\fswiss\cpg0\fcharset0 DejaVu Sans;}{\f5\fswiss\cpg1252\fcharset0 DejaVu Sans;}{\f6\fro-De\cpg1257\fcharset186 jaVu Sans;}{\f7\froman\cpg0\fcharset0 Times New Roman;}{\f8\froman\cpg1252\fcharset0 Times New Roman;}{\f9\fmodern\cpg1257\fcharset186 Courier New;}{\f10\fmodern\cpg0\fcharset0 Courier New;}{\f11\fmodern\cpg1252\fcharset0 Courier New;}}{\stylesheet {\ql Normal;}{\s1\sbasedon0\ql\fi-120\sl-276\slmult0 Style1;}{\s2\sbasedon0\qj\fi560\sl-300\slmult0 Style2;}{\s3\sbasedon0\ql\sl-264\slmult0 Style3;}{\s4\sbasedon0\ql\fi-1088\sl-320\slmult0 Style4;}{\s5\sbasedon0\ql Style5;}{\s6\sbasedon0\ql Style6;}{\s7\sbasedon0\ql\sl-320\slmult0 Style7;}{\s8\sbasedon0\qr Style8;}{\s9\sbasedon0\ql Style9;}{\s10\sbasedon0\qj\sl-264\slmult0 Style10;}{\s11\sbasedon0\qj\sl-298\slmult0 Style11;}{\s12\sbasedon0\qj\sl-288\slmult0 Style12;}{\s13\sbasedon0\ql Style13;}{\s14\sbasedon0\ql\fi600\sl-329\slmult0 Style14;}{\s15\sbasedon0\ql\sl-240\slmult0 Style15;}{\s16\sbasedon0\ql Style16;}{\s17\sbasedon0\ql\fi576\sl-328\slmult0 Style17;}{\s18\sbasedon0\ql Style18;}{\s19\sbasedon0\ql\sl-271\slmult0 Style19;}{\s20\sbasedon0\ql\fi2406\sl-339\slmult0 Style20;}{\s21\sbasedon0\ql Style21;}{\s22\sbasedon0\ql\fi2821\sl-161\slmult0 Style22;}{\s23\sbasedon0\ql\fi568\sl-306\slmult0 Style23;}{\s24\sbasedon0\ql Style24;}{\s25\sbasedon0\ql Style25;}{\s26\sbasedon0\ql Style26;}{\s27\sbasedon0\ql Style27;}{\s28\sbasedon0\qj\sl-271\slmult0 Style28;}{\s29\sbasedon0\ql\fi568\sl-322\slmult0 Style29;}{\s30\sbasedon0\ql Style30;}{\s31\sbasedon0\ql Style31;}{\s32\sbasedon0\ql Style32;}{\s33\sbasedon0\ql Style33;}{\s34\sbasedon0\ql Style34;}{\s35\sbasedon0\ql Style35;}{\*\cs36\additive Default Paragraph Font;}{\*\cs37\sbasedon36\additive\b\charscalex120\f2\fs58 Font Style37;}{\*\cs38\sbasedon36\additive\b\charscalex30\f2\fs400 Font Style38;}{\*\cs39\sbasedon36\additive\i\f2\fs22 Font Style39;}{\*\cs40\sbasedon36\additive\scaps\f8\fs8 Font Style40;}{\*\cs41\sbasedon36\additive\i\b\f2\fs10 Font Style41;}{\*\cs42\sbasedon36\additive\f5\fs8 Font Style42;}{\*\cs43\sbasedon36\additive\b\expndtw200\f2\fs10 Font Style43;}{\*\cs44\sbasedon36\additive\f2\fs22 Font Style44;}{\*\cs45\sbasedon36\additive\b\expndtw-10\f2\fs22 Font Style45;}{\*\cs46\sbasedon36\additive\scaps\f2\fs20 Font Style46;}{\*\cs47\sbasedon36\additive\charscalex20\f2\fs104 Font Style47;}{\*\cs48\sbasedon36\additive\b\f2\fs20 Font Style48;}{\*\cs49\sbasedon36\additive\f2\fs22 Font Style49;}{\*\cs50\sbasedon36\additive\b\f2\fs38 Font Style50;}{\*\cs51\sbasedon36\additive\f2\fs20 Font Style51;}{\*\cs52\sbasedon36\additive\expndtw-20\f2\fs30 Font Style52;}{\*\cs53\sbasedon36\additive\i\expndtw-10\f2\fs22 Font Style53;}{\*\cs54\sbasedon36\additive\i\expndtw-20\f2\fs22 Font Style54;}{\*\cs55\sbasedon36\additive\f2\fs22 Font Style55;}{\*\cs56\sbasedon36\additive\f2\fs18 Font Style56;}{\*\cs57\sbasedon36\additive\b\expndtw10\f2\fs16 Font Style57;}{\*\cs58\sbasedon36\additive\b\f2\fs20 Font Style58;}{\*\cs59\sbasedon36\additive\i\b\expndtw-10\f11\fs22 Font Style59;}{\*\cs60\sbasedon36\additive\f2\fs20 Font Style60;}{\*\cs61\sbasedon36\additive\f2\fs12 Font Style61;}{\*\cs62\sbasedon36\additive\f2\fs18 Font Style62;}{\*\cs63\sbasedon36\additive\i\expndtw-20\f2\fs22 Font Style63;}{\*\cs64\sbasedon36\additive\b\expndtw-20\f2\fs26 Font Style64;}}\fet2{\*\ftnsep {\chftnsep\par }}{\*\aftnsep {\chftnsep\par }}\expshrtn\widowctrl\paperw20384\paperh12312\margl360\margr360\margt360\margb360 \sectd \sbknone\pgwsxn20384\pghsxn12312\marglsxn360\margrsxn360\margtsxn360\margbsxn360\titlepg\cols2\colno1\colw8632\colsr2104\colno2\colw8928 {\headerf }{\footerf }{\header \pard \plain \s11\ql\li720\fi0\ri9\sb0\sa0\tx2120 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \'e1\f0\cchs186 Ma\ul b\f0\cchs186 \'fb\f0\cchs186 s vaikai:\ul0 {\charscalex100\expndtw0\tab }\ul ir galimyb\f0\cchs186 \'eb\f0\cchs186 s\par }{\footer \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx0\posnegy0\absw0\absh-254\nowrap\dfrmtxtx34\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 {\field{\*\fldinst{PAGE}}{\fldrslt 100}}\par \pard \plain \s21\qr\li720\fi0\ri9{\sl-240\slmult0\fs20\par }\sb90\sa0 \cs61\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs12 101\par }\pard\sl-4680\slmult0\sb0\keepn\pvpara\dropcapli7\dropcapt1{\b\i0\ul0\cf0\highlight0\charscalex30\f0\fs400{i}\par}\pard \plain \s1\ql\li880\fi-880\ri0\sb0\sa0\sl-272\slmult0 \cs37\i0\strike0\nosupersub\b\scaps0\charscalex120\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs58 Hfc \cs55\0\super\charscalex100\fs22 mddj8\nosupersub \super tUn\nosupersub \super tam\nosupersub \super dkrts\nosupersub identifikacijos proced\f0\cchs186 \'fb\f0\cchs186 ras, vadinasi \cs60\fs20 ivuiiy* toje \cs55\fs22 programoje \cs53\i\expndtw-10 asmenys \cs55\i0\expndtw0 turi mok\f0\cchs186 \'eb\f0\cchs186 ti naudotis identifikacijos \f0\cchs186 \'e1\f0\cchs186 ran-\cs60\fs20 *>*\f0\cchs186 \'ab\'f8\f0\cchs186 geb\f0\cchs186 \'eb\f0\cchs186 ti \cs55\fs22 analizuoti mokini\f0\cchs186 \'f8\f0\cchs186 veiklos produktus ir pati mokymosi proces\f0\cchs186 \'e0\f0\cchs186 , \cs60\f0\cchs186\fs20 \'95\f0\cchs186 tpaftistant \cs55\fs22 kriterijus, pagal kuriuos vaikas gali b\f0\cchs186 \'fb\f0\cchs186 ti priskirtas gabi\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 grupei. \cs60\fs20 Vargu, ar \cs55\fs22 bc specialaus \cs53\i\expndtw-10 pasirengimo \cs55\i0\expndtw0 gali dirbti mokytojas. Pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, Clark modelyje numatyta, kad mokytojas turi b\f0\cchs186 \'fb\f0\cchs186 ti \f0\cchs186 \'e1\f0\cchs186 vald\f0\cchs186 \'e6\f0\cchs186 s \f0\cchs186 \'e1\f0\cchs186 tampos klas\f0\cchs186 \'eb\f0\cchs186 je suma\f0\cchs186 \'fe\f0\cchs186 i\-nimo strategijas (autogenin\f0\cchs186 \'e6\f0\cchs186 treniruot\f0\cchs186 \'e6\f0\cchs186 , meditacij\f0\cchs186 \'e0\f0\cchs186 ), turi geb\f0\cchs186 \'eb\f0\cchs186 ti parinkti mo\-kymo med\f0\cchs186 \'fe\f0\cchs186 iag\f0\cchs186 \'e0\f0\cchs186 , pratimus ir u\f0\cchs186 \'fe\f0\cchs186 duotis, kurioms atlikti b\f0\cchs186 \'fb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 naudojama abiej\f0\cchs186 \'f8 \f0\cchs186 smegen\f0\cchs186 \'f8\f0\cchs186 pusrutuli\f0\cchs186 \'f8\f0\cchs186 veikla, geb\f0\cchs186 \'eb\f0\cchs186 ti \f0\cchs186 \'e1\f0\cchs186 ugdymo turin\f0\cchs186 \'e1\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 traukti pratimus, kurie, panaudojant fizin\f0\cchs186 \'e1\f0\cchs186 k\f0\cchs186 \'fb\f0\cchs186 n\f0\cchs186 \'e0\f0\cchs186 , abstraktaus ir simbolinio lygmens \cs39\i informacij\f0\cchs186 \'e0\f0\cchs186 , \cs55\i0 trans\-formuoja \f0\cchs186 \'e1\f0\cchs186 konkretesn\f0\cchs186 \'e1\f0\cchs186 lygmen\f0\cchs186 \'e1\f0\cchs186 ir pan. Kai kurie autoriai, pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, Wil-liams, netgi nurodo mokymo strategijas, kurias \cs39\i naudoti savo \cs55\i0 darbe turi mok\f0\cchs186 \'eb\f0\cchs186 ti \cs60\fs20 mokytojas, \cs55\fs22 kiti savo darbo komand\f0\cchs186 \'e0\f0\cchs186 apmoko. Renzulli modelio realizavimo komand\f0\cchs186 \'e0\f0\cchs186 sudaro ne tik mokytojai, bet ir t\f0\cchs186 \'eb\f0\cchs186 vai, bendruomen\f0\cchs186 \'eb\f0\cchs186 s ekspertai, mo\-kyklos administracija ir kt. personalas. Modelio veikimo efektyvum\f0\cchs186 \'e0\f0\cchs186 vertina \cs53\i\expndtw-10 visi \cs39\expndtw0 jo \cs53\expndtw-10 dalyviai, pagal tokios analiz\f0\cchs186 \'eb\f0\cchs186 s \cs55\i0\expndtw0 rezultatus bei mokini\f0\cchs186 \'f8\f0\cchs186 pageidavimus ar pakitusius poreikius ugdymo programa modifikuojama.\par \pard \plain \s2\ql\li576\fi560\ri0\sb0\sa0\sl-296\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Atskirai reik\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 pamin\f0\cchs186 \'eb\f0\cchs186 ti Taylor model\f0\cchs186 \'e1\f0\cchs186 . Jis vadinamas ir muititalento, ir k\f0\cchs186 \'fb\f0\cchs186 rybinio bei kritinio m\f0\cchs186 \'e0\f0\cchs186 stymo modeliu. \cs39\i Laikoma, kad \cs55\i0 bent vienai (j\f0\cchs186 \'f8\f0\cchs186 nuro\-domos net devynios) gabumo sri\f0\cchs186 \'e8\f0\cchs186 iai yra gabus kiekvienas vaikas. Toks gabi\f0\cchs186 \'f8 \f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 \cs53\i\expndtw-10 ugdymo modelis tur\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 b\f0\cchs186 \'fb\f0\cchs186 ti \cs39\expndtw0 priimtinas ir \cs55\i0\f0\cchs186 \'fe\f0\cchs186 mon\f0\cchs186 \'eb\f0\cchs186 ms, kurie mano, jog visi vaikai \cs60\fs20 turi \cs55\fs22 tam \cs53\i\expndtw-10 tikr\f0\cchs186 \'f8\f0\cchs186 \cs55\i0\expndtw0 gabum\f0\cchs186 \'f8\f0\cchs186 , ir d\f0\cchs186 \'eb\f0\cchs186 l koki\f0\cchs186 \'f8\f0\cchs186 nors prie\f0\cchs186 \'fe\f0\cchs186 as\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 nenori pripa\-\cs60\f0\cchs186\fs20 \'fe\f0\cchs186 inti \cs55\fs22 gabum\f0\cchs186 \'f8\f0\cchs186 \cs53\i\expndtw-10 lygmens \cs55\i0\expndtw0 skirtum\f0\cchs186 \'f8\f0\cchs186 . Modelio autorius nurodo \f0\cchs186 \'f0\f0\cchs186 ias gabum\f0\cchs186 \'f8\f0\cchs186 sritis: akademin\f0\cchs186 \'eb\f0\cchs186 s srities, \cs53\i\expndtw-10 produktyviojo \cs55\i0\expndtw0 m\f0\cchs186 \'e0\f0\cchs186 stymo, komuniJcavimo, prognozavimo, \cs53\i\expndtw-10 sprendim\f0\cchs186 \'f8\f0\cchs186 pri\f0\cchs186 \'eb\f0\cchs186 mimo, plan\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 gyvendinimo, \cs55\i0\expndtw0\f0\cchs186 \'fe\f0\cchs186 mogi\f0\cchs186 \'f0\f0\cchs186 k\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 , galimybi\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\'fe\f0\cchs186 vel\-gimo \cs39\i\expndtw-20 (ir.\expndtw0 2.2.1 \cs53\expndtw-10 lentel\f0\cchs186 \'e6\f0\cchs186 ).\par \pard \plain \s11\qj\li6976\fi0\ri0{\sl-240\slmult0\fs20\par }\sb72\sa0 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 2.2.1 \cs55 lentel\f0\cchs186 \'eb\par \pard \plain \s8\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx6464\posnegy688\absw0\absh-256\dfrmtxtx40\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 U\f0\cchs186 \'fe\f0\cchs186 duo\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 pavyzd\f0\cchs186 \'fe\f0\cchs186 iai\par \pard \plain \s4\qc\li2112\fi0\ri2232\sb0\sa0\sl-320\slmult0 \cs53\b0\strike0\nosupersubLi\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\s22 Gabum\f0\cchs186 \'f8\f0\cchs186 \cs44\i0\expndtw0 ugdymas pagal Taylor \cs55 model\f0\cchs186 \'e1 \f0\cchs186 (pagal TayJor, 1986)\par \pard \plain \s9\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx2648\posnegy368\absw0\absh-328\dfrmtxtx40\dfrmtxty0 \cs53\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\fs22 Geb\f0\cchs186 \'eb\f0\cchs186 jimas \cs55\i0\expndtw0 susikurti \cs39\i atitinka- \{\f0\cchs186 \'84\f0\cchs186 Surinkite informacij\f0\cchs186 \'e0\f0\cchs186 apie... ii\par \pard \plain \s6\qj\li304\fi0\ri0\sb16\sa0 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 I \cs53\expndtw-10 Gabum\f0\cchs186 \'f8\f0\cchs186 sritis Paai\f0\cchs186 \'f0\f0\cchs186 kinimas\par \pard \plain \s10\qj\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \pvpara\phcol\posnegx6032\posnegy328\absw2600\absh-544\dfrmtxtx40\dfrmtxty0 \cs53\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\fs22 j mos temos \f0\cchs186 \'fe\f0\cchs186 ini\f0\cchs186 \'f8\f0\cchs186 ir \f0\cchs186 \'e1\f0\cchs186 g\f0\cchs186 \'fb\f0\cchs186 d\f0\cchs186 \'fe\f0\cchs186 i\f0\cchs186 \'f8 \cs55\i0\expndtw0\f0\cchs186 'baz\f0\cchs186 \'e6\f0\cchs186 .\par \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0\sl-288\slmult0 \pvpara\phcol\posnegx5672\posnegy384\absw2960\absh-584\dfrmtxtx40\dfrmtxty0 \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 kuo \f0\cchs186 \'e1\f0\cchs186 vairesni\f0\cchs186 \'80008\f0\cchs186 \f0\cchs186 \'f0\f0\cchs186 altini\f0\cchs186 \'f8\f0\cchs186 ir j\f0\cchs186 \'e0\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 a\-nalizuokite".\par \pard \plain \s11\ql\li0\fi0\ri0\sb0\sa0\sl-296\slmult0\tlul\tx2520 \pvpara\phcol\posnegx5856\posnegy896\absw2776\absh-1656\dfrmtxtx40\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 f Geb\f0\cchs186 \'eb\f0\cchs186 jimas generuoti \cs60\fs20 ne-\line \cs55\fs22 f \f0\cchs186 \'e1\f0\cchs186 prastas, originalias i\f0\cchs186 \'eb\f0\cchs186 /as,\line \cs60\fs20 f\cs53\i\expndtw-10\fs22 pasteb\f0\cchs186 \'eb\'fb\f0\cchs186 naujus \cs55\i0\expndtw0 s\f0\cchs186 \'e0\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 ius,\line \cs53\i\expndtw-10 | papildyti detal\f0\cchs186 \'eb\f0\cchs186 mis, \cs55\i0\expndtw0 kurios\line \cs53\i\expndtw-10\f0\cchs186 \'c1\f0\cchs186 pa\f0\cchs186 \'e1\f0\cchs186 vairioa id\f0\cchs186 \'eb\f0\cchs186 jas,\expndtw0 {\charscalex100\expndtw0\tab }\par \pard \plain \s6\qj\li232\fi0\ri0\sb0\sa0 \cs53\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-10\dn0\f0\cchs186\lang1063\langfe1063\fs22 'Akademin\f0\cchs186 \'eb\par \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0\sl-272\slmult0 \pvpara\phcol\posnegx5264\posnegy160\absw3368\absh-648\dfrmtxtx40\dfrmtxty0 \cs39\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \'84\f0\cchs186 Sukurkite, kuo \cs60\i0\fs20 pakeisti \f0\cchs186 \'e1\f0\cchs186 prastas energijos r\f0\cchs186 \'fb\'f0\f0\cchs186 is".\par \pard \plain \s7\ql\li0\fi0\ri0\sb0\sa0\sl-320\slmult0 \cs39\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 (K\f0\cchs186 \'fb\f0\cchs186 rybos, produktyvioio\par \pard \plain \s13\qj\li5816\fi0\ri0\sb88\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 2.2.1 icntcU\par \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-240\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Gabum\f0\cchs186 \'f8\f0\cchs186 \cs60\fs20 sritis\par \pard \plain \s15\ql\li0\fi40\ri0\sb0\sa0\sl-240\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Sprendim\f0\cchs186 \'f8 \f0\cchs186 pri\f0\cchs186 \'eb\f0\cchs186 mimo\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-248\slmult0\tlul\tx2736 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Paai\f0\cchs186 \'f0\f0\cchs186 kinimas {\charscalex100\expndtw0\tab }Ll\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas rasti alternatyvas, \cs55\fs22 l.,\par \pard \plain \s15\ql\li32\fi-32\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 jas \f0\cchs186 \'e1\f0\cchs186 vertinti ir priimti tinka- \cs55\fs22 t \cs60\fs20 r m\f0\cchs186 \'e0\f0\cchs186 problemos sprendim\f0\cchs186 \'e0\f0\cchs186 . 1 \cs41\b\i\f0\cchs186\fs10 \'e1\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs5u\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 J\f0\cchs186 \'fe\f0\cchs186 duo\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 pavyzd\f0\cchs186 \'fe\f0\cchs186 iai Nurodykite \cs60\fs20 savo \cs55\fs22 m\f0\cchs186 \'eb\f0\cchs186 giamiausi\f0\cchs186 \'e0\f0\cchs186 \cs60\fs20 I\par \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 a\f0\cchs186 \'f0\f0\cchs186 y toj\f0\cchs186 \'e0\f0\cchs186 , ai\f0\cchs186 \'f0\f0\cchs186 kiai pagr\f0\cchs186 \'e1\f0\cchs186 sdami at- t \cs60\fs20 rumentais \cs55\fs22 savo pasirinkim\f0\cchs186 \'e0\f0\cchs186 it\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 itmetim\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Planavimo\cell \pard \plain \s15\ql\li16\fi-16\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas numatyti kelius ir b\f0\cchs186 \'fb\f0\cchs186 dus id\f0\cchs186 \'eb\f0\cchs186 jai \f0\cchs186 \'e1\f0\cchs186 gyvendinti, nustatant, koki\f0\cchs186 \'f8\f0\cchs186 reikia resur- \cs55\fs22 1 \cs60\fs20 s\f0\cchs186 \'f8\f0\cchs186 , \f0\cchs186 \'e1\'fe\f0\cchs186 velgiant, kokios gali\-mos problemos, ir numatant \f0\cchs186 \'fe\f0\cchs186 ingsnius j\f0\cchs186 \'f8\f0\cchs186 sprendimui, to\-kiu b\f0\cchs186 \'fb\f0\cchs186 du patobulinant plan\f0\cchs186 \'e0\f0\cchs186 .\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-256\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 .I\f0\cchs186 \'f0\f0\cchs186 studijav\f0\cchs186 \'e6\f0\cchs186 \cs55\fs22 mitus apie \f0\cchs186 \'f0\f0\cchs186 ik\f0\cchs186 \'f0\f0\cchs186 nos\-\cs60\fs20 parnius, \cs55\fs22 sukurkite tyrimo plan\f0\cchs186 \'e0\f0\cchs186 \cs62\fs18 1\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-256\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 savo draug\f0\cchs186 \'f8\f0\cchs186 \cs55\fs22 nuomonei \cs60\fs20 apie \f0\cchs186 \'f0\f0\cchs186 iuos gyv\f0\cchs186 \'fb\f0\cchs186 nus i\f0\cchs186 \'f0\f0\cchs186 tirti\super 41\nosupersub , \f0\cchs186 \'84\f0\cchs186 Sukurkite akcijos prie\f0\cchs186 \'f0\f0\cchs186 \cs55\fs22 r\f0\cchs186 \'fb\f0\cchs186 kym\f0\cchs186 \'e0\f0\cchs186 \cs62\fs18 1 \cs60\fs20 plan\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Prognozavimo\cell \pard \plain \s15\ql\li0\fi8\ri0\sb0\sa0\sl-248\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas numatyti ir pati\-krinti prie\f0\cchs186 \'fe\f0\cchs186 asties ir pasekm\f0\cchs186 \'eb\f0\cchs186 s s\f0\cchs186 \'e0\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 ius.\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 I\f0\cchs186 \'f0\f0\cchs186 studijuokite N sutart\f0\cchs186 \'e1\f0\cchs186 ir nurodykite \f0\cchs186 \'e1\f0\cchs186 vairias galimas jos i ratifikavimo pasekmes".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Komunikavimo\cell \pard \plain \s15\ql\li0\fi16\ri0\sb0\sa0\sl-256\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas reik\f0\cchs186 \'f0\f0\cchs186 ti savo id\f0\cchs186 \'eb\f0\cchs186 jas, jausmus, poreikius ir suprasti kitus, vartojant verbalin\f0\cchs186 \'e6\f0\cchs186 ir neverbalin\f0\cchs186 \'e6\f0\cchs186 kalb\f0\cchs186 \'e0\f0\cchs186 .\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 Pademonstruokite savo jaus- \cs55\fs22 1 \cs60\fs20 mus, kai su\f0\cchs186 \'fe\f0\cchs186 inote apie ... \f0\cchs186 \'84\f0\cchs186 Papasakokite apie \f0\cchs186 \'e1\f0\cchs186 vyk\f0\cchs186 \'e1\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 vaiko i ir i\f0\cchs186 \'f0\f0\cchs186 suaugusiojo pozicini". i\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Plan\f0\cchs186 \'f8\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'e1\f0\cchs186 gyvendinimo\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas \f0\cchs186 \'e1\f0\cchs186 gyvendinti plan\f0\cchs186 \'e0\cell \pard \plain \s16\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs43\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw200\dn0\f0\cchs186\lang1063\langfe1063\fs10 \'97\f0\cchs186 \f0\cchs186 \'97\f0\cchs186 \f1\cchs186 \u9632\'3f\f0\cchs186 - \f0\cchs186 \'97\'97\f0\cchs186  \expndtw0 *-\expndtw200 \expndtw0 L-\expndtw200 \expndtw0 -\expndtw200 \cs42\b0\expndtw0\f3\cchs186\fs8 i \f4\cchs186 \u9632\'3f\f3\cchs186 \f4\cchs186 \u9632\'3f\f3\cchs186 \cs41\b\i\f0\cchs186\fs10 a \cs40\b0\i0\scaps\f6\cchs186\fs8 - ii \f7\cchs186 \u9632\'3f\f6\cchs186 \cs62\scaps0\f0\cchs186\fs18 1\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-264\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 Sukurkite ir \f0\cchs186 \'e1\f0\cchs186 gyvendinkite N 1 renginio plan\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1848 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx4792 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8376 \pard \plain \s15\ql\li32\fi-32\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Galimybi\f0\cchs186 \'f8 \'e1\'fe\f0\cchs186 velgimo\cell \pard \plain \s15\ql\li0\fi40\ri0\sb0\sa0\sl-272\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Geb\f0\cchs186 \'eb\f0\cchs186 jimas identifikuoti gali\-myb\f0\cchs186 \'e6\f0\cchs186 ir ja pasinaudoti.\cell \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\sl-272\slmult0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'84\f0\cchs186 I\f0\cchs186 \'f0\f0\cchs186 tirkite ispan\f0\cchs186 \'f8\f0\cchs186 kalbos mokymo(si) poreik\f0\cchs186 \'e1\f0\cchs186 mokykloje ir inicijuokite atitinkamos pro\-gramos \f0\cchs186 \'e1\f0\cchs186 gyvendinim\f0\cchs186 \'e0\f0\cchs186 ".\cell \pard\intbl\row \pard\pard \plain \s14\ql\li0\fi600\ri0\sb232\sa0\sl-328\slmult0 \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Taylor siekia ugdyti kuo daugiau gabum\f0\cchs186 \'f8\f0\cchs186 , kuriais, jo manymu, pasi\f0\cchs186 \'fe\f0\cchs186 ymi vaikai. Tad kuo \f0\cchs186 \'e1\f0\cchs186 vairesniems vaik\f0\cchs186 \'f8\f0\cchs186 gabumams mokytojas skirs d\f0\cchs186 \'eb\f0\cchs186 mes\f0\cchs186 \'e1\f0\cchs186 , tuo daugiau galimybi\f0\cchs186 \'f8\f0\cchs186 , kad vaikas ras srit\f0\cchs186 \'e1\f0\cchs186 , kurios \f0\cchs186 \'fe\f0\cchs186 inovu jis gali tapti. Ta\f0\cchs186 \'e8\f0\cchs186 iau pir\-masis \f0\cchs186 \'f0\f0\cchs186 io modelio etapas - tai vis d\f0\cchs186 \'eb\f0\cchs186 lto akademini\f0\cchs186 \'f8\f0\cchs186 gabum\f0\cchs186 \'f8\f0\cchs186 ugdymas. Kitas \f0\cchs186 \'fe\f0\cchs186 ingsnis, skirtas mokytojui apsispr\f0\cchs186 \'e6\f0\cchs186 sti, kuri\f0\cchs186 \'e0\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 likusi\f0\cchs186 \'f8\f0\cchs186 a\f0\cchs186 \'f0\f0\cchs186 tuoni\f0\cchs186 \'f8\f0\cchs186 gabum\f0\cchs186 \'f8\f0\cchs186 sri\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8 \f0\cchs186 jis imasi ugdyti. Paprastai seka, anot autoriaus, tur\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 b\f0\cchs186 \'fb\f0\cchs186 ti tokia: produktyvusis m\f0^cchs186 \'e0\f0\cchs186 stymas, planavimas, sprendim\f0\cchs186 \'f8\f0\cchs186 pri\f0\cchs186 \'eb\f0\cchs186 mimas, pian\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 gyvendinimas, \f0\cchs186 \'e1\'fe\f0\cchs186 valgos. Akivaizdu, jog dirbti pagal \f0\cchs186 \'f0\'e1\f0\cchs186 model\f0\cchs186 \'e1\f0\cchs186 mokytojas tur\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 b\f0\cchs186 \'fb\f0\cchs186 ti specialiai pasi\-reng\f0\cchs186 \'e6\f0\cchs186 s, tad modelio autorius si\f0\cchs186 \'fb\f0\cchs186 lo kelet\f0\cchs186 \'e0\f0\cchs186 mokytojo darbo metod\f0\cchs186 \'f8\f0\cchs186 . Pirmuouiu atveju si\f0\cchs186 \'fb\f0\cchs186 loma papildom\f0\cchs186 \'f8\f0\cchs186 gabum\f0\cchs186 \'f8\f0\cchs186 ugdym\f0\cchs186 \'e0\f0\cchs186 organizuoti baigiantis pamokoms. \f0\cchs186 \'c1\f0\cchs186 prastinis mokymo turinys \f0\cchs186 \'84\f0\cchs186 suspaud\f0\cchs186 \'fe\f0\cchs186 iamas" laike, o atsiradusias 5\f0\cchs186 \'97\f0\cchs186 10 laisvuj minu\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 mokytojas gali i\f0\cchs186 \'f0\f0\cchs186 naudoti pasirinkto gabumo ugdymui. Kai \cs48\b\fs20 mokytojui \cs44\b0\fs22 atrodo, kad jau pasiekta tam tikra pa\f0\cchs186 \'fe\f0\cchs186 anga ugdant pirm\f0\cchs186 \'e0\f0\cchs186 j\f0\cchs186 \'e1\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 o pasirinkt\f0\cchs186 \'f8\f0\cchs186 ga\-\par \sect\soctd \sbkpage\pgwsxn20855\pghsxn13316\marglsxn1080\margrsxn8026\margtsxn360\margbsxn360\cols2\colno1\colw7936\colsr2482\colno2\colw1329 {\header \pard \plain \s11\ql\li0\fi0\ri-7657\sb0\sa0\tx2245 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \'e1\f0\cchs186 Ma\ul b\f0\cchs186 \'fb\f0\cchs186 s vaikai:\ul0 {\charscalex100\expndtw0\tab }\ul ir galimyb\f0\cchs186 \'eb\f0\cchs186 s\par }{\footer \par \plain \s11\qj\li0\fi0\ri0\sb0\sa0 \pvpara\phcol\posnegx-720\posnegy0\absw0\absh-254\nowrap\dfrmtxtx34\dfrmtxty0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 {\field{\*\fldinst{PAGE}}{\fldrslt 100}}\par \pard \plain \s21\qr\li0\fi0\ri-7657{\sl-240\slmult0\fs20\par }\sb90\sa0 \cs61\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs12 101\par }{\shp {\*\shpinst \chpleft13358\shptop593\shpright14748\shpbottom830\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz1\shplid1{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 317500}}{\sp{\sn dyWrapDistBottom}{\sv 198755}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s31\qj\li0\fi0\ri0\sb0\sa0 \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Rai\f0\cchs186 \'f0\f0\cchs186 kos \cs51\b0 b\f0\cchs186 \'fb\f0\cchs186 dai\par }}}{\shp {\*\shpinst \shpleft11859\shptop534\shpright13172\shpbottom2169\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz0\shplid0{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 279400}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0\sl-254\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas\par \pard \plain \s13\ql\li0\fi0\ri0\sb17\sa0\sl-271\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Ugdytojo ir ugdytini\f0\cchs186 \'f8 \f0\cchs186 s\f0\cchs186 \'e0\f0\cchs186 veika, ko\-munikacija\par }}}{\shp {\*\shpinst \shp|eft13350\shptop1144\shpright17594\shpbottom2296\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz2\shplid2{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 139700}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPint}{\sv 1}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0\sl-271\slmult0 \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Informacijos srautai \f0\cchs186 \'97\f0\cchs186 \cs48\b Asmenvb\f0\cchs186 \'eb\f0\cchs186 s tobuli* tiesioginiai ir \cs60\b0 gr\f0\cchs186 \'e1\'fe\f0\cchs186 tamieji, ir s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 \cs48\b tobulintai pedagogin\f0\cchs186 \'eb\f0\cchs186 \cs60\b0 sistema sudarymas: \cs48\b\f0\cchs186 \'fb\f0\cchs186 ssionj\par \pard \plain \s33\ql\li2499\fi0\ri0\sb93\sa0 \cs51\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 - b. \cs60 y\super 1\nosupersub "\super 0\nosupersub \cs51 HBB\par }}}{\shp {\*\shpinst \shpleft13299\shptop2228\shpright14205\shpbottom2474\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz4\shplid4{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Saviugda\par }}}{\shp {\*\shpinst \shpleft15874\shptop2279\shpright17187\shpbottom2524\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz5\shplid5{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s12\qj\li0\fi0\ri0\sb0\sa0 \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Tobulinimasis\par }}}{\shp {\*\shpinst \shpleft11867\shptop2152\shpright13078\shpbottom2812\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz3\shplid3{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 640080}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Individo as\-menyb\f0\cchs186 \'eb\par }}}{\shpgrp{\*\shpinst \shpleft-720\shptop3939\shpright7878\shpbottom12384\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz6\shplid6{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn groupLeft}{\sv 1067}}{\sp{\sn groupTop}{\sv 6209}}{\sp{\sn groupRight}{\sv 9665}}{\sp{\sn groupBottom}{\sv 14654}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 1067}}{\sp{\sn relTop}{\sv 6429}}{\sp{\sn relRight}{\sv 9665}}{\sp{\sn relBottom}{\sv 14654}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li474\fi0\ri0\sb0\sa0\sl-271\slmult0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1 \cs48\b\fs20 Ugdymo \cs49\b0\fs22 res \cs46\scaps\fs20 f\cs48\b\scaps0 lyb\f0\cchs186 \'eb\f0\cchs186 s lygmu\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 i- \cs49\b0\fs22 Strukt\f0\cchs186 \'fb\f0\cchs186 rini \cs48\b\fs20 o elementas\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 s Rai\f0\cchs186 \'f0\f0\cchs186 kos b\f0\cchs186 \'fb\f0\cchs186 dai\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Funkcijos\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li440\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 j \cs48\b\fs20 Valstybinis\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Valstyb\f0\cchs186 \'eb\f0\cchs186 s politika\cell \pard \plain \s19\ql\li0\fi8\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 \'d0\f0\cchs186 vietimo politika ir j\f0\cchs186 \'e0 \f0\cchs186 atspindintys \f0\cchs186 \'e1\f0\cchs186 statymai\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-288\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Teisinis reguliavimas, u\f0\cchs186 \'fe\f0\cchs186 tikrinantis kiekvie\-nam vaikui (vadinasi, ir gabiam) teis\f0\cchs186 \'e6\f0\cchs186 gauti jo poreikius ir galimybes atitinkant\f0\cchs186 \'e1\f0\cchs186 ugdym\f0\cchs186 \'e0\f0\cchs186 ir ug\-dymosi s\f0\cchs186 \'e0\f0\cchs186 lygas\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li390\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langde1063\fs20 Visuomeninis\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-280\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Visuomen\f0\cchs186 \'eb\f0\cchs186 s institutai\cell \pard \plain \s19\ql\li0\fi68\ri0\sb0\sa0\sl-288\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Vyriausybines insti\-tucijos/ visuomenini\f0\cchs186 \'f8 \f0\cchs186 organizacij\f0\cchs186 \'f8\f0\cchs186 /paramos fond\f0\cchs186 \'f8\f0\cchs186 /auk\f0\cchs186 \'f0\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 moky\-kl\f0\cchs186 \'f8\f0\cchs186 /mokslo institucij\f0\cchs186 \'f8 \cs39\b0\i\f0\cchs186\fs22 tikslin\f0\cchs186 \'eb\f0\cchs186 \cs48\i0\b\fs20 veikla\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-296\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Veiklos inicijavimas; koordinavimas, organi\-zavimas, informacijos kaupimas, analiz\f0\cchs186 \'eb\f0\cchs186 ir sklai\-da; gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 paie\f0\cchs186 \'f0\f0\cchs186 kos programos, identifikavi\-mas, globa; mokytoj\f0\cchs186 \'f8\f0\cchs186 ir kit\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'f0\f0\cchs186 vietimo darbuotoj\f0\cchs186 \'f8 \f0\cchs186 rengi mas;ugdymo t\f0\cchs186 \'e6\f0\cchs186 sti\-numo u\f0\cchs186 \'fe\f0\cchs186 tikrinimas; kt.\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx1889 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx3354 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx5836 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8597 \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 1 Institucinis\par \pard \plain \s25\ql\li0\fi0\ri0\sb0\sa0\sl-983\slmult0 \intbl \cs47\b0\i0\strike0\nosupersub\scaps0\charscalex20\expndtw0\dn19\f0\cchs186\lang1063\langfe1063\fs104 1\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Ugdymo nstituci\f0\cchs186 \'e1\f0\cchs186 os\par \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 i \cs49\b0\fs22 1 \cs48\b\fs20 i\par \pard \plain \s26\ql\li0\fi0\ri0\sb0\sa0\sl-381\slmult0 \intbl \cs50\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn5\f0\cchs186\lang1063\langfe1063\fs38 !\cell \pard \plain \s19\ql\li25\fi-25\ri0\sb0\sa0\sl-296\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo modelis institucijos lygmeniu \f0\cchs186 \'97\f0\cchs186 mokyklos, papildomojo ugdymo mokyklos, technin\f0\cchs186 \'eb\f0\cchs186 s \{\f0\cchs186 \'fb\f0\cchs186 rybos namai, klas\f0\cchs186 \'eb\f0\cchs186 s, tovyklos, kursai, kon\-kursai ir kt.\cell \pard \plain \s19\ql\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \intbl \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw-5420746430195647047\dn0\f0\cchs186\lang1063\langfe1063\fs20 Ugdymo proceso opti\-mizavimas: optimalios ugdymo(si) aplinkos sudarymas, ugdymas, mo\-kymas, veiklos rezultat\f0\cchs186 \'f8 \f0\cchs186 vertinimas, mokymo dife\-rencijavimas ir kt.\cell \pard\intbl\row \pard}}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 3371}}{\sp{\sn relTop}{\sv 6209}}{\sp{\sn relRight}{\sv 7988}}{\sp{\sn relBotto}}{\sv 6497}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s18\qj\li0\fi0\ri0\sb0\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Gabi\f0\cchs186 \'f8\f0\cchs186 \cs49 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo ir jo s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 modelis\par }}}}}\pard \plain \s14\qr\li0\fi0\ri0\sb0\sa0\sl-305\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 m\f0\cchs186 \'e0\f0\cchs186 gali apib\f0\cchs186 \'fb\f0\cchs186 dinti asmenyb\f0\cchs186 \'eb\f0\cchs186 s saviugda, iritrapersonaliniame lygmenyje \f0\cchs186 \'e1\f0\cchs186 gyjanti gryn\f0\cchs186 \'e0\f0\cchs186 rai\f0\cchs186 \'f0\f0\cchs186 k\f0\cchs186 \'e0\f0\cchs186 . \cs45\b\expndtw-10 II \cs55\b0\expndtw0 esm\f0\cchs186 \'eb\f0\cchs186 s \cs53\i\expndtw-10 vis\f0\cchs186 \'f8\f0\cchs186 \cs55\i0\expndtw0 anks\f0\cchs186 \'e8\f0\cchs186 iau min\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 strukt\f0\cchs186 \'fb\f0\cchs186 rini\f0\cchs186 \'f8\f0\cchs186 element\f0\cchs186 \'f8\f0\cchs186 funkcionavi\-mo tikslas \cs49 I \cs55 prigimtini\f0\cchs186 \'f8\f0\cchs186 asmens gali\f0\cchs186 \'f8\f0\cchs186 pl\f0\cchs186 \'eb\f0\cchs186 tra ir i\f0\cchs186 \'f0\f0\cchs186 vystymas jo paties j\f0\cchs186 \'eb\f0\cchsq86 gomis iki maksimalaus tam asmeniui galimo lygio. Literat\f0\cchs186 \'fb\f0\cchs186 roje (Gross, 1995; Almonaitien\f0\cchs186 \'eb\f0\cchs186 , 1997; Heller, 1999; Gagne, 2004 ir kt.) nurodoma, kad gabaus vaiko savirealizaci\-jai turi (takos jo asmenyb\f0\cchs186 \'eb\f0\cchs186 s nekognityvin\f0\cchs186 \'eb\f0\cchs186 s savyb\f0\cchs186 \'eb\f0\cchs186 s - pasiekim\f0\cchs186 \'f8\f0\cchs186 motyvacija, tei\-giamas \cs45\b\expndtw-10 sav\f0\cchs186 \'e6\f0\cchs186 s \cs55\b0\expndtw0 vertinimas, darbingumas, savikontrol\f0\cchs186 \'eb\f0\cchs186 ir kt. Yra pagrindo manyti, kad tinkamas min\f0\cchs186 \'eb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 GAVUS modelio strukt\f0\cchs186 \'fb\f0\cchs186 rini\f0\cchs186 \'f8\f0\cchs186 element\f0\cchs186 \'f8\f0\cchs186 funkcionavimas palankiai veikia gabaus vaiko asmenyb\f0\cchs186 \'e6\f0\cchs186 , taigi skatina \cs45\b\expndtw-10 j\f0\cchs186 \'e1\f0\cchs186 \cs55\b0\expndtw0 tobul\f0\cchs186 \'eb\f0\cchs186 ti.\par \pard \plain \s2\qj\li0\fi584\ri0\sb8\sa0\sl-271\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Apibendrinant tai, kas pasakyta, galima pateikti tok\f0\cchs186 \'e1\f0\cchs186 teorin\f0\cchs186 \'e1\f0\cchs186 gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8 \f0\cchs186 ugdymo ir jo s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 model\f0\cchs186 \'e1\f0\cchs186 :\par \pard \plain \s11\qr\li0\fi0\ri0{\sl-240\slmult0\fs20\par }\sb99\sa0 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 3.1 \cs55 lentel\f0\cchs186 \'eb\par \column \pard \plain \s28\qj\li0\fi0\ri0{\sl-240\slmult0\fs20\par }\sb200\sa0\sl-271\slmult0 \cs48\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Ugdymo rea-\ul lyb\f0\cchs186 \'eb\f0\cchs186 s lygmuo\par \pard \plain \s11\qj\li0\fi0\ri0\sb42\sa0\sl-246\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Interpersona-linis\khftn{\footnote\pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \chftn Pastaba. Interpersonalinio ir intrapersonalinio \cs48\b\fs20 lygmens \cs55\b0\fs22 elemcr\cs48\b\f0\cchs186\fs20 \'a3\f0\cchs186 E\cs52\b0\expndtw-20\fs30 ^^PK\cs48\b\expndtw0\fs20 ^niaj\par \pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 modelio elementai, kuri\f0\cchs186 \'f8\f0\cchs186 optimaliamveikimui \cs49 ir skirtas ug\strike dy\strike0 m\strike o\strike0 \cs55 s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 \cs60\fs20 mo\-\cs55\fs22 delis\par \pard \plain \s23 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Sukurtasis \expndtw0 GAVUS\expndtw-20 moeelis turi savo strukt\f0\cchs186 \'fb\f0\cchs186 r\f0\cchs186 \'e0\f0\cchs186 , funkcijas \cs53\expndtw-10 ir \cs63\expndtw0 funkcionavimo\expndtw-20 \expndtw0 aptin-\cs53\expndtw-10 k\f0\cchs186 \'e0\f0\cchs186 . \cs63\expndtw-20 Modelis turi \expndtw0 paskirti\expndtw-20 bendr\f0\cchs186 \'e0\f0\cchs186 tiksl\f0\cchs186 \'e0\f0\cchs186 \f0\cchs186 \'97\f0\cchs186 \cs49\i0\expndtw0 sudaryti s\f0\cchs186 \'e0\f0\cchs186 lygas gabiems valkams, nepriklausomai nuo j\f0\cchs186 \'f8\f0\cchs186 socialin\f0\cchs186 \'eb\f0\cchs186 s pad\f0\cchs186 \'eb\f0\cchs186 ties, gyvenamosios vietos, am\-\f0\cchs186 \'fe\f0\cchs186 iaus, lyties ir kt., rinktis j\f0\cchs186 \'f8\f0\cchs186 poreikius atitinkanti ugdym\f0\cchs186 \'e0\f0\cchs186 ir galimybes saviugdai, pad\f0\cchs186 \'eb\f0\cchs186 ti jam ir skatinti vaik\f0\cchs186 \'e0\f0\cchs186 siekti pilno savojo gabum\f0\cchs186 \'f8\f0\cchs186 po\-tencialo realizavimo ir b\f0\cchs186 \'fb\f0\cchs186 ti naudingam visuomenei, Sis tikslas suteikia modeliui vienov\f0\cchs186 \'eb\f0\cchs186 s, vientisumo.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Kiekvienas strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas turi ir papildom\f0\cchs186 \'f8\f0\cchs186 (i\f0\cchs186 \'f0\f0\cchs186 vestini\f0\cchs186 \'f8\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 ben\-drojo) tiksl\f0\cchs186 \'f8\f0\cchs186 , kurie susij\f0\cchs186 \'e6\f0\cchs186 su funkcijomis, kurias atlieka strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas. Modelis skirtas \f0\cchs186 \'fe\f0\cchs186 mogui jame vyksta informacijos perdavimo ir valdymo pro\-cesai \f0\cchs186 \'97\f0\cchs186 tai b\f0\cchs186 \'fb\f0\cchs186 dinga visuomenin\f0\cchs186 \'eb\f0\cchs186 ms sistemoms.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis sudarytas i\f0\cchs186 \'f0\f0\cchs186 posistemi\f0\cchs186 \'f8\f0\cchs186 (pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, GVU atskiroje ugdymo institucijoje, jo posistem\f0\cchs186 \'eb\f0\cchs186 - pedagogin\f0\cchs186 \'eb\f0\cchs186 sistema, ir kt.). Visi GAVUS elementai yra vienaip ar kitaip susij\f0\cchs186 \'e6\f0\cchs186 su ugdymu ir jo funkcijomis: \f0\cchs186 \'f0\f0\cchs186 vietimu, lavinimu, aukl\f0\cchs186 \'eb\f0\cchs186 jimu, mokymu, globojimu, formavimu ir kt. Kiekviena jo sud\f0\cchs186 \'eb\f0\cchs186 tin\f0\cchs186 \'eb\f0\cchs186 dalis atlieka tam tikr\f0\cchs186 \'e0\f0\cchs186 funkcij\f0\cchs186 \'e0\f0\cchs186 (jas nurod\f0\cchs186 \'eb\f0\cchs186 me aptardami model\f0\cchs186 \'e1\f0\cchs186 ). Tuomet, kai mo\-delio strukt\f0\cchs186 \'fb\f0\cchs186 riniai elementai funkcionuoja visuose ugdymo realyb\f0\cchs186 \'eb\f0\cchs186 s lygmeny\-se, jis apima daugel\f0\cchs186 \'e1\f0\cchs186 aplinkos veiksni\f0\cchs186 \'f8\f0\cchs186 , kurie yra gabumo virsmo pasiekimais katalizatoriai. Funkciniais ry\f0\cchs186 \'f0\f0\cchs186 iais susij\f0\cchs186 \'e6\f0\cchs186 elementai sukuria palaikan\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'e0\f0\cchs186 aplink\f0\cchs186 \'e0 \f0\cchs186 vienas kito veikimui, o tai savo ruo\f0\cchs186 \'fe\f0\cchs186 tu suma\f0\cchs186 \'fe\f0\cchs186 ina atsitiktinum\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 tiesiogi\-\cs44 niam \cs49 ugdymui, t.y. skatina gabaus vaiko saviugd\f0\cchs186 \'e0\f0\cchs186 .\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelio artimiausioji funkcionavimo aplinka yra \f0\cchs186 \'f0\f0\cchs186 vietimo sistema.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis yra atviras ir dinami\f0\cchs186 \'f0\f0\cchs186 kas. Atviras, nes tai yra socialin\f0\cchs186 \'eb\f0\cchs186 strukt\f0\cchs186 \'fb\f0\cchs186 ra, kuriai \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 daro aplinka (netgi jo veikimo realyb\f0\cchs186 \'eb\f0\cchs186 je prasme). Modelio struk\-t\f0\cchs186 \'fb\f0\cchs186 riniai elementai turi daug vidini\f0\cchs186 \'f8\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 , o jie savo ruo\f0\cchs186 \'fe\f0\cchs186 tu yra atviri aplinkai, kitoms, i\f0\cchs186 \'f0\f0\cchs186 orin\f0\cchs186 \'eb\f0\cchs186 ms socialin\f0\cchs186 \'eb\f0\cchs186 ms strukt\f0\cchs186 \'fb\f0\cchs186 roms, sistemoms, yra dinami\f0\cchs186 \'f0\f0\cchs186 ki, nes i\f0\cchs186 \'f0\f0\cchs186 likti stati\f0\cchs186 \'f0\f0\cchs186 kam, kai kinta aplinka, n\f0\cchs186 \'eb\f0\cchs186 ra \f0\cchs186 \'e1\f0\cchs186 manoma. Dinami\f0\cchs186 \'f0\f0\cchs186 kas jis ir d\f0\cchs186 \'eb\f0\cchs186 l k\f0\cchs186 \'ab\'a9\f0\cchs186 $}\pAv \pard \plain \s11\qj\li0\fi0\ri0{\sl-240\slmult0\fs20\par }{\sl-240\slmult0\fs20\par }\sb121\sa0\sl-263\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Intrapersona-linis\chftn{\footnote\pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 \chftn Pastaba. Interpersonalinio ir intrapersonalinio \cs48\b\fs20 lygmens \cs55\b0\fs22 elemcr\cs48\b\f0\cchs186\fs20 \'a3\f0\cchs186 E\cs52\b0\expndtw-20\fs30 ^^PK\cs48\b\expndtw0\fs20 ^niaj\par \pard \plain \s13 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 modelio elementai, kuri\f0\cchs186 \'f8\f0\cchs186 optimaliam veikimui \cs49 ir skirtas ug\strike dy\strike0 m\strike o\strike0 \cs55 s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 \cs60\fs20 mo\-\cs55\fs22 delis\par \pard \plain \s23 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Sukurtasis \expndtw0 GAVUS\expndtw-20 modelis turi savo strukt\f0\cchs186 \'fb\f0\cchs186 r\f0\cchs186 \'e0\f0\cchs186 , funkcijas \cs53\expndtw-10 ir \cs63\expndtw0 funkcionavimo\expndtw-20 \expndtw0 aptin-\cs53\expndtw-10 k\f0\cchs186 \'e0\f0\cchs186 . \cs63\expndtw-20 Modelis turi \expndtw0 paskirti\expndtw-20 bendr\f0\cchs186 \'e0\f0\cchs186 tiksl\f0\cchs186 \'e0\f0\cchs186 \f0\cchs186 \'97\f0\cchs186 \cs49\i0\expndtw0 sudaryti s\f0\cchs186 \'e0\f0\cchs186 lygas gabiems valkams, nepriklausomai nuo j\f0\cchs186 \'f8\f0\cchs186 socialin\f0\cchs186 \'eb\f0\cchs186 s pad\f0\cchs186 \'eb\f0\cchs186 ties, gyvenamosios vietos, am\-\f0\cchs186 \'fe\f0\cchs186 iaus, lyties ir kt., rinktis j\f0\cchs186 \'f8\f0\cchs186 poreikius atitinkanti ugdym\f0\cchs186 \'e0\f0\cchs186 ir galimybes saviugdai, pad\f0\cchs186 \'eb\f0\cchs186 ti jam ir skatinti vaik\f0\cchs186 \'e0\f0\cchs186 siekti pilno savojo gabum\f0\cchs186 \'f8\f0\cchs186 po\-tencialo realizavimo ir b\f0\cchs186 \'fb\f0\cchs186 ti naudingam visuomenei, Sis tikslas suteikia modeliui vienov\f0\cchs186 \'eb\f0\cchs186 s, vientisumo.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Kiekvienas strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas turi ir papildom\f0\cchs186 \'f8\f0\cchs186 (i\f0\cchs186 \'f0\f0\cchs186 vestini\f0\cchs186 \'f8\f0\cchs186 i\f0\cchs186 \'f0\f0\cchs186 ben\-drojo) tiksl\f0\cchs186 \'f8\f0\cchs186 , kurie susij\f0\cchs186 \'e6\f0\cchs186 su funkcijomis, kurias atlieka strukt\f0\cchs186 \'fb\f0\cchs186 rinis elementas. Modelis skirtas \v0\cchs186 \'fe\f0\cchs186 mogui, jame vyksta informacijos perdavimo ir valdymo pro\-cesai \f0\cchs064 \'97\f0\cchs186 tai b\f0\cchs186 \'fb\f0\cchs186 dinga visuomenin\f0\cchs186 \'eb\f0\cchs186 ms sistemoms.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis sudarytas i\f0\cchs186 \'f0\f0\cchs186 posistemi\f0\cchs186 \'f8\f0\cchs186 (pavyzd\f0\cchs186 \'fe\f0\cchs186 iui, GVU atskiroje ugdymo institucijoje, jo posistem\f0\cchs186 \'eb\f0\cchs186 - pedagogin\f0\cchs186 \'eb\f0\cchs186 sistema, ir kt.). Visi GAVUS elementai yra vienaip ar kitaip susij\f0\cchs186 \'e6\f0\cchs186 su ugdymu ir jo funkcijomis: \f0\cchs186 \'f0\f0\cchs186 vietimu, lavinimu, aukl\f0\cchs186 \'eb\f0\cchs186 jimu, mokymu, globojimu, formavimu ir kt. Kiekviena jo sudf0\cchs186 \'eb\f0\cchs186 tin\f0\cchs186 \'eb\f0\cchs186 dalis atlieka tam tikr\f0\cchs186 \'e0\f0\cchs186 funkcij\f0\cchs186 \'e0\f0\cchs186 (jas nurod\f0\cchs186 \'eb\f0\cchs186 me aptardami model\f0\cchs186 \'e1\f0\cchs186 ). Tuomet, kai mo\-delio strukt\f0\cchs186 \'fb\f0\cchs186 riniai elementai funkcionuoja visuose ugdymo realyb\f0\cchs186 \'eb\f0\cchs186 s lygmeny\-se, jis apima daugel\f0\cchs186 \'e1\f0\cchs186 aplinkos veiksni\f0\cchs186 \'f8\f0\cchs186 , kurie yra gabumo virsmo pasiekimais katalizatoriai. Funkciniais ry\f0\cchs186 \'f0\f0\cchs186 iais susij\f0\cchs186 \'e6\f0\cchs186 elementai sukuria palaikan\f0\cchs186 \'e8\f0\cchs186 i\f0\cchs186 \'e0\f0\cchs186 aplink\f0\cchs186 \'e0 \f0\cchs186 vienas kito vei{imui, o tai savo ruo\f0\cchs186 \'fe\f0\cchs186 tu suma\f0\cchs186 \'fe\f0\cchs186 ina atsitiktinum\f0\cchs186 \'f8\f0\cchs186 \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 tiesiogi\-\cs44 niam \cs49 ugdymui, t.y. skatina gabaus vaiko saviugd\f0\cchs186 \'e0\f0\cchs186 .\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelio artimiausioji funkcionavimo aplinka yra \f0\cchs186 \'f0\f0\cchs186 vietimo sistema.\par \pard \plain \s23 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Modelis yra atviras ir dinami\f0\cchs186 \'f0\f0\cchs186 kas. Atviras, nes tai yra socialin\f0\cchs186 \'eb\f0\cchs186 strukt\f0\cchs186 \'fb\f0\cchs186 ra, kuriai \f0\cchs186 \'e1\f0\cchs186 tak\f0\cchs186 \'e0\f0\cchs186 daro aplinka (netgi jo veikimo realyb\f0\cchs186 \'eb\f0\cchs186 je prasme). Modelio struk\-t\f0\cchs186 \'fb\f0\cchs186 riniai elementai turi daug vidini\f0\cchs186 \'f8\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 i\f0\cchs186 \'f8\f0\cchs186 , o jie savo ruo\f0\cchs186 \'fe\f0\cchs186 tu yra atviri aplinkai, kitoms, i\f0\cchs186 \'f0\f0\cchs186 orin\f0\cchs186 \'eb\f0\cchs186 ms socialin\f0\cchs186 \'eb\f0\cchs186 ms strukt\f0\cchs186 \'fb\f0\cchs186 roms, sistemoms, yra dinami\f0\cchs186 \'f0\f0\cchs186 ki, nes i\f0\cchs186 \'f0\f0\cchs186 likti stati\f0\cchs186 \'f0\f0\cchs186 kam, kai kinta aplinka, n\f0\cchs186 \'eb\f0\cchs186 ra \f0\cchs186 \'e1\f0\cchs186 manoma. Dinami\f0\cchs186 \'f0\f0\cchs186 kas jis ir d\f0\cchs186 \'eb\f0\cchs186 l k\f0\cchs186 \'ab\'a9\f0\cchs186 $}\par \sect\sectd \sbknone\pgwsxn20126\pghsxn13892\marglsxn733\margrsxn360\margtsxn360\margbsxn360\cols1\colsx60 {\header }{\footer \pard \plain \s27\qr\li0\fi0\ri0\sb0\sa0 \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 {\field{\*\fldinst{PAGE}}{\fldrslt 123}}\par }{\pard\plain \sb1144\sa0\sl-240\slmult0\fs20\par}\pard \plain \s29\qj\li11181\fi0\ri0\sb51\sa102 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 4. \cs55 Gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ufidymo ir jo s\f0\cchs186 \'e0\f0\cchs186 lyg\f0\cchs186 \'f8\f0\cchs186 mo\ul delio rai\f0\cchs186 \'f0\f0\cchs186 kos\ul0 \cs45\b\expndtw-10\f0\cchs186 \'c1\f0\cchs186 \cs55\b0\ul\expndtw0 jetuvo\f0\cchs186 \'e1\f0\cchs186 e \cs60\fs20 pristatymas\par \sect\sectd \sbknone\pgwsxn20126\pghsxn13892\marglsxn733\margrsxn453\margtsxn360\margbsxn360\cols2\colno1\colw8123\colsr2431\colno2\colw8385 {\shpgrp{\*\shpinst \shpleft10622\shptop263\shpright18737\shpbottom1966\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr1\shpz7\shplid7{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 107315}}{\sp{\sn dyWrapDistBottom}{\sv 48260}}{\sp{\sn groupLeft}{\sv 12045}}{\sp{\sn groupTop}{\sv 2846}}{\sp{\sn groupRight}{\sv 20160}}{\sp{\sn groupBottom}{\sv 4549}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 12045}}{\sp{\sn relTop}{\sv 2922}}{\sp{\sn relRight}{\sv 20160}}{\sp{\sn relBottom}{\sv 4100}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx542 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx6666 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7378 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8115 \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Nr.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0\sl-144\slmult0\tlhyph\tx3744\tlul\tx4574 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn2\f0\cchs186\lang1063\langfe1063\fs22 rr-ri{\charscalex100\expndtw0\tab }\cs61\fs12 _ {\charscalex100\expndtw0\tab } J \f0\cchs186 \'bb\par \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Teiginys \f0\cchs186 \'97\cell \pard \plain \s35\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 mreies\par \pard \plain \s3\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Vid *\cell \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 t\f0\cchs186 \'e6\f0\cchs186 sinys\par \pard \plain \s24\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs61\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs12 Qt \cs60\fs20 n\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx542 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx6666 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7378 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8115 \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 11.\cell \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 Tr\f0\cchs186 \'fb\f0\cchs186 ksta mokini\f0\cchs186 \'f8\f0\cchs186 t\f0\cchs186 \'eb\f0\cchs186 v\f0\cchs1:6 \'f8\f0\cchs186 palaikymo, pritarimo\cell \pard \plain \s5\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 00\cs49\fs22 .24\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.21\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx542 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx6666 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7378 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8115 \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 12.\cell \pard \plain \s35\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 [Tr\f0\cchs186 \'fb\f0\cchs186 ksta mokyklos administracijos paskatinimo ir \cs57\expndtw10\fs16 nri\cs58\expndtw0\fs20 -^mn\par \pard \plain \s15\ql\li0\fi0\ri0\sb0\sa0\tlhyph\tx5472\tlhyph\tx6107 \intbl \cs58\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 maksimalus \cs60\b0 galimas trukume .v\cs57\b\expndtw10\fs16 .-rr.\cs59\i\expndtw-10\f9\cchs186\fs22 ^-ETrr\cs60\b0\i0\expndtw0\f0\cchs186\fs20 {\charscalex100\expndtw0\tab }rr{\charscalex100\expndtw0\tab }1\cell \pard \plain \s5\qr\li0\fi0\ri0\sb0\sa0 \intbl \cs60\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs20 00\cs49\fs22 .41\cel \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.22\cell \pard\intbl\row \pard}}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 18025}}{\sp{\sn relTop}{\sv 2846}}{\sp{\sn relRight}{\sv 20152}}{\sp{\sn relBottom}{\sv 3117}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}vs\n\{s\{p{ }1s} fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s11\ql\li0\fi0\ri0\sb0\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 4.2.3 lentel\f0\cchs186 \'eb\f0\cchs186 s t\f0\cchs186 \'e6\f0\cchs186 sinys\par }}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 12629}}{\sp{\sn relTop}{\sv 4074}}{\sp{\sn relRight}{\sv 20100}}{\sp{\sn relBottom}{\sv 4549}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s22\ql\li0\fi2821\ri0\sb0\sa0\sl-161\slmult0\tlhyph\tx3456\tldot\tx3812 \cs62\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs18 _ ,{\charscalex100\expndtw0\tab }{\charscalex100\expndtw0\tab }.\f0\cchs186 \'84\'ab\f0\cchs186 , , icigu \expndtw20 trukumoexpndtw0 \cs55fs22 visi\f0\cchs186 \'f0\f0\cchs186 kai nejau\f0\cchs186 -\line \'e8\f0\cchs186 iama \f0\cchs186 \'97\f0\cchs186 vertinimas \cs49\f0\cchs186 \'84\f0\cchs186 -2".\par }}}}}{\shpgrp{\*\shpinst \shpleft-373\shptop6683\shpright8098\shpbottom12511\shpfhdr0\shpfblwtxt0\shpbxmargin\shpbypara\shpwr2\shpwrk3\shpz8\shplid8{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}{\sp{\sn fAllowOverlap}{\sv 1}}{\sp{\sn dxWrapDistLeft}{\sv 21590}}{\sp{\sn dxWrapDistRight}{\sv 21590}}{\sp{\sn dyWrapDistTop}{\sv 0}}{\sp{\sn dyWrapDistBottom}{\sv 0}}{\sp{\sn groupLeft}{\sv 1050}}{\sp{\sn groupTop}{\sv 9267}}{\sp{\sn groupRight}{\sv 9521}}{\sp{\sn groupBottom}{\sv 15095}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 1050}}{\sp{\sn relTop}{\sv 10275}}{\sp{\sn relRight}{\sv 9521}}{\sp{\sn relBottom}{\sv 15095}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdr15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li246\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Nr\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\strike0\nosupersub\scaps0\chrlex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Teiginys\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Vid.*\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 St. n.\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1 \super 1\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta u\f0\cchs186 \'fe\f0\cchs186 mokes\f0\cchs186 \'e8\f0\cchs186 io u\f0\cchs186 \'fe\f0\cchs186 \cs56\fs18 papildom\f0\cchs186 \'e0\f0\cchs186 \cs55\fs22 darb\f0\cchs186 \'e0\f0\cchs186 ,.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.43\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.84\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 12.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta materialinio paskatinimo itin gabiems mokiniams.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.35\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.87\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 13.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-288\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta bendros itin gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo politikos visos i\f0\cchs186 \'f0\f0\cchs186 liet \cs52\expndtw-20\fs30 j \cs44\expndtw0\fs22 mastu.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.27\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.85\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 14.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 [Tr\f0\cchs186 \'fb\f0\cchs186 ksta apr\f0\cchs186 \'fb\f0\cchs186 pinimo reikalinga mokymo metodine med\f0\cchs186 \'fe\f0\cchs186 iaga\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.22\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.96\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 15.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-296\slmult0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta kvalifikacijos k\f0\cchs186 \'eb\f0\cchs186 limo kurs\f0\cchs186 \'f8\f0\cchs186 itin gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo \cs44 tems.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1\cs49 .20\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.91\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrsbrdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s30\ql\li0\fi0\ri0\sb0\sa0\sl-407\slmult0 \intbl \cs52\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw-20\up2\f0\cchs186\lang1063\langfe1063\fs30 j \cs44\expndtw0\fs22 6. \cs55 j\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-313\slmult0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Tr\f0\cchs186 \'fb\f0\cchs186 ksta \cs55 bendradarbiavimo tu auk\f0\cchs186 \'f0\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 mokykl\f0\cchs186 \'f8\f0\cchs186 d\f0\cchs186 \'eb\f0\cchs186 stytojais, \cs44 mokalininkaif.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1\cs49 .04\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.99\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0\sl-313\slmult0 \intbl \cs44\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 7. \cs55 1 \cs44 Tr\f0\cchs186 \'fb\f0\cchs186 ksta literatu \expndtw-20 rot\expndtw0 \cs54\i\expndtw-20 apie itin \cs55\i0\expndtw0 gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 pa\f0\cchs186 \'fe\f0\cchs186 inim\f0\cchs186 \'e0\f0\cchs186 , ugdym\f0\cchs186 \'e0\f0\cchs186 , \cs52\expndtw-20\fs30 j \cs55\expndtw0\fs22 psichologij\f0\cchs186 \'e0\f0\cchs186 , \cs44 kir\f0\cchs186 \'f8\f0\cchs186 \cs55\f0\cchs186 \'f0\f0\cchs186 ali\f0\cchs186 \'f8\f0\cchs186 patirt j.\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1\cs49 .00\cell \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.97\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 8. \cs55 j Tr\f0\cchs186 \'fb\f0\cchs186 ksta \cs44 bendradarbiavimo \cs55 su patyrusiais \f0\cchs186 \'f0\f0\cchs186 ioje srityje kolegomis,\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.88\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.02\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s32\ql\li0\fi0\ri0\sb0\sa0\sl-356\slmult0 \intbl \cs52\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw-20\dn4\f0\cchs186\lang1063\langfe1063\fs30 1 \cs49\expndtw0\fs22 1\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtu0\dn0\f0\cchs186\lang1063\langfe1063\fs22 'r\f0\cchs186 \'fb\f0\cchs186 ksta \cs44 tinkamo \cs55 pasirengimo auk\f0\cchs186 \'f0\f0\cchs186 tojoje mokykloje.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 0.56\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.17\cell \pard\intbl\row \trowd\trgaph40 \trrh0 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx661 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7014 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx7751 \clvertalt\clbrdrt\brdrs\brdrw15\clbrdrl\brdrs\brdrw15\clbrdrb\brdrs\brdrw15\clbrdrr\brdrs\brdrw15\cltxlrtb\cellx8471 \pard \plain \s5\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 10. 7\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 r\f0\cchs186 \'fb\f0\cchs186 ksta galimybi\f0\cchs186 \'f8\f0\cchs186 \cs44 naudotis \cs55 kompiuteriu ir internetu.\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 -0.19\cell \pard \plain \s3\ql\li0\fi0\ri0\sb0\sa0 \intbl \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 1.33\cell \pard\intbl\row \pard}}}{\shp {\*\shpinst \shplid1{\sp{\sn relLeft}{\sv 2151}}{\sp{\sn relTop}{\sv 9267}}{\sp{\sn relRight}{\sv 8724}}{\sp{\sn relBottom}{\sv 10300}}{\sp{\sn fRelFlipH}{\sv 0}}{\sp{\sn fRelFlipV}{\sv 0}}{\sp{\sn shapeType}{\sv 202}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fLine}{\sv 1}}{\sp{\sn lineWidth}{\sv 0}}{\sp{\sn lineColor}{\sv 16777215}}{\sp{\sn fPrint}{\sv 1}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fEditedWrap}{\sv 0}}{\sp{\sn txflTextFlow}{\sv 0}}{\sp{\sn dxTextLeft}{\sv 0}}{\sp{\sn dyTextTop}{\sv 0}}{\sp{\sn dxTextRight}{\sv 0}}{\sp{\sn dyTextBottom}{\sv 0}}{\sp{\sn fFitTextToShape}{\sv 0}}{\shptxt \pard \plain \s2\qj\li0\fi0\ri0\sb0\sa0\sl-330\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Duomenys apie tai, ko mokytojams tr\f0\cchs186 \'fb\f0\cchs186 ksta darbui su itin\par \pard \plain \s20\ql\li0\fi2406\ri0\sb0\sa0\sl-330\slmult0\tlul\tx805 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 gabiais vaikais\line \lang1033 {\charscalex100\expndtw0\tab }\ul\lang1063 (Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , Janilionis,\ul0 Almonaitien\f0\cchs186 \'eb\f0\cchs186 , \cs49 2002)\par }}}}}\pard \plain \s11\qj\li0\fi0\ri0\sb0\sa0\sl-322\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 niams, galima manyti, kad jaunesni\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 klasi\f0\cchs186 \'f8\f0\cchs186 gabi\f0\cchs186 \'f8\f0\cchs186 mokini\fcchs186 \'f8\f0\cchs186 ugdymo rezulta\-tai \f0\cchs186\'fe\f0\cchs186 inomi ir fiksuojami tik klases ir mokyklos (atskirais atvejais savivaldyb\f0\cchs186 \'eb\f0\cchs186 s) lygmeniu. be to, olimpiad\f0\cchs186 \'f8\f0\cchs186 rezultatai - tai tik pasiekimai, \cs49 o \cs55 kas daroma klas\f0\cchs186 \'eb\-\f0\cchs186 je, \cs53\i\expndtw-10 mokykloje, \cs55\i0\expndtw0 kad tie pasiekimai b\f0\cchs186 \'fb\f0\cchs186 t\f0\cchs186 \'f8\f0\cchs186 tokie, ir \cs49 ar \cs55 tie pasiekimai \f0\cchs186 \'97\f0\cchs186 tai mokytojo ir mokinio darbo rezultatas ar tik mokinio potencialo \{vertinimas, informaci\-jos taip pat neturime arba turime labai nedaug \cs49 (\f0\cchs186 \'fe\f0\cchs186 r. \cs55 Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , \cs49 1997,1998, \cs55 2003, Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , Janilionis, Almonaitien\f0\cchs186 \'eb\f0\cchs186 , \cs49 2002).\par \pard \plain \s2\qj\li0\fi576\ri0\sb0\sa0\sl-322\slmult0 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Mokytoj\f0\cchs186 \'f8\f0\cchs186 rengimas. \cs55\i0\expndtw0 N\f0\cchs186 \'eb\f0\cchs186 vienas Lietuvos universitetas, rengiantis mokyto\-jus, nesi\f0\cchs186 \'fb\f0\cchs186 lo pirmos ar antros pakopos studij\f0\cchs186 \'f8\f0\cchs186 programos, kurios paskirtis b\f0\cchs186 \'fb\f0\cchs186 t\f0\cchs186 \'f8 \f0\cchs186 ai\f0\cchs186 \'f0\f0\cchs186 kiai orientuota \f0cchs186 \'e1\f0\cchs186 gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo specialisto parengim\f0\cchs186 \'e0\f0\cchs186 . Per\f0\cchs186 \'fe\f0\cchs186 i\f0\cchs186 \'fb\f0\cchs186 r\f0\cchs186 \'eb\f0\cchs186 jus mokytoj\f0\cchs186 \'f8\f0\cchs186 rengimo programas Vilniaus pedagginiame, \f0\cchs186 \'d0\f0\cchs186 iauli\f0\cchs186 \'f8\f0\cchs186 , Kauno tech\-nologijos bei Vytauto Did\f0\cchs186 \'fe\f0\cchs186 iojo universitetuose, rasti tik du, be to, tik \cs63\i\expndtw-20 pasiren\-kamieji \cs55\i0\expndtw0 gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 problemoms skirti moduliai. Tai Vilniaus pedagoginiame universitete neakivaizdininkams \cs63\i\expndtw-20 si\f0\cchs186 \'fb\f0\cchs186 lomas \cs55\i0\expndtw0 modulis \f0\cchs186 \'84\f0\cchs186 Gabi\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 atpa\f0\cchs186 \'fe\f0\cchs186 inimas ir ugdymo galimyb\f0\cchs186 \'eb\f0\cchs186 s" bei \f0\cchs186 \'d0\f0\cchs186 iauli\f0\cchs186 \'f8\f0\cchs186 pedagoginiame universitete si\f0\cchs186 \'fb\f0\cchs186 lomas modulis \f0\cchs186 \'84\f0\cchs186 Gabi\f0\cchs186 \'f8\f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 psichologija".\par \pard \plain \s23\qj\li0\fi576\ri0\sb8\sa0\sl-322\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Lietuvos mokytojams, \cs49 tyrim\f0\cchs186 \'f8\f0\cchs186 duomenimis (Narkevi\f0\cchs186 \'e8\f0\cchs186 ien\f0\cchs186 \'eb\f0\cchs186 , \cs55 Janilionis, \cs49 Almonaitien\f0\cchs186 \'eb\f0\cchs186 , \cs55 2002), darbui su \cs49 gabiais vaikais tr\f0\cchs186 \'fb\f0\cchs186 ksta \cs55 ir tinkamo pasirengimo auk\f0\cchs186 \'f0\f0\cchs186 tojoje \cs49 mokykloje, ir kir\f0\cchs186 \'f8\f0\cchs186 \cs55 dalyk\f0\cchs186 \'f8\f0\cchs186 \cs49 (\f0\cchs186 \'fe\f0\cchs186 r. 4.2.3 lentel\f0\cchs186 \'e6\f0\cchs186 ).\par \pard \plain \s11\qr\li0\fi0\ri0{\sl-240\slmult0\fs20\p`r }\sb65\sa0 \cs49\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 4.2.3 \cs55 lentel\f0\cchs186 \'eb\par \pard \plain \s29\ql\li0\fi568\ri0\sb0\sa0\sl-722\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Lentel\f0\cchs186 \'eb\f0\cchs186 je teiginiai pateikti eil\f0\cchs186 \'eb\f0\cchs186 s tvarka pagal tr\f0\cchs186 \'fb\f0\cchs186 kumo \f0\cchs186 \'e1\f0\cchs186 vertinimo vidur\-k\f0\cchs186 \'e1\f0\cchs186 . Matome, jog labiausiai, mokytoj\f0\cchs186 \'f8\f0\cchs186 nuomone, tr\f0\cchs186 \'fb\f0\cchs186 ksta u\f0\cchs186 \'fe\f0\cchs186 mokes\f0\cchs186 \'e8\f0\cchs186 io u\f0\cchs186 \'fe\f0\cchs186 papil\-dom\f0\cchs186 \'e0\f0\cchs186 darb\f0\cchs186 \'e0\f0\cchs186 , materialinio paskatinimo gabiems vaikams ir bendros gabi\f0\cchs186 \'f8\f0\cchs186 vai\-k\f0\cchs186 \'f8\f0\cchs186 ugdymo politikos visos \f0\cchs186 \'f0\f0\cchs186 alies mastu. Su pirmu teiginiu visi\f0\cchs186 \'f0\f0\cchs186 kai sutiko \cs49 59%, \cs55 sutiko \cs49 30% \cs55 (t.y. i\f0\cchs186 \'f0\f0\cchs186 viso taip teig\f0\cchs186 \'eb\f0\cchs186 \cs49 89%) \cs55 mokytoj\f0\cchs186 \'f8\f0\cchs186 , dar \cs49 7% \cs55 renkasi neutrali\f0\cchs186 \'e0 \f0\cchs186 pozicij\f0\cchs186 \'e0\f0\cchs186 . \cs49 88% \cs55 mokytoj\f0\cchs186 \'f8\f0\cchs186 mano, jog tr\f0\cchs186 \'fb\f0\cchs186 ksta materialinio paskatinimo patiems gabiems mokiniams. \cs49 87% \cs55 respondent\f0\cchs186 \'f8\f0\cchs186 mano, kad tr\f0\cchs186 \'fb\f0\cchs186 ksta bendros itin gabi\f0\cchs186 \'f8 \f0\cchs186 vaik\f0\cchs186 \'f8\f0\cchs186 ugdymo politikos \f0\cchs186 \'d0\f0\cchs186 alies mastu; \cs49 84% \cs55 - apr\f0\cchs186 \'fb\f0\cchs186 pinimo mokymo metodi\-ne med\f0\cchs186 \'fe\f0\cchs186 iaga; \cs49 86% \cs55 - kvalifikacijos k\f0\cchs186 \'eb\f0\cchs186 limo kurs\f0\cchs186 \'f8\f0\cchs186 , \cs49 79% \cs55 - bendradarbiavimo su mokslininkais; \cs49 76% \cs55 - atitinkamos literat\f0\cchs186 \'fb\f0\cchs186 ras; \cs49 74% \cs55 - bendradarbiavimo su patyrusiais \f0\cchs186 \'f0\f0\cchs186 ioje srityje kolegomis (neutralus vertinimas - \cs49 14%). \cs55 Tinkamo pasirengimo auk\f0\cchs186 \'f0\f0\cchs186 tojoje mokykloje pasigedo \cs49 60% \cs55 apklaust\f0\cchs186 \'f8\f0\cchs186 j\f0\cchs186 \'f8\f0\cchs186 mokytoj\f0\cchs186 \'f8\f0\cchs186 , tik penktadalis \cs49 (21%) \cs55 j\f0\cchs186 \'f8\f0\cchs186 sutiko, jog auk\f0\cchs186 \'f0\f0\cchs186 toji mokykla pareng\f0\cchs186 \'eb\f0\cchs186 j\f0\cchs186 \'e1\f0\cchs186 /j\f0\cchs186 \'e0\f0\cchs186 \f0\cchs186 \'f0\f0\cchs186 iam darbui. Malonu pasteb\f0\cchs186 \'eb\f0\cchs186 ti, jog \cs49 56% \cs55 mokytoj\f0\cchs186 \'f8\f0\cchs186 darbui su itin gabiais vaikais \expndtw-20 yra\expndtw0 skatina\-mi ir palaikomi mokyklos administracijos (neutralum\f0\cchs186 \'e0\f0\cchs186 vertinant teigin\f0\cchs186 \'e1\f0\cchs186 rinko\-si \cs49 18%). \cs55 Nema\f0\cchs186 \'fe\f0\cchs186 ai mokytoj\f0\cchs186 \'f8\f0\cchs186 turi galimybi\f0\cchs186 \'f8\f0\cchs186 naudotis kompiuteriu ir internetu \cs49 (49% \cs55 nejau\f0\cchs186 \'e8\f0\cchs186 ia tr\f0\cchs186 \'fb\f0\cchs186 kumo, \cs49 16% \cs55 lieka neutral\f0\cchs186 \'fb\f0\cchs186 s, \cs49 35% \cs55 tr\f0\cchs186 \'fb\f0\cchs186 ksta tokios galimybes). \cs49 46% \cs55 mokytoj\f0\cchs186 \'f8\f0\cchs186 jau\f0\cchs186 \'e8\f0\cchs186 ia t\f0\cchs186 \'eb\f0\cchs186 v\f0\cchs186 \'f8\f0\cchs186 palaikym\f0\cchs186 \'e0\f0\cchs186 , \cs49 31% \cs55 tokio palaikymo pasigenda.\par \pard \plain \s17\ql\li0\fi0\ri0\sb0\sa0\sl-322\slmult0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 Anketoje buvo palikta vieta laisvam atsakymui, ko \cs64\b\expndtw-20\fs26 dar tr\f0\cchs186 \'fb\f0\cchs186 ksta, \cs55\b0\expndtw0\f0\cchs186\fs22 \'e1\f0\cchs186 ra\f0\cchs186 \'f0\f0\cchs186 yti. Pa\-min\f0\cchs186 \'eb\f0\cchs186 tini tokie dalykai, kuri\f0\cchs186 \'f8\f0\cchs186 mokytojai nurod\f0\cchs186 \'eb\f0\cchs186 pasigendantys (kalba netaisyta): \cs63\i\expndtw-20 d\f0\cchs186 \'eb\f0\cchs186 mesio, sistemos Siame darbe; \f0\cchs186 \'e1\f0\cchs186 d\f0\cchs186 \'eb\f0\cchs186 jimu \f0\cchs186 \'e1\f0\cchs186 J\f0\cchs186 \'e1\f0\cchs186 darini plali\f0\cchs186 \'e0\f0\cchs186 ja prasme; pa$d laikmet\f0\cchs186 \'e1 \f0\cchs186 apr\f0\cchs186 \'fb\f0\cchs186 pinto kabineto; lenko; &bi\f0\cchs186 \'f8\f0\cchs186 mokini\f0\cchs186 \'f8\f0\cchs186 su ffra mokymosi motyvacija; skiriam\f0\cchs186 \'e0 \f0\cchs186 papildomai pamoki\f0\cchs186 \'e1\f0\cchs186 mokytojai - olimpiadoms ruo\f0\cchs186 \'f0\f0\cchs186 tis; materialin\f0\cchs186 \'eb\f0\cchs186 s bas\f0\cchs186 \'e6\f0\cchs186 s, ma&u* mokint\f0\cchs186 \'e0\f0\cchs186 skaiiiaus klas\f0\cchs186 \'eb\f0\cchs186 je, nes bana labai sunku diferencijuotai dirbti, meni nesp\f0\cchs186 \'eb\f0\cchs186 ja, kiti neturi k\f0\cchs186 \'e0\f0\cchs186 neikti, vadov\f0\cchs186 \'eb\f0\cchs186 liuose dainai n\f0\cchs186 \'eb\f0\cchs186 ra tinkam\f0\cchs186 \'e0\f0\cchs186 nf\f0\cchs186 \'eb\f0\cchs186 eoti\f0\cchs186 \'e0\f0\cchs186 ; dau\f0\cchs186 \'fe\f0\cchs186 tu stovykl\f0\cchs186 \'f8 \sub\f0\cchs186 ga\nosupersub /,iems tankiniam respublikos mastu, bet kad \f0\cchs186 \'e1\f0\cchs186 jos patekt\f0\cchs186 \'f8\f0\cchs186 irprmncijos vaikai, \expndtw0 o\expndtw-20 \expndtw0 neHk\expndtw-20 didf\f0\cchs186 \'e1\f0\cchs186 nj\f0\cchs186 \'f8\f0\cchs186 miest\f0\cchs186 \'f8\f0\cchs186 ; mokini\f0\achs186 \'f8\f0\cchs186 suinterrsmtama mokytis; laiko per pamokas m po pamnk\f0\cchs186 \'e0\f0\cchs186 ; bijau perkrauti mokinis nereikt\f0\cchs186 \'f8\f0\cchs186 niveliuoti \f0\cchs186 \'e1\f0\cchs186 tatna\f0\cchs186 \'f8\f0\cchs186 j/\f0\cchs186 \'f8\f0\cchs186 \expndtw0 irj\f0\cchs186 \'f8\expndtw-20\f0\cchs186 sukart\f0\cchs186 \'f8 \f0\cchs186 proffttm\f0\cchs186 \'f8\f0\cchs186 .\par \pard \plain \s34\qc\li0\fi0\ri0\sb102\sa0 \cs63\b0\strike0\nosupersub\i\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs22 Apilmidrinamosios i\f0\cchs186 \'f0\f0\cchs186 vados\par \pard \plain \s29\ql\li584\fi0\ri0\sb110\sa0 \cs64\i0\strike0\nosupersub\b\scaps0\charscalex100\expndtw-20\dn0\f0\cchs186\lang1063\langfe1063\fs26 Tiriant GAVUS \cs55\b0\expndtw0\fs22 modelio rai\f0\cchs186 \'f0\f0\cchs186 k\f0\cchs186 \'e0\f0\cchs186 visuomeniniame lygmenyje, i\f0\cchs186 \'f0\f0\cchs186 ry\f0\cchs186 \'f0\f0\cchs186 k\f0\cchs186 \'eb\f0\cchs186 jo\par \pard \plain \s11\ql\li0\fi0\ri0\sb102\sa0 \cs55\b0\i0\strike0\nosupersub\scaps0\charscalex100\expndtw0\dn0\f0\cchs186\lang1063\langfe1063\fs22 tokios problemos:\par } diff --git a/vcl/qa/cppunit/pdfexport/data/form-font-name.odt b/vcl/qa/cppunit/pdfexport/data/form-font-name.odt new file mode 100644 index 0000000000..a7430c9a8a Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/form-font-name.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/formcontrol.fodt b/vcl/qa/cppunit/pdfexport/data/formcontrol.fodt new file mode 100644 index 0000000000..f6ec845852 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/formcontrol.fodt @@ -0,0 +1,192 @@ + + + 2023-04-03T17:28:30.0316987822023-04-03T17:48:01.654889994PT19M34S3LibreOfficeDev/7.6.0.0.alpha0$Linux_X86_64 LibreOffice_project/581bc338cb60e9511c2f870acfbb7ec3593a582ddummy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + textuelle alternative + a box to check + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/grouped-shape.fodt b/vcl/qa/cppunit/pdfexport/data/grouped-shape.fodt new file mode 100644 index 0000000000..af506d9688 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/grouped-shape.fodt @@ -0,0 +1,213 @@ + + + Gabor Kelemen LO2023-04-19T23:36:32.1500000002023-07-20T19:34:33.405705509PT7M23S4LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/9c21d86f20871f2840fe390c5f365de48d48258aGrouped shapes a11y example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Two rectangles + Grouped + + + + + + + + these ones are green + + + + + + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/image-hyperlink-alttext.fodt b/vcl/qa/cppunit/pdfexport/data/image-hyperlink-alttext.fodt new file mode 100644 index 0000000000..211d3a7e5e --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/image-hyperlink-alttext.fodt @@ -0,0 +1,195 @@ + + + Gabor Kelemen LO2023-04-19T18:19:46.2880000002023-04-20T15:37:33.898000000Gabor Kelemen LOPT4H18M23S8LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/255ea355f14bdb3efd78f5cfada88c8ac0accfb8Ship image with hyperlink + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Image with hyperlink!description: + iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAANbY1E9YMgAAABl0 + RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFpSURBVHjaYvz//z8DtQBAADER + o+jjZGuibAQIICZiDOK/cgzFwEnrV/4HYXS1AAHERIxBR58yMiAb2DtzM1b1AAHERIxBIIBu + IDYAEEBMxBjE0bgdxcBL3vcZLl16jaEPIICYiDFIU9MSw8BeoeUYhgEEEBMxBnFx8WE1EN3L + AAHERIxBIECMgQABxAhKtPgM+vbtE9xmGP/69eMMP+o9wWLW0kD9OlYM/LlHGQECiAndoKg/ + USgGgTTmdS8C0yA+zIUgdeguBAggljtWdQwMVkDXACWMjd0ZXRun/Id5DWTA9C23GSaVxoEN + zISoARvoamnBYF2/hPHs2Z3/z0JdDhBADCBvIuPkhsn/QeDr14//QWwQjY0PVYeiFyCA8OaA + 3cdPoEQAiI8PAAQQEwMVAUAAsWATBAX0jx9fsWrAJQ4CAAGE1TBQwOMC9+9fwikHEEBYDQPF + IAzIe8TglEMHAAHESM2SFiDAADEwCe4BJwcYAAAAAElFTkSuQmCC + + + Ship drawing + Very cute + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/image-shape.fodt b/vcl/qa/cppunit/pdfexport/data/image-shape.fodt new file mode 100644 index 0000000000..a0bcfeb0eb --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/image-shape.fodt @@ -0,0 +1,141 @@ + + + Gabor Kelemen LO2022-10-12T16:49:07.1140000002022-11-18T15:28:13.568307995PT3M39S2LibreOfficeDev/7.5.0.0.alpha0$Linux_X86_64 LibreOffice_project/867afb8f1cc153fba2c28c85deedda74bd077cf0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is a blue... + ...rectangle + + + + iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAANbY1E9YMgAAABl0 + RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFpSURBVHjaYvz//z8DtQBAADER + o+jjZGuibAQIICZiDOK/cgzFwEnrV/4HYXS1AAHERIxBR58yMiAb2DtzM1b1AAHERIxBIIBu + IDYAEEBMxBjE0bgdxcBL3vcZLl16jaEPIICYiDFIU9MSw8BeoeUYhgEEEBMxBnFx8WE1EN3L + AAHERIxBIECMgQABxAhKtPgM+vbtE9xmGP/69eMMP+o9wWLW0kD9OlYM/LlHGQECiAndoKg/ + USgGgTTmdS8C0yA+zIUgdeguBAggljtWdQwMVkDXACWMjd0ZXRun/Id5DWTA9C23GSaVxoEN + zISoARvoamnBYF2/hPHs2Z3/z0JdDhBADCBvIuPkhsn/QeDr14//QWwQjY0PVYeiFyCA8OaA + 3cdPoEQAiI8PAAQQEwMVAUAAsWATBAX0jx9fsWrAJQ4CAAGE1TBQwOMC9+9fwikHEEBYDQPF + IAzIe8TglEMHAAHESM2SFiDAADEwCe4BJwcYAAAAAElFTkSuQmCC + + + Image of a house + nice drawing, isn't it? + He heard quiet steps behind him. That didn't bode well. + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/justified-arabic-kashida.odt b/vcl/qa/cppunit/pdfexport/data/justified-arabic-kashida.odt new file mode 100644 index 0000000000..6ca6ad1965 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/justified-arabic-kashida.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg b/vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg new file mode 100644 index 0000000000..1fad913e04 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/link-wrong-page-partial.odg differ diff --git a/vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp b/vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp new file mode 100644 index 0000000000..b6787aff66 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/link-wrong-page.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/master.odm b/vcl/qa/cppunit/pdfexport/data/master.odm new file mode 100644 index 0000000000..74016352b7 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/master.odm differ diff --git a/vcl/qa/cppunit/pdfexport/data/nestedsection.fodt b/vcl/qa/cppunit/pdfexport/data/nestedsection.fodt new file mode 100644 index 0000000000..ab743058f5 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/nestedsection.fodt @@ -0,0 +1,132 @@ + + + 2023-08-31T13:12:47.4788436062023-08-31T19:59:09.088439334PT5M46S6LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/f72e62cf27db17505de57abe93127f8b8d40eb292023-08-31T19:31:58.495592060PDF filestitle + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 2 + + 3 + + 4 + 5 + + 6 + + + diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg b/vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg new file mode 100644 index 0000000000..6dee0145c5 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/pdf-image-annots.odg differ diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg b/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg new file mode 100644 index 0000000000..aa0f89300b Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/pdf-image-hyperlink.odg differ diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf b/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf new file mode 100644 index 0000000000..739a80c476 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/pdf-image-resource-inline-xobject-ref.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf b/vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf new file mode 100644 index 0000000000..981ca32061 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/pdf-image-rotate-180.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/data/rectangles.pdf b/vcl/qa/cppunit/pdfexport/data/rectangles.pdf new file mode 100644 index 0000000000..6911d229aa --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/rectangles.pdf @@ -0,0 +1,54 @@ +%PDF-1.7 +% +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [0 0 200 300] + /Count 1 + /Kids [3 0 R] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R +>> +endobj +4 0 obj << + /Length 188 +>> +stream +q +0 0 0 rg +0 290 10 10 re B* +10 150 50 30 re B* +0 0 1 rg +190 290 10 10 re B* +70 232 50 30 re B* +0 1 0 rg +190 0 10 10 re B* +130 150 50 30 re B* +1 0 0 rg +0 0 10 10 re B* +70 67 50 30 re B* +Q +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000157 00000 n +0000000226 00000 n +trailer << + /Root 1 0 R + /Size 5 +>> +startxref +466 +%%EOF diff --git a/vcl/qa/cppunit/pdfexport/data/reduce-image.fodt b/vcl/qa/cppunit/pdfexport/data/reduce-image.fodt new file mode 100644 index 0000000000..b5737ae27e --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/reduce-image.fodt @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAABmJLR0QA/wD/AP+gvaeTAAAA + CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AEVDCUTfvEVdAAAAYhJREFUeNrt3bEJwzAQ + htFckjLreP8Bso5bc2lTpBDG4kfkvQUE5uNUGEnV3TdIufsECBABggARIAgQAYIAESAIEAGC + ABEgCBABggARIAgQAYIAESAIEAGCABEgCBABggARIHx7phZ+vF9D13Id217WXW9dExBbMAgQ + AYIAESAIEAGCABEgCBABIkAQIAIEASJAECAChKnq6hfTR88gsKarz46YgNiCESAIEAGCABEg + CBABwlSx27FStzHxW+oPlgmILRgBggARIAgQAYIAESAIEAGCABEgCBABggARIAgQAYIAESAI + EAGCABEgCBABggARIAgQAYIAESACBAEiQBAgAgQBIkAQIAIEASJAECACBAEiQBAgi4u9mJ56 + oRsTEASIAEGACBABggARIAiQP1LdmR8So39Cjm0v6663rgmILRgEiABBgAgQBIgAQYAIEASI + ABEgCBABggARIAgQAcJUsTMhYAIiQAQIAkSAIEAECAJEgCBABAgCRIAgQAQIAkSAIEAECKd9 + AEYENxB/sygQAAAAAElFTkSuQmCC + + + + diff --git a/vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt b/vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt new file mode 100644 index 0000000000..99ff22746e --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/reduce-small-image.fodt @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMklEQVR42mP4//8/AyWYYXAZ + wHSK+z8pbOoaAJIgBWM1gFh/jxqAxwCKYmHgE9KAZSYAhK3Dgc2FxfUAAAAASUVORK5CYII= + + + + diff --git a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf new file mode 100644 index 0000000000..fdda33f782 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf differ diff --git a/vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt b/vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt new file mode 100644 index 0000000000..ecd7795377 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/softhyphen_pdf.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/spanlist.fodt b/vcl/qa/cppunit/pdfexport/data/spanlist.fodt new file mode 100644 index 0000000000..31096c6ccf --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/spanlist.fodt @@ -0,0 +1,207 @@ + + + 2023-09-01T15:10:27.5024794962023-09-01T17:33:02.178300225PT15M42S6LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/f72e62cf27db17505de57abe93127f8b8d40eb29spans2023-09-01T17:30:16.229603024PDF files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The first item in the list, with about 2 lines of en-GB text + + + The second item in the listhas many linebreaks and ends on page 2 + + + The third item in the list does have a hyperlink and a footnote1 + footnote so it is 4 lines of en-GB text + + + item 4 has strikeout formatting on both lines + + + + + diff --git a/vcl/qa/cppunit/pdfexport/data/tdf103492.odt b/vcl/qa/cppunit/pdfexport/data/tdf103492.odt new file mode 100644 index 0000000000..88b8dc146f Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf103492.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105093.odp b/vcl/qa/cppunit/pdfexport/data/tdf105093.odp new file mode 100644 index 0000000000..82ce29cda0 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf105093.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105461.odp b/vcl/qa/cppunit/pdfexport/data/tdf105461.odp new file mode 100644 index 0000000000..9c86a3bd79 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf105461.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105954.odt b/vcl/qa/cppunit/pdfexport/data/tdf105954.odt new file mode 100644 index 0000000000..ba5c96de68 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf105954.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf105972.fodt b/vcl/qa/cppunit/pdfexport/data/tdf105972.fodt new file mode 100644 index 0000000000..b9f1e29f55 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf105972.fodt @@ -0,0 +1,175 @@ + + + 2022-05-17T10:53:27.0449158892022-05-18T18:02:56.717773462PT3M6LibreOfficeDev/7.4.0.0.alpha1$Linux_X86_64 LibreOffice_project/9e37c70c5c7413aee31f13fcd154cae30153e8ae + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + : + + : + + + + + + + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106059.odt b/vcl/qa/cppunit/pdfexport/data/tdf106059.odt new file mode 100644 index 0000000000..a2c1803783 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf106059.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106206.odt b/vcl/qa/cppunit/pdfexport/data/tdf106206.odt new file mode 100644 index 0000000000..3581157de4 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf106206.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106693.odt b/vcl/qa/cppunit/pdfexport/data/tdf106693.odt new file mode 100644 index 0000000000..a2c1803783 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf106693.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106702.odt b/vcl/qa/cppunit/pdfexport/data/tdf106702.odt new file mode 100644 index 0000000000..da3b7e8145 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf106702.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt b/vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt new file mode 100644 index 0000000000..d46c93dffb Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf106972-pdf17.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf106972.odt b/vcl/qa/cppunit/pdfexport/data/tdf106972.odt new file mode 100644 index 0000000000..3fa76c49fa Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf106972.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107013.odt b/vcl/qa/cppunit/pdfexport/data/tdf107013.odt new file mode 100644 index 0000000000..644e65c6de Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf107013.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107018.odt b/vcl/qa/cppunit/pdfexport/data/tdf107018.odt new file mode 100644 index 0000000000..3bfc7b2d73 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf107018.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107089.odt b/vcl/qa/cppunit/pdfexport/data/tdf107089.odt new file mode 100644 index 0000000000..5aaaab944a Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf107089.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf107868.odt b/vcl/qa/cppunit/pdfexport/data/tdf107868.odt new file mode 100644 index 0000000000..8309f4b878 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf107868.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf108963.odp b/vcl/qa/cppunit/pdfexport/data/tdf108963.odp new file mode 100644 index 0000000000..246c0c72ae Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf108963.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf109143.odt b/vcl/qa/cppunit/pdfexport/data/tdf109143.odt new file mode 100644 index 0000000000..7d9afa3789 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf109143.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf113143.odp b/vcl/qa/cppunit/pdfexport/data/tdf113143.odp new file mode 100644 index 0000000000..5f8a1b10e2 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf113143.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf114256.ods b/vcl/qa/cppunit/pdfexport/data/tdf114256.ods new file mode 100644 index 0000000000..1e30a7e31f Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf114256.ods differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt b/vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt new file mode 100644 index 0000000000..63fe82946e Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf115117-1.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt b/vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt new file mode 100644 index 0000000000..c1e1f6d439 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf115117-2.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115262.ods b/vcl/qa/cppunit/pdfexport/data/tdf115262.ods new file mode 100644 index 0000000000..b401a74ce9 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf115262.ods differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf115967.odt b/vcl/qa/cppunit/pdfexport/data/tdf115967.odt new file mode 100644 index 0000000000..ff538af5f5 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf115967.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt b/vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt new file mode 100644 index 0000000000..caabc4987c Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf118244_radioButtonGroup.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf121615.odt b/vcl/qa/cppunit/pdfexport/data/tdf121615.odt new file mode 100644 index 0000000000..7d2a87cf0e Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf121615.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf121962.odt b/vcl/qa/cppunit/pdfexport/data/tdf121962.odt new file mode 100644 index 0000000000..a831b11361 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf121962.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf124272.odt b/vcl/qa/cppunit/pdfexport/data/tdf124272.odt new file mode 100644 index 0000000000..54d4dcb2a1 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf124272.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf127217.odt b/vcl/qa/cppunit/pdfexport/data/tdf127217.odt new file mode 100644 index 0000000000..470600a0aa Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf127217.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf128445.odp b/vcl/qa/cppunit/pdfexport/data/tdf128445.odp new file mode 100644 index 0000000000..adabdb2235 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf128445.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf128630.odp b/vcl/qa/cppunit/pdfexport/data/tdf128630.odp new file mode 100644 index 0000000000..d216504b73 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf128630.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf129085.docx b/vcl/qa/cppunit/pdfexport/data/tdf129085.docx new file mode 100644 index 0000000000..6ac21d8f28 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf129085.docx differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp b/vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp new file mode 100644 index 0000000000..6168dd2a28 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf135192-1.fodp @@ -0,0 +1,239 @@ + + + 2020-07-27T11:44:30.444393550PT2M31S2LibreOfficeDev/7.5.0.0.alpha1$Linux_X86_64 LibreOffice_project/0c0fef37f8ea5528584324f72328f23b7fcc92d7Impress2020-07-27T11:47:01.552127285 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + Average starting score + + + Average improved score + + + + + Images + + + 35% + + + 91% + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/tdf135346.ods b/vcl/qa/cppunit/pdfexport/data/tdf135346.ods new file mode 100644 index 0000000000..5f696e5504 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf135346.ods differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf139065.odt b/vcl/qa/cppunit/pdfexport/data/tdf139065.odt new file mode 100644 index 0000000000..f8ffa26b2f Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf139065.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt b/vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt new file mode 100644 index 0000000000..f17f603788 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf139736-1.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf141171.odt b/vcl/qa/cppunit/pdfexport/data/tdf141171.odt new file mode 100644 index 0000000000..951f69541a Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf141171.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf144222.ods b/vcl/qa/cppunit/pdfexport/data/tdf144222.ods new file mode 100644 index 0000000000..7b572d301a Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf144222.ods differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf145274.docx b/vcl/qa/cppunit/pdfexport/data/tdf145274.docx new file mode 100644 index 0000000000..5b3b6afecf Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf145274.docx differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf145873.pptx b/vcl/qa/cppunit/pdfexport/data/tdf145873.pptx new file mode 100644 index 0000000000..7f5eb135c9 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf145873.pptx differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf147027.ods b/vcl/qa/cppunit/pdfexport/data/tdf147027.ods new file mode 100644 index 0000000000..24e1fde9ae Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf147027.ods differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf147164.odp b/vcl/qa/cppunit/pdfexport/data/tdf147164.odp new file mode 100644 index 0000000000..1b593348ea Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf147164.odp differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf148442.odt b/vcl/qa/cppunit/pdfexport/data/tdf148442.odt new file mode 100644 index 0000000000..10a5abf48e Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf148442.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf148706.odt b/vcl/qa/cppunit/pdfexport/data/tdf148706.odt new file mode 100644 index 0000000000..974bb97433 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf148706.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf150846.txt b/vcl/qa/cppunit/pdfexport/data/tdf150846.txt new file mode 100644 index 0000000000..ce01362503 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf150846.txt @@ -0,0 +1 @@ +hello diff --git a/vcl/qa/cppunit/pdfexport/data/tdf150931.ods b/vcl/qa/cppunit/pdfexport/data/tdf150931.ods new file mode 100644 index 0000000000..633362c614 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf150931.ods differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf152231.fodt b/vcl/qa/cppunit/pdfexport/data/tdf152231.fodt new file mode 100644 index 0000000000..26b5d329b2 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf152231.fodt @@ -0,0 +1,208 @@ + + + Gabor Kelemen LO2022-11-22T00:38:49.8080000002022-11-22T01:02:17.524000000Gabor Kelemen LOPT23M25S11LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/3d1f9c90605623e5c7e7dd2d28f87aaa45fb9c86aaa2023-06-30T17:07:42.601941685PDF files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + He heard quiet steps behind him. + That didn't bode well. + Who could be following him this late at night and in this deadbeat part of town? + And at this particular moment, just after he pulled off the big time and was making off with the greenbacks. + Was there another crook who'd had the same idea, and was now watching him and waiting for a chance to grab the fruit of his labor? + Or did the steps behind him mean that one of many law officers in town was on to him and just waiting to pounce and snap those cuffs on his wrists? + + Gabor Kelemen LO + 2022-11-22T00:56:44.315000000 + GK + This is a comment + He nervously looked all around. + Suddenly he saw the alley. + Like lightning he darted off to the left and disappeared between the two warehouses almost falling + over the trash can lying in the middle of the sidewalk. + He tried to nervously tap his way along in the inky + darkness and suddenly stiffened: it was a dead-end, he would have to go back the way he had come. The steps got louder and louder, he saw the black outline of a figure coming around the corner. Is this the end of the line? he thought pressing himself back against the wall trying to make himself invisible in the dark, was all that planning and energy wasted? He was dripping with sweat now, cold and wet, he could smell the fear coming off his clothes. Suddenly next to him, with a barely noticeable squeak, a door swung quietly to and fro in the night's breeze. Could this be the haven he'd prayed for? Slowly he slid toward the door, pressing himself more and more into the wall, into the dark, away from his enemy. Would this door save his hide? + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/tdf154549.odt b/vcl/qa/cppunit/pdfexport/data/tdf154549.odt new file mode 100644 index 0000000000..09ed1324ec Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf154549.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf154982.odt b/vcl/qa/cppunit/pdfexport/data/tdf154982.odt new file mode 100644 index 0000000000..a35ffb861a Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf154982.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf155161.odt b/vcl/qa/cppunit/pdfexport/data/tdf155161.odt new file mode 100644 index 0000000000..1d22bb7c4d Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf155161.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf155190.odt b/vcl/qa/cppunit/pdfexport/data/tdf155190.odt new file mode 100644 index 0000000000..51930ad299 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf155190.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf156685.docx b/vcl/qa/cppunit/pdfexport/data/tdf156685.docx new file mode 100644 index 0000000000..a3eddf8459 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf156685.docx differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf157679.pptx b/vcl/qa/cppunit/pdfexport/data/tdf157679.pptx new file mode 100644 index 0000000000..ca82491c21 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf157679.pptx differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf157816.fodt b/vcl/qa/cppunit/pdfexport/data/tdf157816.fodt new file mode 100644 index 0000000000..5288f3aa75 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf157816.fodt @@ -0,0 +1,175 @@ + + + 2020-12-04T17:01:40.586000000LibreOfficeP18DT13H30M55S102LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/70bf29987ceb90cd3988fc2dfc4cad2a0163fe172023-10-18T20:11:26.1740000002023-10-18T20:36:10.265000000PDF files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Abbildung 1: Haus! + + Extras fdsfsdf dfs sdf dsfsd fs fsd sdfsd fsgf gfhf gfhgfrt fd fdg ddfg dfgd fdfg df dfg + szíjfdgdf fdfg dfg gdfgdfg dggdf fd + aads fsdfsd sdf sd fsd sdffsdf Error: Reference source not foundError: Reference source not foundbb dsfsd sdfsdfsd. + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/tdf48707-1.fodt b/vcl/qa/cppunit/pdfexport/data/tdf48707-1.fodt new file mode 100644 index 0000000000..02286e5051 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf48707-1.fodt @@ -0,0 +1,290 @@ + + + + Scott Wills2011-08-03T07:12:282023-07-03T14:56:12.773653822PT1M52S2LibreOffice/7.5.4.2$MacOSX_X86_64 LibreOffice_project/36ccfdc35048b057fd9854c757a8b67ec53977b6 + + + 0 + 0 + 22666 + 10624 + true + false + + + view2 + 10463 + 2501 + 0 + 0 + 22664 + 10622 + 3 + 0 + false + 167 + false + false + true + true + false + + + + + true + true + true + true + false + + false + false + true + false + false + false + true + false + false + false + false + false + 0 + 0 + false + false + false + false + true + false + false + false + true + false + false + + false + false + + true + false + false + false + false + false + true + true + false + false + false + false + false + false + false + false + false + + false + false + false + false + false + false + 0 + false + false + false + false + false + true + false + false + false + false + false + false + false + + false + false + true + true + false + true + true + false + 821660 + true + true + false + + false + true + false + high-resolution + 1 + 0 + true + false + false + true + true + true + true + true + false + true + + false + true + 850755 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ABC + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/tdf48707-2.fodt b/vcl/qa/cppunit/pdfexport/data/tdf48707-2.fodt new file mode 100644 index 0000000000..2fc8287bab --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/tdf48707-2.fodt @@ -0,0 +1,335 @@ + + + + 2021-05-08T05:14:15.2955032482021-05-08T05:18:15.188776430PT2M4S2LibreOffice/7.5.4.2$MacOSX_X86_64 LibreOffice_project/36ccfdc35048b057fd9854c757a8b67ec53977b6 + + + 0 + 0 + 37110 + 17392 + true + false + + + view2 + 10054 + 2501 + 0 + 0 + 37109 + 17390 + 0 + 1 + false + 102 + false + false + false + true + false + + + + + true + true + true + true + false + + false + false + false + false + false + false + true + false + false + false + false + false + 0 + 0 + false + false + false + false + false + true + false + false + true + false + false + + false + false + + true + false + false + false + false + false + true + false + true + true + false + false + false + false + true + false + false + + false + false + false + false + false + false + 0 + false + false + false + false + false + true + false + false + false + false + false + false + false + + true + false + true + true + false + true + true + false + 1346600 + true + true + false + + false + true + false + high-resolution + 1 + 0 + true + false + false + true + true + true + true + true + false + true + + false + true + 1496896 + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A little test. + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt b/vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt new file mode 100644 index 0000000000..e5cc9bc0b3 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf66597-1.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt b/vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt new file mode 100644 index 0000000000..3d7b5e59cc Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf66597-2.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt b/vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt new file mode 100644 index 0000000000..6db91fe81b Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf66597-3.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf84283.doc b/vcl/qa/cppunit/pdfexport/data/tdf84283.doc new file mode 100644 index 0000000000..dc48cfaae0 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf84283.doc differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt b/vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt new file mode 100644 index 0000000000..47c370004d Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf99680-2.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/tdf99680.odt b/vcl/qa/cppunit/pdfexport/data/tdf99680.odt new file mode 100644 index 0000000000..de12f9baa1 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf99680.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/toc-link.fodt b/vcl/qa/cppunit/pdfexport/data/toc-link.fodt new file mode 100644 index 0000000000..ab29e88a47 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/toc-link.fodt @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Table of Contents + + + + + + + + + Table of Contents + + Heading 11 + + + Heading 1 + + + diff --git a/vcl/qa/cppunit/pdfexport/data/transparentshape.fodp b/vcl/qa/cppunit/pdfexport/data/transparentshape.fodp new file mode 100644 index 0000000000..2fddc3ac0d --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/transparentshape.fodp @@ -0,0 +1,439 @@ + + + 2023-10-10T13:14:06.5730039102023-10-10T13:16:02.094663208PT1M57S1LibreOfficeDev/24.2.0.0.alpha0$Linux_X86_64 LibreOffice_project/1aa3fb5816925ce1bc28aa17a26b8d8c2f2036f5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + + + + + + + + + + + + + + + + <number> + + + + + + + + + + Transparent shape + + + + + + + + + + + + + + + Nothing transparent here + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/data/vid.odt b/vcl/qa/cppunit/pdfexport/data/vid.odt new file mode 100644 index 0000000000..fc34ab8f19 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/vid.odt differ diff --git a/vcl/qa/cppunit/pdfexport/data/wide_page1.fodt b/vcl/qa/cppunit/pdfexport/data/wide_page1.fodt new file mode 100644 index 0000000000..9e7390a8e2 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/data/wide_page1.fodt @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx new file mode 100644 index 0000000000..d5515facb5 --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -0,0 +1,2774 @@ +/* -*- 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 + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Tests the PDF export filter. +class PdfExportTest : public UnoApiTest +{ +protected: + utl::MediaDescriptor aMediaDescriptor; + +public: + PdfExportTest() + : UnoApiTest("/vcl/qa/cppunit/pdfexport/data/") + { + } + + void saveAsPDF(std::u16string_view rFile); + void load(std::u16string_view rFile, vcl::filter::PDFDocument& rDocument, + bool bUseTaggedPDF = true); +}; + +void PdfExportTest::saveAsPDF(std::u16string_view rFile) +{ + // Import the bugdoc and export as PDF. + loadFromFile(rFile); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); +} + +void PdfExportTest::load(std::u16string_view rFile, vcl::filter::PDFDocument& rDocument, + bool bUseTaggedPDF) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "UseTaggedPDF", uno::Any(bUseTaggedPDF) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(rFile); + + // Parse the export result. + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(rDocument.Read(aStream)); +} + +/// Tests that a pdf image is roundtripped back to PDF as a vector format. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106059) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + // Explicitly enable the usage of the reference XObject markup. + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "UseReferenceXObject", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf106059.odt"); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // Assert that the XObject in the page resources dictionary is a reference XObject. + std::vector aPages = aDocument.GetPages(); + // The document has one page. + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + // The page has one image. + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pReferenceXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pReferenceXObject); + // The image is a reference XObject. + // This dictionary key was missing, so the XObject wasn't a reference one. + CPPUNIT_ASSERT(pReferenceXObject->Lookup("Ref"_ostr)); +} + +/// Tests export of PDF images without reference XObjects. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106693) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf106693.odt", aDocument); + + // Assert that the XObject in the page resources dictionary is a form XObject. + std::vector aPages = aDocument.GetPages(); + // The document has one page. + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + // The page has one image. + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + // The image is a form XObject. + auto pSubtype = dynamic_cast(pXObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pSubtype->GetValue()); + // This failed: UseReferenceXObject was ignored and Ref was always created. + CPPUNIT_ASSERT(!pXObject->Lookup("Ref"_ostr)); + + // Assert that the form object refers to an inner form object, not a + // bitmap. + auto pInnerResources + = dynamic_cast(pXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pInnerResources); + auto pInnerXObjects = dynamic_cast( + pInnerResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pInnerXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pInnerXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pInnerXObject + = pInnerXObjects->LookupObject(pInnerXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pInnerXObject); + auto pInnerSubtype + = dynamic_cast(pInnerXObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pInnerSubtype); + // This failed: this was Image (bitmap), not Form (vector). + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pInnerSubtype->GetValue()); +} + +/// Tests that text highlight from Impress is not lost. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105461) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf105461.odp"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Make sure there is a filled rectangle inside. + int nPageObjectCount = pPdfPage->getObjectCount(); + int nYellowPathCount = 0; + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPdfPageObject = pPdfPage->getObject(i); + if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path) + continue; + + if (pPdfPageObject->getFillColor() == COL_YELLOW) + ++nYellowPathCount; + } + + // This was 0, the page contained no yellow paths. + CPPUNIT_ASSERT_EQUAL(1, nYellowPathCount); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107868) +{ +// No need to run it on Windows, since it would use GDI printing, and not trigger PDF export +// which is the intent of the test. +// FIXME: Why does this fail on macOS? +#if !defined MACOSX && !defined _WIN32 + + // Import the bugdoc and print to PDF. + loadFromFile(u"tdf107868.odt"); + uno::Reference xPrintable(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xPrintable.is()); + uno::Sequence aOptions(comphelper::InitPropertySequence( + { { "FileName", uno::Any(maTempFile.GetURL()) }, { "Wait", uno::Any(true) } })); + xPrintable->print(aOptions); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + if (!pPdfDocument) + // Printing to PDF failed in a non-interesting way, e.g. CUPS is not + // running, there is no printer defined, etc. + return; + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Make sure there is no filled rectangle inside. + int nPageObjectCount = pPdfPage->getObjectCount(); + int nWhitePathCount = 0; + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPdfPageObject = pPdfPage->getObject(i); + if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path) + continue; + + if (pPdfPageObject->getFillColor() == COL_WHITE) + ++nWhitePathCount; + } + + // This was 4, the page contained 4 white paths at problematic positions. + CPPUNIT_ASSERT_EQUAL(0, nWhitePathCount); +#endif +} + +/// Tests that embedded video from Impress is not exported as a linked one. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105093) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf105093.odp", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Get page annotations. + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnnots->GetElements().size()); + auto pAnnotReference + = dynamic_cast(pAnnots->GetElements()[0]); + CPPUNIT_ASSERT(pAnnotReference); + vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + CPPUNIT_ASSERT_EQUAL( + "Annot"_ostr, + static_cast(pAnnot->Lookup("Type"_ostr))->GetValue()); + + // Get the Action -> Rendition -> MediaClip -> FileSpec. + auto pAction = dynamic_cast(pAnnot->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAction); + auto pRendition + = dynamic_cast(pAction->LookupElement("R"_ostr)); + CPPUNIT_ASSERT(pRendition); + auto pMediaClip + = dynamic_cast(pRendition->LookupElement("C"_ostr)); + CPPUNIT_ASSERT(pMediaClip); + auto pFileSpec + = dynamic_cast(pMediaClip->LookupElement("D"_ostr)); + CPPUNIT_ASSERT(pFileSpec); + // Make sure the filespec refers to an embedded file. + // This key was missing, the embedded video was handled as a linked one. + CPPUNIT_ASSERT(pFileSpec->LookupElement("EF"_ostr)); +} + +/// Tests export of non-PDF images. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106206) +{ + // Import the bugdoc and export as PDF. + vcl::filter::PDFDocument aDocument; + load(u"tdf106206.odt", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // The page has a stream. + 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()); + + // Make sure there is an image reference there. + OString aImage("/Im"_ostr); + auto pStart = static_cast(aUncompressed.GetData()); + const char* pEnd = pStart + aUncompressed.GetSize(); + auto it = std::search(pStart, pEnd, aImage.getStr(), aImage.getStr() + aImage.getLength()); + CPPUNIT_ASSERT(it != pEnd); + + // And also that it's not an invalid one. + OString aInvalidImage("/Im0"_ostr); + it = std::search(pStart, pEnd, aInvalidImage.getStr(), + aInvalidImage.getStr() + aInvalidImage.getLength()); + // This failed, object #0 was referenced. + CPPUNIT_ASSERT(bool(it == pEnd)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf127217) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf127217.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // The page has one annotation. + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); + std::unique_ptr pAnnot = pPdfPage->getAnnotation(0); + + // Without the fix in place, this test would have failed here + CPPUNIT_ASSERT(!pAnnot->hasKey("DA"_ostr)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf109143) +{ + // Import the bugdoc and export as PDF. + vcl::filter::PDFDocument aDocument; + load(u"tdf109143.odt", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Get access to the only image on the only page. + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + + // Make sure it's re-compressed. + auto pLength = dynamic_cast(pXObject->Lookup("Length"_ostr)); + CPPUNIT_ASSERT(pLength); + int nLength = pLength->GetValue(); + // This failed: cropped TIFF-in-JPEG wasn't re-compressed, so crop was + // lost. Size was 59416, now is 11827. + CPPUNIT_ASSERT(nLength < 50000); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106972) +{ + // Import the bugdoc and export as PDF. + vcl::filter::PDFDocument aDocument; + load(u"tdf106972.odt", aDocument); + + // Get access to the only form object on the only page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + + // Get access to the only image inside the form object. + auto pFormResources + = dynamic_cast(pXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pFormResources); + auto pImages = dynamic_cast( + pFormResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pImages); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pImages->GetItems().size()); + vcl::filter::PDFObjectElement* pImage + = pImages->LookupObject(pImages->GetItems().begin()->first); + CPPUNIT_ASSERT(pImage); + + // Assert resources of the image. + auto pImageResources + = dynamic_cast(pImage->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pImageResources); + // This failed: the PDF image had no Font resource. + CPPUNIT_ASSERT(pImageResources->LookupElement("Font"_ostr)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106972Pdf17) +{ + // Import the bugdoc and export as PDF. + vcl::filter::PDFDocument aDocument; + load(u"tdf106972-pdf17.odt", aDocument); + + // Get access to the only image on the only page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + + // Assert that we now attempt to preserve the original PDF data, even if + // the original input was PDF >= 1.4. + CPPUNIT_ASSERT(pXObject->Lookup("Resources"_ostr)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testSofthyphenPos) +{ +// No need to run it on Windows, since it would use GDI printing, and not trigger PDF export +// which is the intent of the test. +// FIXME: Why does this fail on macOS? +#if !defined MACOSX && !defined _WIN32 + + // Import the bugdoc and print to PDF. + loadFromFile(u"softhyphen_pdf.odt"); + uno::Reference xPrintable(mxComponent, uno::UNO_QUERY); + CPPUNIT_ASSERT(xPrintable.is()); + uno::Sequence aOptions(comphelper::InitPropertySequence( + { { "FileName", uno::Any(maTempFile.GetURL()) }, { "Wait", uno::Any(true) } })); + xPrintable->print(aOptions); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + if (!pPdfDocument) + // Printing to PDF failed in a non-interesting way, e.g. CUPS is not + // running, there is no printer defined, etc. + return; + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // tdf#96892 incorrect fractional part of font size caused soft-hyphen to + // be positioned inside preceding text (incorrect = 11.1, correct = 11.05) + + // there are 3 texts currently, for line 1, soft-hyphen, line 2 + bool haveText(false); + + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPdfPageObject = pPdfPage->getObject(i); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Text, pPdfPageObject->getType()); + haveText = true; + double const size = pPdfPageObject->getFontSize(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(11.05, size, 1E-06); + } + + CPPUNIT_ASSERT(haveText); +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107013) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf107013.odt", aDocument); + + // Get access to the only image on the only page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + // This failed, the reference to the image was created, but not the image. + CPPUNIT_ASSERT(pXObject); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107018) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf107018.odt", aDocument); + + // Get access to the only image on the only page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + + // Get access to the form object inside the image. + auto pXObjectResources + = dynamic_cast(pXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast( + pXObjectResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm + = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + // Get access to Resources -> Font -> F1 of the form. + auto pFormResources + = dynamic_cast(pForm->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pFormResources); + auto pFonts = dynamic_cast( + pFormResources->LookupElement("Font"_ostr)); + CPPUNIT_ASSERT(pFonts); + auto pF1Ref = dynamic_cast(pFonts->LookupElement("F1"_ostr)); + CPPUNIT_ASSERT(pF1Ref); + vcl::filter::PDFObjectElement* pF1 = pF1Ref->LookupObject(); + CPPUNIT_ASSERT(pF1); + + // Check that Foo -> Bar of the font is of type Pages. + auto pFontFoo = dynamic_cast(pF1->Lookup("Foo"_ostr)); + CPPUNIT_ASSERT(pFontFoo); + auto pBar + = dynamic_cast(pFontFoo->LookupElement("Bar"_ostr)); + CPPUNIT_ASSERT(pBar); + vcl::filter::PDFObjectElement* pObject = pBar->LookupObject(); + CPPUNIT_ASSERT(pObject); + auto pName = dynamic_cast(pObject->Lookup("Type"_ostr)); + CPPUNIT_ASSERT(pName); + // This was "XObject", reference in a nested dictionary wasn't updated when + // copying the page stream of a PDF image. + CPPUNIT_ASSERT_EQUAL("Pages"_ostr, pName->GetValue()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf148706) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf148706.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // The page has one annotation. + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); + std::unique_ptr pAnnot = pPdfPage->getAnnotation(0); + + CPPUNIT_ASSERT(pAnnot->hasKey("V"_ostr)); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("V"_ostr)); + OUString aV = pAnnot->getString("V"_ostr); + + // Without the fix in place, this test would have failed with + // - Expected: 1821.84 + // - Actual : + CPPUNIT_ASSERT_EQUAL(OUString("1821.84"), aV); + + CPPUNIT_ASSERT(pAnnot->hasKey("DV"_ostr)); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("DV"_ostr)); + OUString aDV = pAnnot->getString("DV"_ostr); + + CPPUNIT_ASSERT_EQUAL(OUString("1821.84"), aDV); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf107089) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf107089.odt", aDocument); + + // Get access to the only image on the only page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + + // Get access to the form object inside the image. + auto pXObjectResources + = dynamic_cast(pXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast( + pXObjectResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm + = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + // Make sure 'Hello' is part of the form object's stream. + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream aObjectStream; + ZCodec aZCodec; + aZCodec.BeginCompression(); + pStream->GetMemory().Seek(0); + aZCodec.Decompress(pStream->GetMemory(), aObjectStream); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + aObjectStream.Seek(0); + OString aHello("Hello"_ostr); + auto pStart = static_cast(aObjectStream.GetData()); + const char* pEnd = pStart + aObjectStream.GetSize(); + auto it = std::search(pStart, pEnd, aHello.getStr(), aHello.getStr() + aHello.getLength()); + // This failed, 'Hello' was part only a mixed compressed/uncompressed stream, i.e. garbage. + CPPUNIT_ASSERT(it != pEnd); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf99680) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf99680.odt", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // The page 1 has a stream. + 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()); + + // tdf#130150 See infos in task - short: tdf#99680 was not the + // correct fix, so empty clip regions are valid - allow again in tests + // Make sure there are no empty clipping regions. + // OString aEmptyRegion("0 0 m h W* n"); + // auto it = std::search(pStart, pEnd, aEmptyRegion.getStr(), aEmptyRegion.getStr() + aEmptyRegion.getLength()); + // CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty clipping region detected!", it, pEnd); + + // Count save graphic state (q) and restore (Q) operators + // and ensure their amount is equal + auto pStart = static_cast(aUncompressed.GetData()); + const char* pEnd = pStart + aUncompressed.GetSize(); + size_t nSaveCount = std::count(pStart, pEnd, 'q'); + size_t nRestoreCount = std::count(pStart, pEnd, 'Q'); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Save/restore graphic state operators count mismatch!", nSaveCount, + nRestoreCount); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf99680_2) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf99680-2.odt", aDocument); + + // For each document page + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(3), aPages.size()); + for (size_t nPageNr = 0; nPageNr < aPages.size(); nPageNr++) + { + // Get page contents and stream. + vcl::filter::PDFObjectElement* pContents = aPages[nPageNr]->LookupObject("Contents"_ostr); + CPPUNIT_ASSERT(pContents); + vcl::filter::PDFStreamElement* pStream = pContents->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + + // Uncompress the stream. + SvMemoryStream aUncompressed; + ZCodec aZCodec; + aZCodec.BeginCompression(); + rObjectStream.Seek(0); + aZCodec.Decompress(rObjectStream, aUncompressed); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + + // tdf#130150 See infos in task - short: tdf#99680 was not the + // correct fix, so empty clip regions are valid - allow again in tests + // Make sure there are no empty clipping regions. + // OString aEmptyRegion("0 0 m h W* n"); + // auto it = std::search(pStart, pEnd, aEmptyRegion.getStr(), aEmptyRegion.getStr() + aEmptyRegion.getLength()); + // CPPUNIT_ASSERT_EQUAL_MESSAGE("Empty clipping region detected!", it, pEnd); + + // Count save graphic state (q) and restore (Q) operators + // and ensure their amount is equal + auto pStart = static_cast(aUncompressed.GetData()); + const char* pEnd = pStart + aUncompressed.GetSize(); + size_t nSaveCount = std::count(pStart, pEnd, 'q'); + size_t nRestoreCount = std::count(pStart, pEnd, 'Q'); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Save/restore graphic state operators count mismatch!", + nSaveCount, nRestoreCount); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf108963) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf108963.odp"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Test page size (28x15.75 cm, was 1/100th mm off, tdf#112690) + // bad: MediaBox[0 0 793.672440944882 446.428346456693] + // good: MediaBox[0 0 793.700787401575 446.456692913386] + const double aWidth = pPdfPage->getWidth(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(793.7, aWidth, 0.01); + const double aHeight = pPdfPage->getHeight(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(446.46, aHeight, 0.01); + + // Make sure there is a filled rectangle inside. + int nPageObjectCount = pPdfPage->getObjectCount(); + int nYellowPathCount = 0; + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPdfPageObject = pPdfPage->getObject(i); + if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path) + continue; + + if (pPdfPageObject->getFillColor() == COL_YELLOW) + { + ++nYellowPathCount; + // The path described a yellow rectangle, but it was not rotated. + int nSegments = pPdfPageObject->getPathSegmentCount(); + CPPUNIT_ASSERT_EQUAL(5, nSegments); + std::unique_ptr pSegment + = pPdfPageObject->getPathSegment(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Moveto, pSegment->getType()); + basegfx::B2DPoint aPoint = pSegment->getPoint(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(245, aPoint.getX(), 0.999); + CPPUNIT_ASSERT_DOUBLES_EQUAL(244, aPoint.getY(), 0.999); + CPPUNIT_ASSERT(!pSegment->isClosed()); + + pSegment = pPdfPageObject->getPathSegment(1); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType()); + aPoint = pSegment->getPoint(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(275, aPoint.getX(), 0.999); + CPPUNIT_ASSERT_DOUBLES_EQUAL(267, aPoint.getY(), 0.999); + CPPUNIT_ASSERT(!pSegment->isClosed()); + + pSegment = pPdfPageObject->getPathSegment(2); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType()); + aPoint = pSegment->getPoint(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(287, aPoint.getX(), 0.999); + CPPUNIT_ASSERT_DOUBLES_EQUAL(251, aPoint.getY(), 0.999); + CPPUNIT_ASSERT(!pSegment->isClosed()); + + pSegment = pPdfPageObject->getPathSegment(3); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType()); + aPoint = pSegment->getPoint(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(257, aPoint.getX(), 0.999); + CPPUNIT_ASSERT_DOUBLES_EQUAL(228, aPoint.getY(), 0.999); + CPPUNIT_ASSERT(!pSegment->isClosed()); + + pSegment = pPdfPageObject->getPathSegment(4); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFSegmentType::Lineto, pSegment->getType()); + aPoint = pSegment->getPoint(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(245, aPoint.getX(), 0.999); + CPPUNIT_ASSERT_DOUBLES_EQUAL(244, aPoint.getY(), 0.999); + CPPUNIT_ASSERT(pSegment->isClosed()); + } + } + + CPPUNIT_ASSERT_EQUAL(1, nYellowPathCount); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testAlternativeText) +{ + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "UseTaggedPDF", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"alternativeText.fodp"); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "Figure") + { + CPPUNIT_ASSERT_EQUAL(u"This is the text alternative - This is the description"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + } + } + } + + // tdf#67866 check that Catalog contains Lang + auto* pCatalog = aDocument.GetCatalog(); + CPPUNIT_ASSERT(pCatalog); + auto* pCatalogDictionary = pCatalog->GetDictionary(); + CPPUNIT_ASSERT(pCatalogDictionary); + auto pLang = dynamic_cast( + pCatalogDictionary->LookupElement("Lang"_ostr)); + CPPUNIT_ASSERT(pLang); + CPPUNIT_ASSERT_EQUAL("en-US"_ostr, pLang->GetValue()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105972) +{ + vcl::filter::PDFDocument aDocument; + // Loading fails with tagged PDF enabled + load(u"tdf105972.fodt", aDocument, false); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(static_cast(3), pAnnots->GetElements().size()); + + sal_uInt32 nTextFieldCount = 0; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("FT"_ostr)); + if (pType && pType->GetValue() == "Tx") + { + ++nTextFieldCount; + + auto pT + = dynamic_cast(pObject->Lookup("T"_ostr)); + CPPUNIT_ASSERT(pT); + auto pAA = dynamic_cast(pObject->Lookup("AA"_ostr)); + CPPUNIT_ASSERT(pAA); + CPPUNIT_ASSERT_EQUAL(static_cast(2), pAA->GetItems().size()); + auto pF + = dynamic_cast(pAA->LookupElement("F"_ostr)); + CPPUNIT_ASSERT(pF); + CPPUNIT_ASSERT_EQUAL(static_cast(2), pF->GetItems().size()); + + if (nTextFieldCount == 1) + { + CPPUNIT_ASSERT_EQUAL("CurrencyField"_ostr, pT->GetValue()); + + auto pJS = dynamic_cast( + pF->LookupElement("JS"_ostr)); + CPPUNIT_ASSERT_EQUAL("AFNumber_Format\\(4, 0, 0, 0, \"\\\\u20ac\",true\\);"_ostr, + pJS->GetValue()); + } + else if (nTextFieldCount == 2) + { + CPPUNIT_ASSERT_EQUAL("TimeField"_ostr, pT->GetValue()); + + auto pJS = dynamic_cast( + pF->LookupElement("JS"_ostr)); + CPPUNIT_ASSERT_EQUAL("AFTime_FormatEx\\(\"h:MM:sstt\"\\);"_ostr, pJS->GetValue()); + } + else + { + CPPUNIT_ASSERT_EQUAL("DateField"_ostr, pT->GetValue()); + + auto pJS = dynamic_cast( + pF->LookupElement("JS"_ostr)); + CPPUNIT_ASSERT_EQUAL("AFDate_FormatEx\\(\"yy-mm-dd\"\\);"_ostr, pJS->GetValue()); + } + } + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf148442) +{ + vcl::filter::PDFDocument aDocument; + // Loading fails with tagged PDF enabled + load(u"tdf148442.odt", aDocument, false); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(static_cast(3), pAnnots->GetElements().size()); + + sal_uInt32 nBtnCount = 0; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("FT"_ostr)); + if (pType && pType->GetValue() == "Btn") + { + ++nBtnCount; + auto pT + = dynamic_cast(pObject->Lookup("T"_ostr)); + CPPUNIT_ASSERT(pT); + auto pAS = dynamic_cast(pObject->Lookup("AS"_ostr)); + CPPUNIT_ASSERT(pAS); + + auto pAP = dynamic_cast(pObject->Lookup("AP"_ostr)); + CPPUNIT_ASSERT(pAP); + auto pN + = dynamic_cast(pAP->LookupElement("N"_ostr)); + CPPUNIT_ASSERT(pN); + CPPUNIT_ASSERT_EQUAL(static_cast(2), pN->GetItems().size()); + + if (nBtnCount == 1) + { + CPPUNIT_ASSERT_EQUAL("Checkbox1"_ostr, pT->GetValue()); + CPPUNIT_ASSERT_EQUAL("Yes"_ostr, pAS->GetValue()); + CPPUNIT_ASSERT(!pN->GetItems().count("ref"_ostr)); + CPPUNIT_ASSERT(pN->GetItems().count("Yes"_ostr)); + CPPUNIT_ASSERT(pN->GetItems().count("Off"_ostr)); + } + else if (nBtnCount == 2) + { + CPPUNIT_ASSERT_EQUAL("Checkbox2"_ostr, pT->GetValue()); + CPPUNIT_ASSERT_EQUAL("Yes"_ostr, pAS->GetValue()); + + // Without the fix in place, this test would have failed here + CPPUNIT_ASSERT(pN->GetItems().count("ref"_ostr)); + CPPUNIT_ASSERT(!pN->GetItems().count("Yes"_ostr)); + CPPUNIT_ASSERT(pN->GetItems().count("Off"_ostr)); + } + else + { + CPPUNIT_ASSERT_EQUAL("Checkbox3"_ostr, pT->GetValue()); + CPPUNIT_ASSERT_EQUAL("Off"_ostr, pAS->GetValue()); + CPPUNIT_ASSERT(pN->GetItems().count("ref"_ostr)); + CPPUNIT_ASSERT(!pN->GetItems().count("Yes"_ostr)); + + // tdf#143612: Without the fix in place, this test would have failed here + CPPUNIT_ASSERT(!pN->GetItems().count("Off"_ostr)); + CPPUNIT_ASSERT(pN->GetItems().count("refOff"_ostr)); + } + } + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf118244_radioButtonGroup) +{ + vcl::filter::PDFDocument aDocument; + // Loading fails with tagged PDF enabled + load(u"tdf118244_radioButtonGroup.odt", aDocument, false); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // There are eight radio buttons. + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL_MESSAGE("# of radio buttons", static_cast(8), + pAnnots->GetElements().size()); + + sal_uInt32 nRadioGroups = 0; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("FT"_ostr)); + if (pType && pType->GetValue() == "Btn") + { + auto pKids = dynamic_cast(pObject->Lookup("Kids"_ostr)); + if (pKids) + { + size_t expectedSize = 2; + ++nRadioGroups; + if (nRadioGroups == 3) + expectedSize = 3; + CPPUNIT_ASSERT_EQUAL(expectedSize, pKids->GetElements().size()); + } + } + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("# of radio groups", sal_uInt32(3), nRadioGroups); +} + +/// Test writing ToUnicode CMAP for LTR ligatures. +// This requires Carlito font, if it is missing the test will most likely +// fail. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_1) +{ +#if HAVE_MORE_FONTS + vcl::filter::PDFDocument aDocument; + load(u"tdf115117-1.odt", aDocument); + + vcl::filter::PDFObjectElement* pToUnicode = nullptr; + + // Get access to ToUnicode of the first font + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pToUnicodeRef = dynamic_cast( + pObject->Lookup("ToUnicode"_ostr)); + CPPUNIT_ASSERT(pToUnicodeRef); + pToUnicode = pToUnicodeRef->LookupObject(); + break; + } + } + + CPPUNIT_ASSERT(pToUnicode); + auto pStream = pToUnicode->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream aObjectStream; + ZCodec aZCodec; + aZCodec.BeginCompression(); + pStream->GetMemory().Seek(0); + aZCodec.Decompress(pStream->GetMemory(), aObjectStream); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + aObjectStream.Seek(0); + // The first values, <01> <02> etc., are glyph ids, they might change order + // if we changed how font subsets are created. + // The second values, <00740069> etc., are Unicode code points in hex, + // <00740069> is U+0074 and U+0069 i.e. "ti" which is a ligature in + // Carlito/Calibri. This test is failing if any of the second values + // changed which means we are not detecting ligatures and writing CMAP + // entries for them correctly. If glyph order in the subset changes then + // the order here will changes and the PDF has to be carefully inspected to + // ensure that the new values are correct before updating the string below. + OString aCmap("9 beginbfchar\n" + "<01> <00740069>\n" + "<02> <0020>\n" + "<03> <0074>\n" + "<04> <0065>\n" + "<05> <0073>\n" + "<06> <00660069>\n" + "<07> <0066006C>\n" + "<08> <006600660069>\n" + "<09> <00660066006C>\n" + "endbfchar"_ostr); + auto pStart = static_cast(aObjectStream.GetData()); + const char* pEnd = pStart + aObjectStream.GetSize(); + auto it = std::search(pStart, pEnd, aCmap.getStr(), aCmap.getStr() + aCmap.getLength()); + CPPUNIT_ASSERT(it != pEnd); +#endif +} + +/// Test writing ToUnicode CMAP for RTL ligatures. +// This requires DejaVu Sans font, if it is missing the test will most likely +// fail. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_2) +{ +#if HAVE_MORE_FONTS + // See the comments in testTdf115117_1() for explanation. + + vcl::filter::PDFDocument aDocument; + load(u"tdf115117-2.odt", aDocument); + + vcl::filter::PDFObjectElement* pToUnicode = nullptr; + + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pToUnicodeRef = dynamic_cast( + pObject->Lookup("ToUnicode"_ostr)); + CPPUNIT_ASSERT(pToUnicodeRef); + pToUnicode = pToUnicodeRef->LookupObject(); + break; + } + } + + CPPUNIT_ASSERT(pToUnicode); + auto pStream = pToUnicode->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream aObjectStream; + ZCodec aZCodec; + aZCodec.BeginCompression(); + pStream->GetMemory().Seek(0); + aZCodec.Decompress(pStream->GetMemory(), aObjectStream); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + aObjectStream.Seek(0); + OString aCmap("7 beginbfchar\n" + "<01> <06440627>\n" + "<02> <0020>\n" + "<03> <0641>\n" + "<04> <0642>\n" + "<05> <0648>\n" + "<06> <06440627>\n" + "<07> <0628>\n" + "endbfchar"_ostr); + auto pStart = static_cast(aObjectStream.GetData()); + const char* pEnd = pStart + aObjectStream.GetSize(); + auto it = std::search(pStart, pEnd, aCmap.getStr(), aCmap.getStr() + aCmap.getLength()); + CPPUNIT_ASSERT(it != pEnd); +#endif +} + +/// Text extracting LTR text with ligatures. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_1a) +{ +#if HAVE_MORE_FONTS + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf115117-1.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + std::unique_ptr pPdfTextPage = pPdfPage->getTextPage(); + CPPUNIT_ASSERT(pPdfTextPage); + + // Extract the text from the page. This pdfium API is a bit higher level + // than we want and might apply heuristic that give false positive, but it + // is a good approximation in addition to the check in testTdf115117_1(). + int nChars = pPdfTextPage->countChars(); + CPPUNIT_ASSERT_EQUAL(44, nChars); + + std::vector aChars(nChars); + for (int i = 0; i < nChars; i++) + aChars[i] = pPdfTextPage->getUnicode(i); + OUString aActualText(aChars.data(), aChars.size()); + CPPUNIT_ASSERT_EQUAL(OUString("ti ti test ti\r\nti test fi fl ffi ffl test fi"), aActualText); +#endif +} + +/// Test extracting RTL text with ligatures. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115117_2a) +{ +#if HAVE_MORE_FONTS + // See the comments in testTdf115117_1a() for explanation. + + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf115117-2.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + std::unique_ptr pPdfTextPage = pPdfPage->getTextPage(); + CPPUNIT_ASSERT(pPdfTextPage); + + int nChars = pPdfTextPage->countChars(); + CPPUNIT_ASSERT_EQUAL(13, nChars); + + std::vector aChars(nChars); + for (int i = 0; i < nChars; i++) + aChars[i] = pPdfTextPage->getUnicode(i); + OUString aActualText(aChars.data(), aChars.size()); + CPPUNIT_ASSERT_EQUAL(u"\u0627\u0644 \u0628\u0627\u0644 \u0648\u0642\u0641 \u0627\u0644"_ustr, + aActualText); +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf154549) +{ +// FIXME: On Windows, the number of chars is 4 instead of 3 +#ifndef _WIN32 + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf154549.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + std::unique_ptr pPdfTextPage = pPdfPage->getTextPage(); + CPPUNIT_ASSERT(pPdfTextPage); + + int nChars = pPdfTextPage->countChars(); + + CPPUNIT_ASSERT_EQUAL(3, nChars); + + std::vector aChars(nChars); + for (int i = 0; i < nChars; i++) + aChars[i] = pPdfTextPage->getUnicode(i); + OUString aActualText(aChars.data(), aChars.size()); + + // Without the fix in place, this test would have failed with + // - Expected: ִبي + // - Actual : بִي + CPPUNIT_ASSERT_EQUAL(u"\u05B4\u0628\u064A"_ustr, aActualText); +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf150846) +{ + // Without the fix in place, this test would have failed with + // An uncaught exception of type com.sun.star.io.IOException + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf150846.txt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + std::unique_ptr pPdfTextPage = pPdfPage->getTextPage(); + CPPUNIT_ASSERT(pPdfTextPage); + + int nChars = pPdfTextPage->countChars(); + + CPPUNIT_ASSERT_EQUAL(5, nChars); + + std::vector aChars(nChars); + for (int i = 0; i < nChars; i++) + aChars[i] = pPdfTextPage->getUnicode(i); + OUString aActualText(aChars.data(), aChars.size()); + CPPUNIT_ASSERT_EQUAL(u"hello"_ustr, aActualText); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf103492) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf103492.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has two page. + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage1 = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage1); + + std::unique_ptr pPdfTextPage1 = pPdfPage1->getTextPage(); + CPPUNIT_ASSERT(pPdfTextPage1); + + int nChars1 = pPdfTextPage1->countChars(); + + // Without the fix in place, this test would have failed with + // - Expected: 15 + // - Actual : 18 + CPPUNIT_ASSERT_EQUAL(15, nChars1); + + std::vector aChars1(nChars1); + for (int i = 0; i < nChars1; i++) + aChars1[i] = pPdfTextPage1->getUnicode(i); + OUString aActualText1(aChars1.data(), aChars1.size()); + CPPUNIT_ASSERT_EQUAL(u"يوسف My name is"_ustr, aActualText1); + + std::unique_ptr pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1); + CPPUNIT_ASSERT(pPdfPage2); + + std::unique_ptr pPdfTextPage2 = pPdfPage2->getTextPage(); + CPPUNIT_ASSERT(pPdfTextPage2); + + int nChars2 = pPdfTextPage2->countChars(); + + CPPUNIT_ASSERT_EQUAL(15, nChars2); + + std::vector aChars2(nChars2); + for (int i = 0; i < nChars2; i++) + aChars2[i] = pPdfTextPage2->getUnicode(i); + OUString aActualText2(aChars2.data(), aChars2.size()); + CPPUNIT_ASSERT_EQUAL(u"My name is يوسف"_ustr, aActualText2); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf145274) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf145274.docx"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + auto pPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT(pPage); + + int nPageObjectCount = pPage->getObjectCount(); + + // Without the fix in place, this test would have failed with + // - Expected: 6 + // - Actual : 4 + CPPUNIT_ASSERT_EQUAL(6, nPageObjectCount); + + auto pTextPage = pPage->getTextPage(); + + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text) + continue; + + CPPUNIT_ASSERT_EQUAL(11.0, pPageObject->getFontSize()); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFTextRenderMode::Fill, pPageObject->getTextRenderMode()); + CPPUNIT_ASSERT_EQUAL(COL_RED, pPageObject->getFillColor()); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf156685) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf156685.docx"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + auto pPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT(pPage); + + int nPageObjectCount = pPage->getObjectCount(); + + CPPUNIT_ASSERT_EQUAL(9, nPageObjectCount); + + auto pTextPage = pPage->getTextPage(); + + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text) + continue; + + CPPUNIT_ASSERT_EQUAL(11.0, pPageObject->getFontSize()); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFTextRenderMode::Fill, pPageObject->getTextRenderMode()); + + // Without the fix in place, this test would have failed with + // - Expected: rgba[000000ff] + // - Actual : rgba[ffffffff] + CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPageObject->getFillColor()); + } +} + +/// Test writing ToUnicode CMAP for doubly encoded glyphs. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf66597_1) +{ +#if HAVE_MORE_FONTS + // This requires Amiri font, if it is missing the test will fail. + vcl::filter::PDFDocument aDocument; + load(u"tdf66597-1.odt", aDocument); + + { + // Get access to ToUnicode of the first font + vcl::filter::PDFObjectElement* pToUnicode = nullptr; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pName + = dynamic_cast(pObject->Lookup("BaseFont"_ostr)); + auto aName = pName->GetValue().copy(7); // skip the subset id + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected font name", "Amiri-Regular"_ostr, aName); + + auto pToUnicodeRef = dynamic_cast( + pObject->Lookup("ToUnicode"_ostr)); + CPPUNIT_ASSERT(pToUnicodeRef); + pToUnicode = pToUnicodeRef->LookupObject(); + break; + } + } + + CPPUNIT_ASSERT(pToUnicode); + auto pStream = pToUnicode->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream aObjectStream; + ZCodec aZCodec; + aZCodec.BeginCompression(); + pStream->GetMemory().Seek(0); + aZCodec.Decompress(pStream->GetMemory(), aObjectStream); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + aObjectStream.Seek(0); + // The <01> is glyph id, <2044> is code point. + // The document has two characters <2044><2215><2044>, but the font + // reuses the same glyph for U+2044 and U+2215 so we should have a single + // CMAP entry for the U+2044, and U+2215 will be handled with ActualText + // (tested below). + std::string aCmap("1 beginbfchar\n" + "<01> <2044>\n" + "endbfchar"); + std::string aData(static_cast(aObjectStream.GetData()), + aObjectStream.GetSize()); + auto nPos = aData.find(aCmap); + CPPUNIT_ASSERT(nPos != std::string::npos); + } + + { + auto aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + // Get page contents and stream. + auto pContents = aPages[0]->LookupObject("Contents"_ostr); + CPPUNIT_ASSERT(pContents); + auto pStream = pContents->GetStream(); + CPPUNIT_ASSERT(pStream); + auto& rObjectStream = pStream->GetMemory(); + + // Uncompress the stream. + SvMemoryStream aUncompressed; + ZCodec aZCodec; + aZCodec.BeginCompression(); + rObjectStream.Seek(0); + aZCodec.Decompress(rObjectStream, aUncompressed); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + + // Make sure the expected ActualText is present. + std::string aData(static_cast(aUncompressed.GetData()), + aUncompressed.GetSize()); + + std::string aActualText("/Span<(1), + nCount); + + aActualText = "/Span<>>"; + nPos = aData.find(aActualText); + CPPUNIT_ASSERT_MESSAGE("ActualText not found!", nPos != std::string::npos); + } +#endif +} + +/// Test writing ActualText for RTL many to one glyph to Unicode mapping. +// This requires Reem Kufi font, if it is missing the test will fail. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf66597_2) +{ +#if HAVE_MORE_FONTS + vcl::filter::PDFDocument aDocument; + load(u"tdf66597-2.odt", aDocument); + + { + // Get access to ToUnicode of the first font + vcl::filter::PDFObjectElement* pToUnicode = nullptr; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pName + = dynamic_cast(pObject->Lookup("BaseFont"_ostr)); + auto aName = pName->GetValue().copy(7); // skip the subset id + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected font name", "ReemKufi-Regular"_ostr, + aName); + + auto pToUnicodeRef = dynamic_cast( + pObject->Lookup("ToUnicode"_ostr)); + CPPUNIT_ASSERT(pToUnicodeRef); + pToUnicode = pToUnicodeRef->LookupObject(); + break; + } + } + + CPPUNIT_ASSERT(pToUnicode); + auto pStream = pToUnicode->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream aObjectStream; + ZCodec aZCodec; + aZCodec.BeginCompression(); + pStream->GetMemory().Seek(0); + aZCodec.Decompress(pStream->GetMemory(), aObjectStream); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + aObjectStream.Seek(0); + std::string aCmap("8 beginbfchar\n" + "<02> <0632>\n" + "<03> <0020>\n" + "<04> <0648>\n" + "<05> <0647>\n" + "<06> <062F>\n" + "<08> <062C>\n" + "<0A> <0628>\n" + "<0C> <0623>\n" + "endbfchar"); + std::string aData(static_cast(aObjectStream.GetData()), + aObjectStream.GetSize()); + auto nPos = aData.find(aCmap); + CPPUNIT_ASSERT(nPos != std::string::npos); + } + + { + auto aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + // Get page contents and stream. + auto pContents = aPages[0]->LookupObject("Contents"_ostr); + CPPUNIT_ASSERT(pContents); + auto pStream = pContents->GetStream(); + CPPUNIT_ASSERT(pStream); + auto& rObjectStream = pStream->GetMemory(); + + // Uncompress the stream. + SvMemoryStream aUncompressed; + ZCodec aZCodec; + aZCodec.BeginCompression(); + rObjectStream.Seek(0); + aZCodec.Decompress(rObjectStream, aUncompressed); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + + // Make sure the expected ActualText is present. + std::string aData(static_cast(aUncompressed.GetData()), + aUncompressed.GetSize()); + + std::vector aCodes({ "0632", "062C", "0628", "0623" }); + std::string aActualText("/Span<>>"; + nPos = aData.find(aActualText); + CPPUNIT_ASSERT_MESSAGE("ActualText not found for " + aCode, nPos != std::string::npos); + } + } +#endif +} + +/// Test writing ActualText for LTR many to one glyph to Unicode mapping. +// This requires Gentium Basic font, if it is missing the test will fail. +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf66597_3) +{ +#if HAVE_MORE_FONTS + vcl::filter::PDFDocument aDocument; + load(u"tdf66597-3.odt", aDocument); + + { + // Get access to ToUnicode of the first font + vcl::filter::PDFObjectElement* pToUnicode = nullptr; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pName + = dynamic_cast(pObject->Lookup("BaseFont"_ostr)); + auto aName = pName->GetValue().copy(7); // skip the subset id + CPPUNIT_ASSERT_EQUAL_MESSAGE("Unexpected font name", "GentiumBasic"_ostr, aName); + + auto pToUnicodeRef = dynamic_cast( + pObject->Lookup("ToUnicode"_ostr)); + CPPUNIT_ASSERT(pToUnicodeRef); + pToUnicode = pToUnicodeRef->LookupObject(); + break; + } + } + + CPPUNIT_ASSERT(pToUnicode); + auto pStream = pToUnicode->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream aObjectStream; + ZCodec aZCodec; + aZCodec.BeginCompression(); + pStream->GetMemory().Seek(0); + aZCodec.Decompress(pStream->GetMemory(), aObjectStream); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + aObjectStream.Seek(0); + std::string aCmap("2 beginbfchar\n" + "<01> <1ECB0331030B>\n" + "<05> <0020>\n" + "endbfchar"); + std::string aData(static_cast(aObjectStream.GetData()), + aObjectStream.GetSize()); + auto nPos = aData.find(aCmap); + CPPUNIT_ASSERT(nPos != std::string::npos); + } + + { + auto aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + // Get page contents and stream. + auto pContents = aPages[0]->LookupObject("Contents"_ostr); + CPPUNIT_ASSERT(pContents); + auto pStream = pContents->GetStream(); + CPPUNIT_ASSERT(pStream); + auto& rObjectStream = pStream->GetMemory(); + + // Uncompress the stream. + SvMemoryStream aUncompressed; + ZCodec aZCodec; + aZCodec.BeginCompression(); + rObjectStream.Seek(0); + aZCodec.Decompress(rObjectStream, aUncompressed); + CPPUNIT_ASSERT(aZCodec.EndCompression()); + + // Make sure the expected ActualText is present. + std::string aData(static_cast(aUncompressed.GetData()), + aUncompressed.GetSize()); + + std::string aActualText("/Span<>>"); + size_t nCount = 0; + size_t nPos = 0; + while ((nPos = aData.find(aActualText, nPos)) != std::string::npos) + { + nCount++; + nPos += aActualText.length(); + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("Number of ActualText entries does not match!", + static_cast(4), nCount); + } +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf105954) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + uno::Sequence aFilterData(comphelper::InitPropertySequence( + { { "ReduceImageResolution", uno::Any(true) }, + { "MaxImageResolution", uno::Any(static_cast(300)) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf105954.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // There is a single image on the page. + int nPageObjectCount = pPdfPage->getObjectCount(); + CPPUNIT_ASSERT_EQUAL(1, nPageObjectCount); + + // Check width of the image. + std::unique_ptr pPageObject = pPdfPage->getObject(/*index=*/0); + Size aMeta = pPageObject->getImageSize(*pPdfPage); + // This was 2000, i.e. the 'reduce to 300 DPI' request was ignored. + // This is now around 238 (228 on macOS). + CPPUNIT_ASSERT_LESS(static_cast(250), aMeta.getWidth()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157679) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + saveAsPDF(u"tdf157679.pptx"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 3 + // - Actual : 5 + CPPUNIT_ASSERT_EQUAL(3, pPdfPage->getObjectCount()); + + std::unique_ptr pTextPage = pPdfPage->getTextPage(); + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + // Check there are not Text objects + std::unique_ptr pPageObject = pPdfPage->getObject(i); + CPPUNIT_ASSERT(pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf128445) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + saveAsPDF(u"tdf128445.odp"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 7 + // - Actual : 6 + CPPUNIT_ASSERT_EQUAL(7, pPdfPage->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf128630) +{ + // FIXME: the DPI check should be removed when either (1) the test is fixed to work with + // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. + if (!IsDefaultDPI()) + return; + + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + saveAsPDF(u"tdf128630.odp"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + // Assert the size of the only bitmap on the page. + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image) + continue; + + std::unique_ptr pBitmap = pPageObject->getImageBitmap(); + CPPUNIT_ASSERT(pBitmap); + int nWidth = pBitmap->getWidth(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 466 + // - Actual : 289 + // i.e. the rotated + scaled arrow was more thin than it should be. + CPPUNIT_ASSERT_DOUBLES_EQUAL(466, nWidth, 1); + int nHeight = pBitmap->getHeight(); + CPPUNIT_ASSERT_EQUAL(nWidth, nHeight); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf106702) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf106702.odt"); + + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has two pages. + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + + // First page already has the correct image position. + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + int nExpected = 0; + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image) + continue; + + // Top, but upside down. + nExpected = pPageObject->getBounds().getMaxY(); + break; + } + + // Second page had an incorrect image position. + pPdfPage = pPdfDocument->openPage(/*nIndex=*/1); + CPPUNIT_ASSERT(pPdfPage); + int nActual = 0; + nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image) + continue; + + // Top, but upside down. + nActual = pPageObject->getBounds().getMaxY(); + break; + } + + // This failed, vertical pos is 818 points, was 1674 (outside visible page + // bounds). + CPPUNIT_ASSERT_EQUAL(nExpected, nActual); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf113143) +{ + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + uno::Sequence aFilterData(comphelper::InitPropertySequence({ + { "ExportNotesPages", uno::Any(true) }, + // ReduceImageResolution is on by default and that hides the bug we + // want to test. + { "ReduceImageResolution", uno::Any(false) }, + // Set a custom PDF version. + { "SelectPdfVersion", uno::Any(static_cast(16)) }, + })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf113143.odp"); + + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has two pages. + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + + // First has the original (larger) image. + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + int nLarger = 0; + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image) + continue; + + nLarger = pPageObject->getBounds().getWidth(); + break; + } + + // Second page has the scaled (smaller) image. + pPdfPage = pPdfDocument->openPage(/*nIndex=*/1); + CPPUNIT_ASSERT(pPdfPage); + int nSmaller = 0; + nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image) + continue; + + nSmaller = pPageObject->getBounds().getWidth(); + break; + } + + // This failed, both were 319, now nSmaller is 169. + CPPUNIT_ASSERT_LESS(nLarger, nSmaller); + + // The following check used to fail in the past, header was "%PDF-1.5": + maMemory.Seek(0); + OString aExpectedHeader("%PDF-1.6"_ostr); + OString aHeader(read_uInt8s_ToOString(maMemory, aExpectedHeader.getLength())); + CPPUNIT_ASSERT_EQUAL(aExpectedHeader, aHeader); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testForcePoint71) +{ + // I just care it doesn't crash + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"forcepoint71.key"); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testForcePoint80) +{ + // printing asserted in SwCellFrame::FindStartEndOfRowSpanCell + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"forcepoint80-1.rtf"); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testForcePoint3) +{ + // printing asserted in SwFrame::GetNextSctLeaf() + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"flowframe_null_ptr_deref.sample"); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf84283) +{ + // Without the fix in place, this test would have crashed + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf84283.doc"); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115262) +{ + aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export"); + saveAsPDF(u"tdf115262.ods"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(8, pPdfDocument->getPageCount()); + + // Get the 6th page. + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/5); + CPPUNIT_ASSERT(pPdfPage); + + // Look up the position of the first image and the 400th row. + std::unique_ptr pTextPage = pPdfPage->getTextPage(); + int nPageObjectCount = pPdfPage->getObjectCount(); + int nFirstImageTop = 0; + int nRowTop = 0; + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + // Top, but upside down. + float fTop = pPageObject->getBounds().getMaxY(); + + if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Image) + { + nFirstImageTop = fTop; + } + else if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Text) + { + OUString sText = pPageObject->getText(pTextPage); + if (sText == "400") + nRowTop = fTop; + } + } + // Make sure that the top of the "400" is below the top of the image (in + // bottom-right-corner-based PDF coordinates). + // This was: expected less than 144, actual is 199. + CPPUNIT_ASSERT_LESS(nFirstImageTop, nRowTop); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf121962) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf121962.odt"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + // Get the first page + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + std::unique_ptr pTextPage = pPdfPage->getTextPage(); + + // Make sure the table sum is displayed as "0", not faulty expression. + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text) + continue; + OUString sText = pPageObject->getText(pTextPage); + CPPUNIT_ASSERT(sText != "** Expression is faulty **"); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf139065) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf139065.odt"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 15 + // - Actual : 6 + CPPUNIT_ASSERT_EQUAL(15, pPdfPage->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf157816.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + vcl::filter::PDFObjectElement* pDocument(nullptr); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Document") + { + pDocument = pObject1; + } + } + } + CPPUNIT_ASSERT(pDocument); + + auto pKidsD = dynamic_cast(pDocument->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD); + // assume there are no MCID ref at this level + auto pKidsDv = pKidsD->GetElements(); + auto pRefKidD2 = dynamic_cast(pKidsDv[2]); + CPPUNIT_ASSERT(pRefKidD2); + auto pObjectD2 = pRefKidD2->LookupObject(); + CPPUNIT_ASSERT(pObjectD2); + auto pTypeD2 = dynamic_cast(pObjectD2->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD2->GetValue()); + auto pSD2 = dynamic_cast(pObjectD2->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Text#20body"_ostr, pSD2->GetValue()); + + auto pKidsD2 = dynamic_cast(pObjectD2->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD2); + auto pKidsD2v = pKidsD2->GetElements(); + auto pRefKidD20 = dynamic_cast(pKidsD2v[0]); + // MCID for text + CPPUNIT_ASSERT(!pRefKidD20); + auto pRefKidD21 = dynamic_cast(pKidsD2v[1]); + // MCID for text + CPPUNIT_ASSERT(!pRefKidD21); + + auto pRefKidD22 = dynamic_cast(pKidsD2v[2]); + CPPUNIT_ASSERT(pRefKidD22); + auto pObjectD22 = pRefKidD22->LookupObject(); + CPPUNIT_ASSERT(pObjectD22); + auto pTypeD22 = dynamic_cast(pObjectD22->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD22->GetValue()); + auto pSD22 = dynamic_cast(pObjectD22->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD22->GetValue()); + { + auto pKids = dynamic_cast(pObjectD22->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"Error: Reference source not found"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(95.143, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(674.589, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + // this changed to the end of the text, not the start of the fly + CPPUNIT_ASSERT_DOUBLES_EQUAL(187.207, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(688.389, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD23 = dynamic_cast(pKidsD2v[3]); + CPPUNIT_ASSERT(pRefKidD23); + auto pObjectD23 = pRefKidD23->LookupObject(); + CPPUNIT_ASSERT(pObjectD23); + auto pTypeD23 = dynamic_cast(pObjectD23->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD23->GetValue()); + auto pSD23 = dynamic_cast(pObjectD23->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD23->GetValue()); + { + auto pKids = dynamic_cast(pObjectD23->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"Error: Reference source not found"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(660.789, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(146.157, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(674.589, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD24 = dynamic_cast(pKidsD2v[4]); + CPPUNIT_ASSERT(pRefKidD24); + auto pObjectD24 = pRefKidD24->LookupObject(); + CPPUNIT_ASSERT(pObjectD24); + auto pTypeD24 = dynamic_cast(pObjectD24->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD24->GetValue()); + auto pSD24 = dynamic_cast(pObjectD24->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD24->GetValue()); + { + auto pKids = dynamic_cast(pObjectD24->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"Error: Reference source not found"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(146.093, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(660.789, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(179.457, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(674.589, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD25 = dynamic_cast(pKidsD2v[5]); + CPPUNIT_ASSERT(pRefKidD25); + auto pObjectD25 = pRefKidD25->LookupObject(); + CPPUNIT_ASSERT(pObjectD25); + auto pTypeD25 = dynamic_cast(pObjectD25->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD25->GetValue()); + auto pSD25 = dynamic_cast(pObjectD25->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD25->GetValue()); + { + auto pKids = dynamic_cast(pObjectD25->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"Error: Reference source not found"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(646.989, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(174.757, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(660.789, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD26 = dynamic_cast(pKidsD2v[6]); + CPPUNIT_ASSERT(pRefKidD26); + auto pObjectD26 = pRefKidD26->LookupObject(); + CPPUNIT_ASSERT(pObjectD26); + auto pTypeD26 = dynamic_cast(pObjectD26->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD26->GetValue()); + auto pSD26 = dynamic_cast(pObjectD26->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD26->GetValue()); + { + auto pKids = dynamic_cast(pObjectD26->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"Error: Reference source not found"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(633.189, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + CPPUNIT_ASSERT_DOUBLES_EQUAL(86.807, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(646.989, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD27 = dynamic_cast(pKidsD2v[7]); + // MCID for text + CPPUNIT_ASSERT(!pRefKidD27); + + // the problem was that in addition to the 5 links with SE there were 3 more + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(static_cast(5), pAnnots->GetElements().size()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf157816Link) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"LinkWithFly.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + vcl::filter::PDFObjectElement* pDocument(nullptr); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Document") + { + pDocument = pObject1; + } + } + } + CPPUNIT_ASSERT(pDocument); + + auto pKidsD = dynamic_cast(pDocument->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD); + // assume there are no MCID ref at this level + auto pKidsDv = pKidsD->GetElements(); + auto pRefKidD0 = dynamic_cast(pKidsDv[0]); + CPPUNIT_ASSERT(pRefKidD0); + auto pObjectD0 = pRefKidD0->LookupObject(); + CPPUNIT_ASSERT(pObjectD0); + auto pTypeD0 = dynamic_cast(pObjectD0->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD0->GetValue()); + auto pSD0 = dynamic_cast(pObjectD0->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pSD0->GetValue()); + + auto pKidsD0 = dynamic_cast(pObjectD0->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD0); + auto pKidsD0v = pKidsD0->GetElements(); + + auto pRefKidD00 = dynamic_cast(pKidsD0v[0]); + CPPUNIT_ASSERT(pRefKidD00); + auto pObjectD00 = pRefKidD00->LookupObject(); + CPPUNIT_ASSERT(pObjectD00); + auto pTypeD00 = dynamic_cast(pObjectD00->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD00->GetValue()); + auto pSD00 = dynamic_cast(pObjectD00->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD00->GetValue()); + { + auto pKids = dynamic_cast(pObjectD00->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://www.mozilla.org/en-US/firefox/119.0/releasenotes/"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(771.389, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + // this changed to the end of the text, not the start of the fly + CPPUNIT_ASSERT_DOUBLES_EQUAL(191.707, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(785.189, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD01 = dynamic_cast(pKidsD0v[1]); + CPPUNIT_ASSERT(pRefKidD01); + auto pObjectD01 = pRefKidD01->LookupObject(); + CPPUNIT_ASSERT(pObjectD01); + auto pTypeD01 = dynamic_cast(pObjectD01->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD01->GetValue()); + auto pSD01 = dynamic_cast(pObjectD01->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD01->GetValue()); + { + auto pKids = dynamic_cast(pObjectD01->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://www.mozilla.org/en-US/firefox/119.0/releasenotes/"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(387.843, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(771.389, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + // this changed to the end of the text, not the start of the fly + CPPUNIT_ASSERT_DOUBLES_EQUAL(534.407, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(785.189, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD02 = dynamic_cast(pKidsD0v[2]); + CPPUNIT_ASSERT(pRefKidD02); + auto pObjectD02 = pRefKidD02->LookupObject(); + CPPUNIT_ASSERT(pObjectD02); + auto pTypeD02 = dynamic_cast(pObjectD02->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD02->GetValue()); + auto pSD02 = dynamic_cast(pObjectD02->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Figure"_ostr, pSD02->GetValue()); + + auto pRefKidD1 = dynamic_cast(pKidsDv[1]); + CPPUNIT_ASSERT(pRefKidD1); + auto pObjectD1 = pRefKidD1->LookupObject(); + CPPUNIT_ASSERT(pObjectD1); + auto pTypeD1 = dynamic_cast(pObjectD1->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD1->GetValue()); + auto pSD1 = dynamic_cast(pObjectD1->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pSD1->GetValue()); + + auto pKidsD1 = dynamic_cast(pObjectD1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD1); + auto pKidsD1v = pKidsD1->GetElements(); + + auto pRefKidD10 = dynamic_cast(pKidsD1v[0]); + CPPUNIT_ASSERT(pRefKidD10); + auto pObjectD10 = pRefKidD10->LookupObject(); + CPPUNIT_ASSERT(pObjectD10); + auto pTypeD10 = dynamic_cast(pObjectD10->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD10->GetValue()); + auto pSD10 = dynamic_cast(pObjectD10->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD10->GetValue()); + { + auto pKids = dynamic_cast(pObjectD10->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://www.mozilla.org/en-US/firefox/118.0/releasenotes/"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(56.693, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(757.589, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + // this changed to the end of the text, not the start of the fly + CPPUNIT_ASSERT_DOUBLES_EQUAL(191.707, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(771.389, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKidD11 = dynamic_cast(pKidsD1v[1]); + CPPUNIT_ASSERT(pRefKidD11); + auto pObjectD11 = pRefKidD11->LookupObject(); + CPPUNIT_ASSERT(pObjectD11); + auto pTypeD11 = dynamic_cast(pObjectD11->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD11->GetValue()); + auto pSD11 = dynamic_cast(pObjectD11->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pSD11->GetValue()); + { + auto pKids = dynamic_cast(pObjectD11->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://www.mozilla.org/en-US/firefox/118.0/releasenotes/"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + auto pStructParent = dynamic_cast( + pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); // every link must have it! + auto pARect + = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pARect); + const auto& rElements = pARect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + const auto* pNumL = dynamic_cast(rElements[0]); + CPPUNIT_ASSERT(pNumL); + CPPUNIT_ASSERT_DOUBLES_EQUAL(387.843, pNumL->GetValue(), 1e-3); + const auto* pNumT = dynamic_cast(rElements[1]); + CPPUNIT_ASSERT(pNumT); + CPPUNIT_ASSERT_DOUBLES_EQUAL(757.589, pNumT->GetValue(), 1e-3); + const auto* pNumR = dynamic_cast(rElements[2]); + CPPUNIT_ASSERT(pNumR); + // this changed to the end of the text, not the start of the fly + CPPUNIT_ASSERT_DOUBLES_EQUAL(534.407, pNumR->GetValue(), 1e-3); + const auto* pNumB = dynamic_cast(rElements[3]); + CPPUNIT_ASSERT(pNumB); + CPPUNIT_ASSERT_DOUBLES_EQUAL(771.389, pNumB->GetValue(), 1e-3); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + // the problem was that in addition to the 4 links with SE there was 1 more + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(static_cast(4), pAnnots->GetElements().size()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf115967) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf115967.odt"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + // Get the first page + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + std::unique_ptr pTextPage = pPdfPage->getTextPage(); + + // Make sure the elements inside a formula in a RTL document are exported + // LTR ( m=750abc ) and not RTL ( m=057cba ) + int nPageObjectCount = pPdfPage->getObjectCount(); + OUString sText; + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Text) + continue; + OUString sChar = pPageObject->getText(pTextPage); + sText += o3tl::trim(sChar); + } + CPPUNIT_ASSERT_EQUAL(OUString("m=750abc"), sText); +} + +} // end anonymous namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx new file mode 100644 index 0000000000..d2811f32fb --- /dev/null +++ b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx @@ -0,0 +1,4858 @@ +/* -*- 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 + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace ::com::sun::star; + +namespace +{ +/// Tests the PDF export filter. +class PdfExportTest2 : public UnoApiTest +{ +protected: + utl::MediaDescriptor aMediaDescriptor; + +public: + PdfExportTest2() + : UnoApiTest("/vcl/qa/cppunit/pdfexport/data/") + { + } + + void saveAsPDF(std::u16string_view rFile); + void load(std::u16string_view rFile, vcl::filter::PDFDocument& rDocument, + bool bUseTaggedPDF = true); +}; + +void PdfExportTest2::saveAsPDF(std::u16string_view rFile) +{ + // Import the bugdoc and export as PDF. + loadFromFile(rFile); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); +} + +void PdfExportTest2::load(std::u16string_view rFile, vcl::filter::PDFDocument& rDocument, + bool bUseTaggedPDF) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "UseTaggedPDF", uno::Any(bUseTaggedPDF) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(rFile); + + // Parse the export result. + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(rDocument.Read(aStream)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf124272) +{ + // Import the bugdoc and export as PDF. + vcl::filter::PDFDocument aDocument; + load(u"tdf124272.odt", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // The page has a stream. + 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()); + + OString aBitmap("Q q 299.899 782.189 m\n" + "55.2 435.889 l 299.899 435.889 l 299.899 782.189 l\n" + "h"_ostr); + + auto pStart = static_cast(aUncompressed.GetData()); + const char* pEnd = pStart + aUncompressed.GetSize(); + auto it = std::search(pStart, pEnd, aBitmap.getStr(), aBitmap.getStr() + aBitmap.getLength()); + CPPUNIT_ASSERT(it != pEnd); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf121615) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf121615.odt", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Get access to the only image on the only page. + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + vcl::filter::PDFStreamElement* pStream = pXObject->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + + // Load the embedded image. + rObjectStream.Seek(0); + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic; + sal_uInt16 format; + ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"import", rObjectStream, + GRFILTER_FORMAT_DONTKNOW, &format); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); + + // The image should be grayscale 8bit JPEG. + sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME); + CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND); + CPPUNIT_ASSERT_EQUAL(jpegFormat, format); + BitmapEx aBitmap = aGraphic.GetBitmapEx(); + CPPUNIT_ASSERT_EQUAL(tools::Long(200), aBitmap.GetSizePixel().Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(300), aBitmap.GetSizePixel().Height()); + CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat()); + // tdf#121615 was caused by broken handling of data width with 8bit color, + // so the test image has some black in the bottomright corner, check it's there + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 0)); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(0, 299)); + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(199, 0)); + CPPUNIT_ASSERT_EQUAL(COL_BLACK, aBitmap.GetPixelColor(199, 299)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf141171) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf141171.odt", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Get access to the only image on the only page. + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + vcl::filter::PDFStreamElement* pStream = pXObject->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + + // Load the embedded image. + rObjectStream.Seek(0); + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic; + sal_uInt16 format; + ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"import", rObjectStream, + GRFILTER_FORMAT_DONTKNOW, &format); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); + + // The image should be grayscale 8bit JPEG. + sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME); + CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND); + CPPUNIT_ASSERT_EQUAL(jpegFormat, format); + BitmapEx aBitmap = aGraphic.GetBitmapEx(); + Size aSize = aBitmap.GetSizePixel(); + CPPUNIT_ASSERT_EQUAL(tools::Long(878), aSize.Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(127), aSize.Height()); + CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N8_BPP, aBitmap.getPixelFormat()); + + for (tools::Long nX = 0; nX < aSize.Width(); ++nX) + { + for (tools::Long nY = 0; nY < aSize.Height(); ++nY) + { + // Check all pixels in the image are white + // Without the fix in place, this test would have failed with + // - Expected: Color: R:255 G:255 B:255 A:0 + // - Actual : Color: R:0 G:0 B:0 A:0 + CPPUNIT_ASSERT_EQUAL(COL_WHITE, aBitmap.GetPixelColor(nX, nY)); + } + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf129085) +{ + vcl::filter::PDFDocument aDocument; + load(u"tdf129085.docx", aDocument); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Get access to the only image on the only page. + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + + // Without the fix in place, this test would have failed here + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject + = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + vcl::filter::PDFStreamElement* pStream = pXObject->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + + // Load the embedded image. + rObjectStream.Seek(0); + GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); + Graphic aGraphic; + sal_uInt16 format; + ErrCode bResult = rFilter.ImportGraphic(aGraphic, u"import", rObjectStream, + GRFILTER_FORMAT_DONTKNOW, &format); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); + + sal_uInt16 jpegFormat = rFilter.GetImportFormatNumberForShortName(JPG_SHORTNAME); + CPPUNIT_ASSERT(jpegFormat != GRFILTER_FORMAT_NOTFOUND); + CPPUNIT_ASSERT_EQUAL(jpegFormat, format); + BitmapEx aBitmap = aGraphic.GetBitmapEx(); + CPPUNIT_ASSERT_EQUAL(tools::Long(884), aBitmap.GetSizePixel().Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(925), aBitmap.GetSizePixel().Height()); + CPPUNIT_ASSERT_EQUAL(vcl::PixelFormat::N24_BPP, aBitmap.getPixelFormat()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTocLink) +{ + // Load the Writer document. + loadFromFile(u"toc-link.fodt"); + + // Update the ToC. + uno::Reference xDocumentIndexesSupplier(mxComponent, + uno::UNO_QUERY); + CPPUNIT_ASSERT(xDocumentIndexesSupplier.is()); + + uno::Reference xToc( + xDocumentIndexesSupplier->getDocumentIndexes()->getByIndex(0), uno::UNO_QUERY); + CPPUNIT_ASSERT(xToc.is()); + + xToc->refresh(); + + // Save as PDF. + save("writer_pdf_Export"); + + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Ensure there is a link on the first page (in the ToC). + // Without the accompanying fix in place, this test would have failed, as the page contained no + // links. + CPPUNIT_ASSERT(pPdfPage->hasLinks()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReduceSmallImage) +{ + // Load the Writer document. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"reduce-small-image.fodt"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + std::unique_ptr pPageObject = pPdfPage->getObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pPageObject->getType()); + + // Make sure we don't scale down a tiny bitmap. + std::unique_ptr pBitmap = pPageObject->getImageBitmap(); + CPPUNIT_ASSERT(pBitmap); + int nWidth = pBitmap->getWidth(); + int nHeight = pBitmap->getHeight(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 16 + // - Actual : 6 + // i.e. the image was scaled down to 300 DPI, even if it had tiny size. + CPPUNIT_ASSERT_EQUAL(16, nWidth); + CPPUNIT_ASSERT_EQUAL(16, nHeight); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf114256) +{ + aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export"); + saveAsPDF(u"tdf114256.ods"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 13 + // - Actual : 0 + CPPUNIT_ASSERT_EQUAL(13, pPdfPage->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf150931) +{ + aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export"); + saveAsPDF(u"tdf150931.ods"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + int nPageObjectCount = pPdfPage->getObjectCount(); + // Without the fix in place, this test would have failed with + // - Expected: 15 + // - Actual : 16 + CPPUNIT_ASSERT_EQUAL(16, nPageObjectCount); + + int nYellowPathCount = 0; + int nBlackPathCount = 0; + int nGrayPathCount = 0; + int nRedPathCount = 0; + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPdfPageObject = pPdfPage->getObject(i); + if (pPdfPageObject->getType() != vcl::pdf::PDFPageObjectType::Path) + continue; + + int nSegments = pPdfPageObject->getPathSegmentCount(); + CPPUNIT_ASSERT_EQUAL(5, nSegments); + + if (pPdfPageObject->getFillColor() == COL_YELLOW) + ++nYellowPathCount; + else if (pPdfPageObject->getFillColor() == COL_BLACK) + ++nBlackPathCount; + else if (pPdfPageObject->getFillColor() == COL_GRAY) + ++nGrayPathCount; + else if (pPdfPageObject->getFillColor() == COL_LIGHTRED) + ++nRedPathCount; + } + + CPPUNIT_ASSERT_EQUAL(3, nYellowPathCount); + CPPUNIT_ASSERT_EQUAL(3, nRedPathCount); + CPPUNIT_ASSERT_EQUAL(3, nGrayPathCount); + CPPUNIT_ASSERT_EQUAL(3, nBlackPathCount); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf147027) +{ + // FIXME: the DPI check should be removed when either (1) the test is fixed to work with + // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. + if (!IsDefaultDPI()) + return; + + // Load the Calc document. + aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export"); + saveAsPDF(u"tdf147027.ods"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 778 + // - Actual : 40 + CPPUNIT_ASSERT_EQUAL(778, pPdfPage->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf135346) +{ + // Load the Calc document. + aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export"); + saveAsPDF(u"tdf135346.ods"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 56 + // - Actual : 0 + CPPUNIT_ASSERT_EQUAL(56, pPdfPage->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf147164) +{ + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + saveAsPDF(u"tdf147164.odp"); + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/1); + CPPUNIT_ASSERT(pPdfPage); + + // Without the fix in place, this test would have failed with + // - Expected: 22 + // - Actual : 16 + CPPUNIT_ASSERT_EQUAL(22, pPdfPage->getObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReduceImage) +{ + // Load the Writer document. + loadFromFile(u"reduce-image.fodt"); + + // Save as PDF. + uno::Reference xFactory = getMultiServiceFactory(); + uno::Reference xFilter( + xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY); + uno::Reference xExporter(xFilter, uno::UNO_QUERY); + xExporter->setSourceDocument(mxComponent); + + SvFileStream aOutputStream(maTempFile.GetURL(), StreamMode::WRITE); + uno::Reference xOutputStream(new utl::OStreamWrapper(aOutputStream)); + + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "ReduceImageResolution", uno::Any(false) } })); + + // This is intentionally in an "unlucky" order, output stream comes before filter data. + uno::Sequence aDescriptor(comphelper::InitPropertySequence({ + { "FilterName", uno::Any(OUString("writer_pdf_Export")) }, + { "OutputStream", uno::Any(xOutputStream) }, + { "FilterData", uno::Any(aFilterData) }, + })); + xFilter->filter(aDescriptor); + aOutputStream.Close(); + + // Parse the PDF: get the image. + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + std::unique_ptr pPageObject = pPdfPage->getObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pPageObject->getType()); + + // Make sure we don't scale down a bitmap. + std::unique_ptr pBitmap = pPageObject->getImageBitmap(); + CPPUNIT_ASSERT(pBitmap); + int nWidth = pBitmap->getWidth(); + int nHeight = pBitmap->getHeight(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 160 + // - Actual : 6 + // i.e. the image was scaled down even with ReduceImageResolution=false. + CPPUNIT_ASSERT_EQUAL(160, nWidth); + CPPUNIT_ASSERT_EQUAL(160, nHeight); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testLinkWrongPage) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + saveAsPDF(u"link-wrong-page.odp"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has 2 pages. + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + + // First page should have 1 link (2nd slide, 1st was hidden). + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // Without the accompanying fix in place, this test would have failed, as the link of the first + // page went to the second page due to the hidden first slide. + CPPUNIT_ASSERT(pPdfPage->hasLinks()); + + // Second page should have no links (3rd slide). + std::unique_ptr pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1); + CPPUNIT_ASSERT(pPdfPage2); + CPPUNIT_ASSERT(!pPdfPage2->hasLinks()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testLinkWrongPagePartial) +{ + // Given a Draw document with 3 pages, a link on the 2nd page: + // When exporting that the 2nd and 3rd page to pdf: + uno::Sequence aFilterData = { + comphelper::makePropertyValue("PageRange", OUString("2-3")), + }; + aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export"); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"link-wrong-page-partial.odg"); + + // Then make sure the we have a link on the 1st page, but not on the 2nd one: + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + // Without the accompanying fix in place, this test would have failed, as the link was on the + // 2nd page instead. + CPPUNIT_ASSERT(pPdfPage->hasLinks()); + std::unique_ptr pPdfPage2 = pPdfDocument->openPage(/*nIndex=*/1); + CPPUNIT_ASSERT(pPdfPage2); + CPPUNIT_ASSERT(!pPdfPage2->hasLinks()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPageRange) +{ + // Given a document with 3 pages: + // When exporting that document to PDF, skipping the first page: + aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export"); + aMediaDescriptor["FilterOptions"] + <<= OUString("{\"PageRange\":{\"type\":\"string\",\"value\":\"2-\"}}"); + saveAsPDF(u"link-wrong-page-partial.odg"); + + // Then make sure the resulting PDF has 2 pages: + std::unique_ptr pPdfDocument = parsePDFExport(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 3 + // i.e. FilterOptions was ignored. + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testLargePage) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export"); + saveAsPDF(u"6m-wide.odg"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has 1 page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + // Check the value (not the unit) of the page size. + basegfx::B2DSize aSize = pPdfDocument->getPageSize(0); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 8503.94 + // - Actual : 17007.875 + // i.e. the value for 600 cm was larger than the 14 400 limit set in the spec. + CPPUNIT_ASSERT_DOUBLES_EQUAL(8503.94, aSize.getWidth(), 0.01); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfImageResourceInlineXObjectRef) +{ + // Create an empty document. + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xText = xTextDocument->getText(); + uno::Reference xCursor = xText->createTextCursor(); + + // Insert the PDF image. + uno::Reference xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference xGraphicObject( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + OUString aURL = createFileURL(u"pdf-image-resource-inline-xobject-ref.pdf"); + xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL)); + uno::Reference xShape(xGraphicObject, uno::UNO_QUERY); + xShape->setSize(awt::Size(1000, 1000)); + uno::Reference xTextContent(xGraphicObject, uno::UNO_QUERY); + xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false); + + // Save as PDF. + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + // Make sure that the page -> form -> form has a child image. + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + std::unique_ptr pPageObject = pPdfPage->getObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType()); + // 2: white background and the actual object. + CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount()); + std::unique_ptr pFormObject = pPageObject->getFormObject(1); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pFormObject->getType()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 0 + // i.e. the sub-form was missing its image. + CPPUNIT_ASSERT_EQUAL(1, pFormObject->getFormObjectCount()); + + // Check if the inner form object (original page object in the pdf image) has the correct + // rotation. + std::unique_ptr pInnerFormObject = pFormObject->getFormObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pInnerFormObject->getType()); + CPPUNIT_ASSERT_EQUAL(1, pInnerFormObject->getFormObjectCount()); + std::unique_ptr pImage = pInnerFormObject->getFormObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pImage->getType()); + basegfx::B2DHomMatrix aMat = pInnerFormObject->getMatrix(); + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate = 0; + double fShearX = 0; + aMat.decompose(aScale, aTranslate, fRotate, fShearX); + int nRotateDeg = basegfx::rad2deg(fRotate); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: -90 + // - Actual : 0 + // i.e. rotation was lost on pdf export. + CPPUNIT_ASSERT_EQUAL(-90, nRotateDeg); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testDefaultVersion) +{ + // Create an empty document. + mxComponent = loadFromDesktop("private:factory/swriter"); + + // Save as PDF. + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + std::unique_ptr pPdfDocument = parsePDFExport(); + int nFileVersion = pPdfDocument->getFileVersion(); + CPPUNIT_ASSERT_EQUAL(17, nFileVersion); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testVersion15) +{ + // Create an empty document. + mxComponent = loadFromDesktop("private:factory/swriter"); + + // Save as PDF. + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + uno::Sequence aFilterData(comphelper::InitPropertySequence( + { { "SelectPdfVersion", uno::Any(static_cast(15)) } })); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + std::unique_ptr pPdfDocument = parsePDFExport(); + int nFileVersion = pPdfDocument->getFileVersion(); + CPPUNIT_ASSERT_EQUAL(15, nFileVersion); +} + +// Check round-trip of importing and exporting the PDF with PDFium filter, +// which imports the PDF document as multiple PDFs as graphic object. +// Each page in the document has one PDF graphic object which content is +// the corresponding page in the PDF. When such a document is exported, +// the PDF graphic gets embedded into the exported PDF document (as a +// Form XObject). +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testMultiPagePDF) +{ +// setenv only works on unix based systems +#ifndef _WIN32 + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + setenv("LO_IMPORT_USE_PDFIUM", "1", false); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + unsetenv("LO_IMPORT_USE_PDFIUM"); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"SimpleMultiPagePDF.pdf", aDocument); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(3), aPages.size()); + + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + + CPPUNIT_ASSERT_EQUAL(static_cast(3), + pXObjects->GetItems().size()); // 3 PDFs as Form XObjects + + std::vector rIDs; + for (auto const& rPair : pXObjects->GetItems()) + { + rIDs.push_back(rPair.first); + } + + // Let's check the embedded PDF pages - just make sure the size differs, + // which should indicate we don't have 3 times the same page. + + { // embedded PDF page 1 + vcl::filter::PDFObjectElement* pXObject1 = pXObjects->LookupObject(rIDs[0]); + CPPUNIT_ASSERT(pXObject1); + CPPUNIT_ASSERT_EQUAL("Im21"_ostr, rIDs[0]); + + auto pSubtype1 + = dynamic_cast(pXObject1->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype1); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pSubtype1->GetValue()); + + auto pXObjectResources + = dynamic_cast(pXObject1->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast( + pXObjectResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm + = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + rObjectStream.Seek(STREAM_SEEK_TO_BEGIN); + + // Just check that the size of the page stream is what is expected. + CPPUNIT_ASSERT_EQUAL(sal_uInt64(230), rObjectStream.remainingSize()); + } + + { // embedded PDF page 2 + vcl::filter::PDFObjectElement* pXObject2 = pXObjects->LookupObject(rIDs[1]); + CPPUNIT_ASSERT(pXObject2); + CPPUNIT_ASSERT_EQUAL("Im27"_ostr, rIDs[1]); + + auto pSubtype2 + = dynamic_cast(pXObject2->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype2); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pSubtype2->GetValue()); + + auto pXObjectResources + = dynamic_cast(pXObject2->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast( + pXObjectResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm + = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + rObjectStream.Seek(STREAM_SEEK_TO_BEGIN); + + // Just check that the size of the page stream is what is expected + CPPUNIT_ASSERT_EQUAL(sal_uInt64(309), rObjectStream.remainingSize()); + } + + { // embedded PDF page 3 + vcl::filter::PDFObjectElement* pXObject3 = pXObjects->LookupObject(rIDs[2]); + CPPUNIT_ASSERT(pXObject3); + CPPUNIT_ASSERT_EQUAL("Im5"_ostr, rIDs[2]); + + auto pSubtype3 + = dynamic_cast(pXObject3->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype3); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pSubtype3->GetValue()); + + auto pXObjectResources + = dynamic_cast(pXObject3->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pXObjectResources); + auto pXObjectForms = dynamic_cast( + pXObjectResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjectForms); + vcl::filter::PDFObjectElement* pForm + = pXObjectForms->LookupObject(pXObjectForms->GetItems().begin()->first); + CPPUNIT_ASSERT(pForm); + + vcl::filter::PDFStreamElement* pStream = pForm->GetStream(); + CPPUNIT_ASSERT(pStream); + SvMemoryStream& rObjectStream = pStream->GetMemory(); + rObjectStream.Seek(STREAM_SEEK_TO_BEGIN); + + // Just check that the size of the page stream is what is expected + CPPUNIT_ASSERT_EQUAL(sal_uInt64(193), rObjectStream.remainingSize()); + } +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFormFontName) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"form-font-name.odt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // The page has one annotation. + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); + std::unique_ptr pAnnot = pPdfPage->getAnnotation(0); + + // Examine the default appearance. + CPPUNIT_ASSERT(pAnnot->hasKey("DA"_ostr)); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFObjectType::String, pAnnot->getValueType("DA"_ostr)); + OUString aDA = pAnnot->getString("DA"_ostr); + + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0 0 0 rg /TiRo 12 Tf + // - Actual : 0 0 0 rg /F2 12 Tf + // i.e. Liberation Serif was exposed as a form font as-is, without picking the closest built-in + // font. + CPPUNIT_ASSERT_EQUAL(OUString("0 0 0 rg /TiRo 12 Tf"), aDA); +} + +// Check we don't have duplicated objects when we reexport the PDF multiple +// times or the size will exponentially increase over time. +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReexportPDF) +{ +// setenv only works on unix based systems +#ifndef _WIN32 + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + setenv("LO_IMPORT_USE_PDFIUM", "1", false); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + unsetenv("LO_IMPORT_USE_PDFIUM"); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"PDFWithImages.pdf", aDocument); + + // Assert that the XObject in the page resources dictionary is a reference XObject. + std::vector aPages = aDocument.GetPages(); + + // The document has 2 pages. + CPPUNIT_ASSERT_EQUAL(size_t(2), aPages.size()); + + // PAGE 1 + { + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + + std::vector rIDs; + for (auto const& rPair : pXObjects->GetItems()) + rIDs.push_back(rPair.first); + + CPPUNIT_ASSERT_EQUAL(size_t(2), rIDs.size()); + + std::vector aBitmapRefs1; + std::vector aBitmapRefs2; + + { + // FORM object 1 + OString aID = rIDs[0]; + CPPUNIT_ASSERT_EQUAL("Im14"_ostr, aID); + vcl::filter::PDFObjectElement* pXObject = pXObjects->LookupObject(aID); + CPPUNIT_ASSERT(pXObject); + + auto pSubtype + = dynamic_cast(pXObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pSubtype->GetValue()); + + auto pInnerResources = dynamic_cast( + pXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pInnerResources); + auto pInnerXObjects = dynamic_cast( + pInnerResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pInnerXObjects); + CPPUNIT_ASSERT_EQUAL(size_t(1), pInnerXObjects->GetItems().size()); + OString aInnerObjectID = pInnerXObjects->GetItems().begin()->first; + CPPUNIT_ASSERT_EQUAL("Im15"_ostr, aInnerObjectID); + + vcl::filter::PDFObjectElement* pInnerXObject + = pInnerXObjects->LookupObject(aInnerObjectID); + CPPUNIT_ASSERT(pInnerXObject); + + auto pInnerSubtype + = dynamic_cast(pInnerXObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pInnerSubtype); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pInnerSubtype->GetValue()); + + auto pInnerInnerResources = dynamic_cast( + pInnerXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pInnerInnerResources); + auto pInnerInnerXObjects = dynamic_cast( + pInnerInnerResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pInnerInnerXObjects); + CPPUNIT_ASSERT_EQUAL(size_t(2), pInnerInnerXObjects->GetItems().size()); + + std::vector aBitmapIDs1; + for (auto const& rPair : pInnerInnerXObjects->GetItems()) + aBitmapIDs1.push_back(rPair.first); + + { + CPPUNIT_ASSERT_EQUAL("Im11"_ostr, aBitmapIDs1[0]); + auto pRef = dynamic_cast( + pInnerInnerXObjects->LookupElement(aBitmapIDs1[0])); + CPPUNIT_ASSERT(pRef); + aBitmapRefs1.push_back(pRef->GetObjectValue()); + CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue()); + + vcl::filter::PDFObjectElement* pBitmap + = pInnerInnerXObjects->LookupObject(aBitmapIDs1[0]); + CPPUNIT_ASSERT(pBitmap); + auto pBitmapSubtype + = dynamic_cast(pBitmap->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pBitmapSubtype); + CPPUNIT_ASSERT_EQUAL("Image"_ostr, pBitmapSubtype->GetValue()); + } + { + CPPUNIT_ASSERT_EQUAL("Im5"_ostr, aBitmapIDs1[1]); + auto pRef = dynamic_cast( + pInnerInnerXObjects->LookupElement(aBitmapIDs1[1])); + CPPUNIT_ASSERT(pRef); + aBitmapRefs1.push_back(pRef->GetObjectValue()); + CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue()); + + vcl::filter::PDFObjectElement* pBitmap + = pInnerInnerXObjects->LookupObject(aBitmapIDs1[1]); + CPPUNIT_ASSERT(pBitmap); + auto pBitmapSubtype + = dynamic_cast(pBitmap->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pBitmapSubtype); + CPPUNIT_ASSERT_EQUAL("Image"_ostr, pBitmapSubtype->GetValue()); + } + } + + { + // FORM object 2 + OString aID = rIDs[1]; + CPPUNIT_ASSERT_EQUAL("Im5"_ostr, aID); + vcl::filter::PDFObjectElement* pXObject = pXObjects->LookupObject(aID); + CPPUNIT_ASSERT(pXObject); + + auto pSubtype + = dynamic_cast(pXObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pSubtype->GetValue()); + + auto pInnerResources = dynamic_cast( + pXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pInnerResources); + auto pInnerXObjects = dynamic_cast( + pInnerResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pInnerXObjects); + CPPUNIT_ASSERT_EQUAL(size_t(1), pInnerXObjects->GetItems().size()); + OString aInnerObjectID = pInnerXObjects->GetItems().begin()->first; + CPPUNIT_ASSERT_EQUAL("Im6"_ostr, aInnerObjectID); + + vcl::filter::PDFObjectElement* pInnerXObject + = pInnerXObjects->LookupObject(aInnerObjectID); + CPPUNIT_ASSERT(pInnerXObject); + + auto pInnerSubtype + = dynamic_cast(pInnerXObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pInnerSubtype); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pInnerSubtype->GetValue()); + + auto pInnerInnerResources = dynamic_cast( + pInnerXObject->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pInnerInnerResources); + auto pInnerInnerXObjects = dynamic_cast( + pInnerInnerResources->LookupElement("XObject"_ostr)); + CPPUNIT_ASSERT(pInnerInnerXObjects); + CPPUNIT_ASSERT_EQUAL(size_t(2), pInnerInnerXObjects->GetItems().size()); + + std::vector aBitmapIDs2; + for (auto const& rPair : pInnerInnerXObjects->GetItems()) + aBitmapIDs2.push_back(rPair.first); + + { + CPPUNIT_ASSERT_EQUAL("Im11"_ostr, aBitmapIDs2[0]); + auto pRef = dynamic_cast( + pInnerInnerXObjects->LookupElement(aBitmapIDs2[0])); + CPPUNIT_ASSERT(pRef); + aBitmapRefs2.push_back(pRef->GetObjectValue()); + CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue()); + + vcl::filter::PDFObjectElement* pBitmap + = pInnerInnerXObjects->LookupObject(aBitmapIDs2[0]); + CPPUNIT_ASSERT(pBitmap); + auto pBitmapSubtype + = dynamic_cast(pBitmap->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pBitmapSubtype); + CPPUNIT_ASSERT_EQUAL("Image"_ostr, pBitmapSubtype->GetValue()); + } + { + CPPUNIT_ASSERT_EQUAL("Im5"_ostr, aBitmapIDs2[1]); + auto pRef = dynamic_cast( + pInnerInnerXObjects->LookupElement(aBitmapIDs2[1])); + CPPUNIT_ASSERT(pRef); + aBitmapRefs2.push_back(pRef->GetObjectValue()); + CPPUNIT_ASSERT_EQUAL(0, pRef->GetGenerationValue()); + + vcl::filter::PDFObjectElement* pBitmap + = pInnerInnerXObjects->LookupObject(aBitmapIDs2[1]); + CPPUNIT_ASSERT(pBitmap); + auto pBitmapSubtype + = dynamic_cast(pBitmap->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pBitmapSubtype); + CPPUNIT_ASSERT_EQUAL("Image"_ostr, pBitmapSubtype->GetValue()); + } + } + // Ref should point to the same bitmap + CPPUNIT_ASSERT_EQUAL(aBitmapRefs1[0], aBitmapRefs2[0]); + CPPUNIT_ASSERT_EQUAL(aBitmapRefs1[1], aBitmapRefs2[1]); + } + +#endif +} + +// Check we correctly copy more complex resources (Fonts describing +// glyphs in recursive arrays) to the target PDF +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testReexportDocumentWithComplexResources) +{ +// setenv only works on unix based systems +#ifndef _WIN32 + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + setenv("LO_IMPORT_USE_PDFIUM", "1", false); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + unsetenv("LO_IMPORT_USE_PDFIUM"); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"ComplexContentDictionary.pdf", aDocument); + + // Assert that the XObject in the page resources dictionary is a reference XObject. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(1), aPages.size()); + + // Go directly to the Font object (24 0) (number could change if we change how PDF export works) + auto pFont = aDocument.LookupObject(24); + CPPUNIT_ASSERT(pFont); + + // Check it is the Font object (Type = Font) + auto pName = dynamic_cast( + pFont->GetDictionary()->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT(pName); + CPPUNIT_ASSERT_EQUAL("Font"_ostr, pName->GetValue()); + + // Check BaseFont is what we expect + auto pBaseFont = dynamic_cast( + pFont->GetDictionary()->LookupElement("BaseFont"_ostr)); + CPPUNIT_ASSERT(pBaseFont); + CPPUNIT_ASSERT_EQUAL("HOTOMR+Calibri,Italic"_ostr, pBaseFont->GetValue()); + + // Check and get the W array + auto pWArray = dynamic_cast( + pFont->GetDictionary()->LookupElement("W"_ostr)); + CPPUNIT_ASSERT(pWArray); + CPPUNIT_ASSERT_EQUAL(size_t(26), pWArray->GetElements().size()); + + // Check the content of W array + // ObjectCopier didn't copy this array correctly and the document + // had glyphs at the wrong places + { + // first 2 elements + auto pNumberAtIndex0 = dynamic_cast(pWArray->GetElement(0)); + CPPUNIT_ASSERT(pNumberAtIndex0); + CPPUNIT_ASSERT_EQUAL(3.0, pNumberAtIndex0->GetValue()); + + auto pArrayAtIndex1 = dynamic_cast(pWArray->GetElement(1)); + CPPUNIT_ASSERT(pArrayAtIndex1); + CPPUNIT_ASSERT_EQUAL(size_t(1), pArrayAtIndex1->GetElements().size()); + + { + auto pNumber + = dynamic_cast(pArrayAtIndex1->GetElement(0)); + CPPUNIT_ASSERT(pNumber); + CPPUNIT_ASSERT_EQUAL(226.0, pNumber->GetValue()); + } + + // last 2 elements + auto pNumberAtIndex24 + = dynamic_cast(pWArray->GetElement(24)); + CPPUNIT_ASSERT(pNumberAtIndex24); + CPPUNIT_ASSERT_EQUAL(894.0, pNumberAtIndex24->GetValue()); + + auto pArrayAtIndex25 = dynamic_cast(pWArray->GetElement(25)); + CPPUNIT_ASSERT(pArrayAtIndex25); + CPPUNIT_ASSERT_EQUAL(size_t(2), pArrayAtIndex25->GetElements().size()); + + { + auto pNumber1 + = dynamic_cast(pArrayAtIndex25->GetElement(0)); + CPPUNIT_ASSERT(pNumber1); + CPPUNIT_ASSERT_EQUAL(303.0, pNumber1->GetValue()); + + auto pNumber2 + = dynamic_cast(pArrayAtIndex25->GetElement(1)); + CPPUNIT_ASSERT(pNumber2); + CPPUNIT_ASSERT_EQUAL(303.0, pNumber2->GetValue()); + } + } +#endif +} + +// Tests that at export the PDF has the PDF/UA metadata properly set +// when we enable PDF/UA support. +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfUaMetadata) +{ + // Import a basic document (document doesn't really matter) + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"BrownFoxLazyDog.odt"); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + auto* pCatalog = aDocument.GetCatalog(); + CPPUNIT_ASSERT(pCatalog); + auto* pCatalogDictionary = pCatalog->GetDictionary(); + CPPUNIT_ASSERT(pCatalogDictionary); + auto* pMetadataObject = pCatalogDictionary->LookupObject("Metadata"_ostr); + CPPUNIT_ASSERT(pMetadataObject); + auto* pMetadataDictionary = pMetadataObject->GetDictionary(); + auto* pType = dynamic_cast( + pMetadataDictionary->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT(pType); + CPPUNIT_ASSERT_EQUAL("Metadata"_ostr, pType->GetValue()); + + auto* pStreamObject = pMetadataObject->GetStream(); + CPPUNIT_ASSERT(pStreamObject); + auto& rStream = pStreamObject->GetMemory(); + rStream.Seek(0); + + // Search for the PDF/UA marker in the metadata + + tools::XmlWalker aWalker; + CPPUNIT_ASSERT(aWalker.open(&rStream)); + CPPUNIT_ASSERT_EQUAL("xmpmeta"_ostr, aWalker.name()); + + bool bPdfUaMarkerFound = false; + OString aPdfUaPart; + + aWalker.children(); + while (aWalker.isValid()) + { + if (aWalker.name() == "RDF" + && aWalker.namespaceHref() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#") + { + aWalker.children(); + while (aWalker.isValid()) + { + if (aWalker.name() == "Description" + && aWalker.namespaceHref() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#") + { + aWalker.children(); + while (aWalker.isValid()) + { + if (aWalker.name() == "part" + && aWalker.namespaceHref() == "http://www.aiim.org/pdfua/ns/id/") + { + aPdfUaPart = aWalker.content(); + bPdfUaMarkerFound = true; + } + aWalker.next(); + } + aWalker.parent(); + } + aWalker.next(); + } + aWalker.parent(); + } + aWalker.next(); + } + aWalker.parent(); + + CPPUNIT_ASSERT(bPdfUaMarkerFound); + CPPUNIT_ASSERT_EQUAL("1"_ostr, aPdfUaPart); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf139736) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) }, + { "SelectPdfVersion", uno::Any(sal_Int32(17)) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf139736-1.odt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(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(aUncompressed.GetData()); + const char* const pEnd = pStart + aUncompressed.GetSize(); + + enum + { + Default, + Artifact, + ArtifactProps1, + ArtifactProps2, + 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, "/Artifact <<")) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state); + // check header/footer properties + CPPUNIT_ASSERT_EQUAL(std::string_view("/Type/Pagination"), line.substr(12)); + state = ArtifactProps1; + ++nArtifacts; + } + else if (state == ArtifactProps1) + { + CPPUNIT_ASSERT_EQUAL(std::string_view("/Subtype/Header"), line); + state = ArtifactProps2; + } + else if (state == ArtifactProps2 && line == ">> BDC") + { + state = Artifact; + } + else if (line == "/Standard<>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(1), nTagged); // text in body + // 1 image and 1 frame and 1 header text; arbitrary number of aux stuff like borders + CPPUNIT_ASSERT(nArtifacts >= 3); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf152231) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) }, + { "ExportNotesInMargin", uno::Any(true) }, + { "SelectPdfVersion", uno::Any(sal_Int32(17)) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf152231.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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< 1) // first line is expected "0.1 w" + { + CPPUNIT_ASSERT_MESSAGE("unexpected content outside MCS", state != Default); + } + } + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state); + CPPUNIT_ASSERT(nTagged >= 12); // text in body + // 1 annotation + CPPUNIT_ASSERT(nArtifacts >= 1); + + auto nPara(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(rDocElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "Standard") + { + ++nPara; + auto pKids = dynamic_cast(pObject->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids); + // one problem was that some StructElem were missing kids + CPPUNIT_ASSERT(!pKids->GetElements().empty()); + } + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(12), nPara); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf152235) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + // Enable PDF/UA + uno::Sequence aFilterData(comphelper::InitPropertySequence( + { { "PDFUACompliance", uno::Any(true) }, + { "Watermark", uno::Any(OUString("kendy")) }, + // need to set a font to avoid assertions about missing "Helvetica" + { "WatermarkFontName", uno::Any(OUString("Liberation Sans")) }, + { "SelectPdfVersion", uno::Any(sal_Int32(17)) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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 (o3tl::starts_with(line, "/Artifact ")) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state); + state = Artifact; + ++nArtifacts; + } + else if (o3tl::starts_with(line, "/Standard< 1) // first line is expected "0.1 w" + { + CPPUNIT_ASSERT_MESSAGE("unexpected content outside MCS", state != Default); + } + } + } + CPPUNIT_ASSERT_EQUAL_MESSAGE("unclosed MCS", Default, state); + CPPUNIT_ASSERT(nTagged >= 0); // text in body + CPPUNIT_ASSERT(nArtifacts >= 2); // 1 watermark + 1 other thing +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf149140) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"TableTH_test_LibreOfficeWriter7.3.3_HeaderRow-HeadersInTopRow.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + int nTH(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(rDocElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "TH") + { + int nTable(0); + auto pAttrs + = dynamic_cast(pObject->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAttrs != nullptr); + for (const auto& rAttrRef : pAttrs->GetElements()) + { + auto pAttrDict = dynamic_cast(rAttrRef); + CPPUNIT_ASSERT(pAttrDict != nullptr); + auto pOwner = dynamic_cast( + pAttrDict->LookupElement("O"_ostr)); + CPPUNIT_ASSERT(pOwner != nullptr); + if (pOwner->GetValue() == "Table") + { + auto pScope = dynamic_cast( + pAttrDict->LookupElement("Scope"_ostr)); + CPPUNIT_ASSERT(pScope != nullptr); + CPPUNIT_ASSERT_EQUAL("Column"_ostr, pScope->GetValue()); + ++nTable; + } + } + CPPUNIT_ASSERT_EQUAL(int(1), nTable); + ++nTH; + } + } + } + CPPUNIT_ASSERT_EQUAL(int(6), nTH); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testNestedSection) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"nestedsection.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // the assert needs 2 follows to reproduce => 3 pages + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(3), aPages.size()); + + auto nDoc(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Document") + { + auto pKids1 + = dynamic_cast(pObject1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1); + // assume there are no MCID ref at this level + auto pKids1v = pKids1->GetElements(); + auto pRefKid10 = dynamic_cast(pKids1v[0]); + CPPUNIT_ASSERT(pRefKid10); + auto pObject10 = pRefKid10->LookupObject(); + CPPUNIT_ASSERT(pObject10); + auto pType10 + = dynamic_cast(pObject10->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType10->GetValue()); + auto pS10 = dynamic_cast(pObject10->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Sect"_ostr, pS10->GetValue()); + + auto pKids10 + = dynamic_cast(pObject10->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids10); + // assume there are no MCID ref at this level + auto pKids10v = pKids10->GetElements(); + + auto pRefKid100 = dynamic_cast(pKids10v[0]); + CPPUNIT_ASSERT(pRefKid100); + auto pObject100 = pRefKid100->LookupObject(); + CPPUNIT_ASSERT(pObject100); + auto pType100 + = dynamic_cast(pObject100->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType100->GetValue()); + auto pS100 + = dynamic_cast(pObject100->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS100->GetValue()); + + auto pRefKid101 = dynamic_cast(pKids10v[1]); + CPPUNIT_ASSERT(pRefKid101); + auto pObject101 = pRefKid101->LookupObject(); + CPPUNIT_ASSERT(pObject101); + auto pType101 + = dynamic_cast(pObject101->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType101->GetValue()); + auto pS101 + = dynamic_cast(pObject101->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS101->GetValue()); + + auto pRefKid102 = dynamic_cast(pKids10v[2]); + CPPUNIT_ASSERT(pRefKid102); + auto pObject102 = pRefKid102->LookupObject(); + CPPUNIT_ASSERT(pObject102); + auto pType102 + = dynamic_cast(pObject102->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType102->GetValue()); + auto pS102 + = dynamic_cast(pObject102->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Sect"_ostr, pS102->GetValue()); + + auto pKids102 + = dynamic_cast(pObject102->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids102); + // assume there are no MCID ref at this level + auto pKids102v = pKids102->GetElements(); + + auto pRefKid1020 = dynamic_cast(pKids102v[0]); + CPPUNIT_ASSERT(pRefKid1020); + auto pObject1020 = pRefKid1020->LookupObject(); + CPPUNIT_ASSERT(pObject1020); + auto pType1020 + = dynamic_cast(pObject1020->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1020->GetValue()); + auto pS1020 + = dynamic_cast(pObject1020->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS1020->GetValue()); + + CPPUNIT_ASSERT_EQUAL(size_t(1), pKids102v.size()); + + auto pRefKid103 = dynamic_cast(pKids10v[3]); + CPPUNIT_ASSERT(pRefKid103); + auto pObject103 = pRefKid103->LookupObject(); + CPPUNIT_ASSERT(pObject103); + auto pType103 + = dynamic_cast(pObject103->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType103->GetValue()); + auto pS103 + = dynamic_cast(pObject103->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS103->GetValue()); + + auto pRefKid104 = dynamic_cast(pKids10v[4]); + CPPUNIT_ASSERT(pRefKid104); + auto pObject104 = pRefKid104->LookupObject(); + CPPUNIT_ASSERT(pObject104); + auto pType104 + = dynamic_cast(pObject104->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType104->GetValue()); + auto pS104 + = dynamic_cast(pObject104->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS104->GetValue()); + + CPPUNIT_ASSERT_EQUAL(size_t(5), pKids10v.size()); + + auto pRefKid11 = dynamic_cast(pKids1v[1]); + CPPUNIT_ASSERT(pRefKid11); + auto pObject11 = pRefKid11->LookupObject(); + CPPUNIT_ASSERT(pObject11); + auto pType11 + = dynamic_cast(pObject11->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType11->GetValue()); + auto pS11 = dynamic_cast(pObject11->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS11->GetValue()); + + CPPUNIT_ASSERT_EQUAL(size_t(2), pKids1v.size()); + ++nDoc; + } + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nDoc); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157817) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"SimpleTOC.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(2), aPages.size()); + + vcl::filter::PDFObjectElement* pTOC(nullptr); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "TOC") + { + pTOC = pObject1; + } + } + } + CPPUNIT_ASSERT(pTOC); + + auto pKidsT = dynamic_cast(pTOC->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT); + // assume there are no MCID ref at this level + auto pKidsTv = pKidsT->GetElements(); + auto pRefKidT0 = dynamic_cast(pKidsTv[0]); + CPPUNIT_ASSERT(pRefKidT0); + auto pObjectT0 = pRefKidT0->LookupObject(); + CPPUNIT_ASSERT(pObjectT0); + auto pTypeT0 = dynamic_cast(pObjectT0->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT0->GetValue()); + auto pST0 = dynamic_cast(pObjectT0->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Caption"_ostr, pST0->GetValue()); + + auto pKidsT0 = dynamic_cast(pObjectT0->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT0); + auto pKidsT0v = pKidsT0->GetElements(); + auto pRefKidT00 = dynamic_cast(pKidsT0v[0]); + CPPUNIT_ASSERT(pRefKidT00); + auto pObjectT00 = pRefKidT00->LookupObject(); + CPPUNIT_ASSERT(pObjectT00); + auto pTypeT00 = dynamic_cast(pObjectT00->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT00->GetValue()); + auto pST00 = dynamic_cast(pObjectT00->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Contents#20Heading"_ostr, pST00->GetValue()); + + auto pRefKidT1 = dynamic_cast(pKidsTv[1]); + CPPUNIT_ASSERT(pRefKidT1); + auto pObjectT1 = pRefKidT1->LookupObject(); + CPPUNIT_ASSERT(pObjectT1); + auto pTypeT1 = dynamic_cast(pObjectT1->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT1->GetValue()); + auto pST1 = dynamic_cast(pObjectT1->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("TOCI"_ostr, pST1->GetValue()); + + auto pKidsT1 = dynamic_cast(pObjectT1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT1); + auto pKidsT1v = pKidsT1->GetElements(); + + auto pRefKidT10 = dynamic_cast(pKidsT1v[0]); + CPPUNIT_ASSERT(pRefKidT10); + auto pObjectT10 = pRefKidT10->LookupObject(); + CPPUNIT_ASSERT(pObjectT10); + auto pTypeT10 = dynamic_cast(pObjectT10->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT10->GetValue()); + auto pST10 = dynamic_cast(pObjectT10->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Contents#201"_ostr, pST10->GetValue()); + + auto pKidsT10 = dynamic_cast(pObjectT10->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT10); + auto pKidsT10v = pKidsT10->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pKidsT10v.size()); + + // there is one and only one Link + auto pRefKidT100 = dynamic_cast(pKidsT10v[0]); + CPPUNIT_ASSERT(pRefKidT100); + auto pObjectT100 = pRefKidT100->LookupObject(); + CPPUNIT_ASSERT(pObjectT100); + auto pTypeT100 = dynamic_cast(pObjectT100->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT100->GetValue()); + auto pST100 = dynamic_cast(pObjectT100->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pST100->GetValue()); + + auto pRefKidT2 = dynamic_cast(pKidsTv[1]); + CPPUNIT_ASSERT(pRefKidT2); + auto pObjectT2 = pRefKidT2->LookupObject(); + CPPUNIT_ASSERT(pObjectT2); + auto pTypeT2 = dynamic_cast(pObjectT2->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT2->GetValue()); + auto pST2 = dynamic_cast(pObjectT2->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("TOCI"_ostr, pST2->GetValue()); + + auto pKidsT2 = dynamic_cast(pObjectT2->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT2); + auto pKidsT2v = pKidsT2->GetElements(); + + auto pRefKidT20 = dynamic_cast(pKidsT2v[0]); + CPPUNIT_ASSERT(pRefKidT20); + auto pObjectT20 = pRefKidT20->LookupObject(); + CPPUNIT_ASSERT(pObjectT20); + auto pTypeT20 = dynamic_cast(pObjectT20->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT20->GetValue()); + auto pST20 = dynamic_cast(pObjectT20->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Contents#201"_ostr, pST20->GetValue()); + + auto pKidsT20 = dynamic_cast(pObjectT20->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT20); + auto pKidsT20v = pKidsT20->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pKidsT20v.size()); + + // there is one and only one Link + auto pRefKidT200 = dynamic_cast(pKidsT20v[0]); + CPPUNIT_ASSERT(pRefKidT200); + auto pObjectT200 = pRefKidT200->LookupObject(); + CPPUNIT_ASSERT(pObjectT200); + auto pTypeT200 = dynamic_cast(pObjectT200->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT200->GetValue()); + auto pST200 = dynamic_cast(pObjectT200->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pST200->GetValue()); + + auto pRefKidT3 = dynamic_cast(pKidsTv[1]); + CPPUNIT_ASSERT(pRefKidT3); + auto pObjectT3 = pRefKidT3->LookupObject(); + CPPUNIT_ASSERT(pObjectT3); + auto pTypeT3 = dynamic_cast(pObjectT3->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT3->GetValue()); + auto pST3 = dynamic_cast(pObjectT3->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("TOCI"_ostr, pST3->GetValue()); + + auto pKidsT3 = dynamic_cast(pObjectT3->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT3); + auto pKidsT3v = pKidsT3->GetElements(); + + auto pRefKidT30 = dynamic_cast(pKidsT3v[0]); + CPPUNIT_ASSERT(pRefKidT30); + auto pObjectT30 = pRefKidT30->LookupObject(); + CPPUNIT_ASSERT(pObjectT30); + auto pTypeT30 = dynamic_cast(pObjectT30->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT30->GetValue()); + auto pST30 = dynamic_cast(pObjectT30->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Contents#201"_ostr, pST30->GetValue()); + + auto pKidsT30 = dynamic_cast(pObjectT30->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsT30); + auto pKidsT30v = pKidsT30->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), pKidsT30v.size()); + + // there is one and only one Link + auto pRefKidT300 = dynamic_cast(pKidsT30v[0]); + CPPUNIT_ASSERT(pRefKidT300); + auto pObjectT300 = pRefKidT300->LookupObject(); + CPPUNIT_ASSERT(pObjectT300); + auto pTypeT300 = dynamic_cast(pObjectT300->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeT300->GetValue()); + auto pST300 = dynamic_cast(pObjectT300->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pST300->GetValue()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf135638) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"image-shape.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + int nFigure(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(rDocElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "Figure") + { + auto pAttrDict + = dynamic_cast(pObject->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAttrDict != nullptr); + auto pOwner = dynamic_cast( + pAttrDict->LookupElement("O"_ostr)); + CPPUNIT_ASSERT(pOwner != nullptr); + CPPUNIT_ASSERT_EQUAL("Layout"_ostr, pOwner->GetValue()); + auto pBBox = dynamic_cast( + pAttrDict->LookupElement("BBox"_ostr)); + CPPUNIT_ASSERT(pBBox != nullptr); + if (nFigure == 0) + { + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 139.5, + dynamic_cast(pBBox->GetElements()[0]) + ->GetValue(), + 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 480.3, + dynamic_cast(pBBox->GetElements()[1]) + ->GetValue(), + 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 472.5, + dynamic_cast(pBBox->GetElements()[2]) + ->GetValue(), + 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 735.3, + dynamic_cast(pBBox->GetElements()[3]) + ->GetValue(), + 0.01); + } + else + { + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 178.45, + dynamic_cast(pBBox->GetElements()[0]) + ->GetValue(), + 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 318.65, + dynamic_cast(pBBox->GetElements()[1]) + ->GetValue(), + 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 326.35, + dynamic_cast(pBBox->GetElements()[2]) + ->GetValue(), + 0.01); + CPPUNIT_ASSERT_DOUBLES_EQUAL( + 382.55, + dynamic_cast(pBBox->GetElements()[3]) + ->GetValue(), + 0.01); + } + ++nFigure; + } + } + } + // the first one is a Writer image, 2nd one SdrRectObj + CPPUNIT_ASSERT_EQUAL(int(2), nFigure); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157703) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"LO_Lbl_Lbody_bug_report.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + vcl::filter::PDFObjectElement* pDocument(nullptr); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Document") + { + pDocument = pObject1; + } + } + } + CPPUNIT_ASSERT(pDocument); + + auto pKidsD = dynamic_cast(pDocument->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD); + // assume there are no MCID ref at this level + auto pKidsDv = pKidsD->GetElements(); + auto pRefKidD0 = dynamic_cast(pKidsDv[0]); + CPPUNIT_ASSERT(pRefKidD0); + auto pObjectD0 = pRefKidD0->LookupObject(); + CPPUNIT_ASSERT(pObjectD0); + auto pTypeD0 = dynamic_cast(pObjectD0->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD0->GetValue()); + auto pSD0 = dynamic_cast(pObjectD0->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("H1"_ostr, pSD0->GetValue()); + + auto pKidsD0 = dynamic_cast(pObjectD0->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD0); + auto pKidsD0v = pKidsD0->GetElements(); + auto pRefKidD00 = dynamic_cast(pKidsD0v[0]); + // MCID for label + CPPUNIT_ASSERT(!pRefKidD00); + + // MCID for text + auto pRefKidD01 = dynamic_cast(pKidsD0v[1]); + CPPUNIT_ASSERT(!pRefKidD01); + + auto pRefKidD1 = dynamic_cast(pKidsDv[1]); + CPPUNIT_ASSERT(pRefKidD1); + auto pObjectD1 = pRefKidD1->LookupObject(); + CPPUNIT_ASSERT(pObjectD1); + auto pTypeD1 = dynamic_cast(pObjectD1->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pTypeD1->GetValue()); + auto pSD1 = dynamic_cast(pObjectD1->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("H2"_ostr, pSD1->GetValue()); + + auto pKidsD1 = dynamic_cast(pObjectD1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKidsD1); + auto pKidsD1v = pKidsD1->GetElements(); + + // MCID for text + auto pRefKidD11 = dynamic_cast(pKidsD1v[0]); + CPPUNIT_ASSERT(!pRefKidD11); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testSpans) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"spanlist.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(2), aPages.size()); + + auto nDoc(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Document") + { + auto pKids1 + = dynamic_cast(pObject1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1); + // assume there are no MCID ref at this level + auto vKids1 = pKids1->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids1.size()); + auto pRefKid10 = dynamic_cast(vKids1[0]); + CPPUNIT_ASSERT(pRefKid10); + auto pObject10 = pRefKid10->LookupObject(); + CPPUNIT_ASSERT(pObject10); + auto pType10 + = dynamic_cast(pObject10->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType10->GetValue()); + auto pS10 = dynamic_cast(pObject10->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("L"_ostr, pS10->GetValue()); + + auto pKids10 + = dynamic_cast(pObject10->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids10); + // assume there are no MCID ref at this level + auto vKids10 = pKids10->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(4), vKids10.size()); + + auto pRefKid100 = dynamic_cast(vKids10[0]); + CPPUNIT_ASSERT(pRefKid100); + auto pObject100 = pRefKid100->LookupObject(); + CPPUNIT_ASSERT(pObject100); + auto pType100 + = dynamic_cast(pObject100->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType100->GetValue()); + auto pS100 + = dynamic_cast(pObject100->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS100->GetValue()); + + auto pKids100 + = dynamic_cast(pObject100->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids100); + // assume there are no MCID ref at this level + auto vKids100 = pKids100->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids100.size()); + + auto pRefKid1000 = dynamic_cast(vKids100[0]); + CPPUNIT_ASSERT(pRefKid1000); + auto pObject1000 = pRefKid1000->LookupObject(); + CPPUNIT_ASSERT(pObject1000); + auto pType1000 + = dynamic_cast(pObject1000->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1000->GetValue()); + auto pS1000 + = dynamic_cast(pObject1000->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS1000->GetValue()); + + auto pRefKid1001 = dynamic_cast(vKids100[1]); + CPPUNIT_ASSERT(pRefKid1001); + auto pObject1001 = pRefKid1001->LookupObject(); + CPPUNIT_ASSERT(pObject1001); + auto pType1001 + = dynamic_cast(pObject1001->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1001->GetValue()); + auto pS1001 + = dynamic_cast(pObject1001->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS1001->GetValue()); + auto pKids1001 + = dynamic_cast(pObject1001->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1001); + // assume there are no MCID ref at this level + auto vKids1001 = pKids1001->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1001.size()); + + auto pRefKid10010 = dynamic_cast(vKids1001[0]); + CPPUNIT_ASSERT(pRefKid10010); + auto pObject10010 = pRefKid10010->LookupObject(); + CPPUNIT_ASSERT(pObject10010); + auto pType10010 + = dynamic_cast(pObject10010->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType10010->GetValue()); + auto pS10010 + = dynamic_cast(pObject10010->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS10010->GetValue()); + auto pKids10010 + = dynamic_cast(pObject10010->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids10010); + // assume there are no MCID ref at this level + auto vKids10010 = pKids10010->GetElements(); + // only one span + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids10010.size()); + + auto pRefKid100100 = dynamic_cast(vKids10010[0]); + CPPUNIT_ASSERT(pRefKid100100); + auto pObject100100 = pRefKid100100->LookupObject(); + CPPUNIT_ASSERT(pObject100100); + auto pType100100 = dynamic_cast( + pObject100100->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType100100->GetValue()); + auto pS100100 + = dynamic_cast(pObject100100->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Span"_ostr, pS100100->GetValue()); + // this span exists because of lang + auto pLang100100 = dynamic_cast( + pObject100100->Lookup("Lang"_ostr)); + CPPUNIT_ASSERT_EQUAL("en-GB"_ostr, pLang100100->GetValue()); + + auto pRefKid101 = dynamic_cast(vKids10[1]); + CPPUNIT_ASSERT(pRefKid101); + auto pObject101 = pRefKid101->LookupObject(); + CPPUNIT_ASSERT(pObject101); + auto pType101 + = dynamic_cast(pObject101->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType101->GetValue()); + auto pS101 + = dynamic_cast(pObject101->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS101->GetValue()); + + auto pKids101 + = dynamic_cast(pObject101->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids101); + // assume there are no MCID ref at this level + auto vKids101 = pKids101->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids101.size()); + + auto pRefKid1010 = dynamic_cast(vKids101[0]); + CPPUNIT_ASSERT(pRefKid1010); + auto pObject1010 = pRefKid1010->LookupObject(); + CPPUNIT_ASSERT(pObject1010); + auto pType1010 + = dynamic_cast(pObject1010->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1010->GetValue()); + auto pS1010 + = dynamic_cast(pObject1010->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS1010->GetValue()); + + auto pRefKid1011 = dynamic_cast(vKids101[1]); + CPPUNIT_ASSERT(pRefKid1011); + auto pObject1011 = pRefKid1011->LookupObject(); + CPPUNIT_ASSERT(pObject1011); + auto pType1011 + = dynamic_cast(pObject1011->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1011->GetValue()); + auto pS1011 + = dynamic_cast(pObject1011->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS1011->GetValue()); + + auto pKids1011 + = dynamic_cast(pObject1011->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1011); + // assume there are no MCID ref at this level + auto vKids1011 = pKids1011->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1011.size()); + + auto pRefKid10110 = dynamic_cast(vKids1011[0]); + CPPUNIT_ASSERT(pRefKid10110); + auto pObject10110 = pRefKid10110->LookupObject(); + CPPUNIT_ASSERT(pObject10110); + auto pType10110 + = dynamic_cast(pObject10110->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType10110->GetValue()); + auto pS10110 + = dynamic_cast(pObject10110->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS10110->GetValue()); + auto pKids10110 + = dynamic_cast(pObject10110->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids10110); + auto vKids10110 = pKids10110->GetElements(); + // only MCIDs, no span + for (size_t i = 0; i < vKids10110.size(); ++i) + { + auto pKid = dynamic_cast(vKids10110[i]); + CPPUNIT_ASSERT(!pKid); + } + + auto pRefKid102 = dynamic_cast(vKids10[2]); + CPPUNIT_ASSERT(pRefKid102); + auto pObject102 = pRefKid102->LookupObject(); + CPPUNIT_ASSERT(pObject102); + auto pType102 + = dynamic_cast(pObject102->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType102->GetValue()); + auto pS102 + = dynamic_cast(pObject102->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS102->GetValue()); + + auto pKids102 + = dynamic_cast(pObject102->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids102); + // assume there are no MCID ref at this level + auto vKids102 = pKids102->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids102.size()); + + auto pRefKid1020 = dynamic_cast(vKids102[0]); + CPPUNIT_ASSERT(pRefKid1020); + auto pObject1020 = pRefKid1020->LookupObject(); + CPPUNIT_ASSERT(pObject1020); + auto pType1020 + = dynamic_cast(pObject1020->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1020->GetValue()); + auto pS1020 + = dynamic_cast(pObject1020->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS1020->GetValue()); + + auto pRefKid1021 = dynamic_cast(vKids102[1]); + CPPUNIT_ASSERT(pRefKid1021); + auto pObject1021 = pRefKid1021->LookupObject(); + CPPUNIT_ASSERT(pObject1021); + auto pType1021 + = dynamic_cast(pObject1021->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1021->GetValue()); + auto pS1021 + = dynamic_cast(pObject1021->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS1021->GetValue()); + + auto pKids1021 + = dynamic_cast(pObject1021->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1021); + // assume there are no MCID ref at this level + auto vKids1021 = pKids1021->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1021.size()); + + auto pRefKid10210 = dynamic_cast(vKids1021[0]); + CPPUNIT_ASSERT(pRefKid10210); + auto pObject10210 = pRefKid10210->LookupObject(); + CPPUNIT_ASSERT(pObject10210); + auto pType10210 + = dynamic_cast(pObject10210->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType10210->GetValue()); + auto pS10210 + = dynamic_cast(pObject10210->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS10210->GetValue()); + auto pKids10210 + = dynamic_cast(pObject10210->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids10210); + // assume there are no MCID ref at this level + auto vKids10210 = pKids10210->GetElements(); + // 2 span and a hyperlink + CPPUNIT_ASSERT_EQUAL(size_t(3), vKids10210.size()); + + auto pRefKid102100 = dynamic_cast(vKids10210[0]); + CPPUNIT_ASSERT(pRefKid102100); + auto pObject102100 = pRefKid102100->LookupObject(); + CPPUNIT_ASSERT(pObject102100); + auto pType102100 = dynamic_cast( + pObject102100->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType102100->GetValue()); + auto pS102100 + = dynamic_cast(pObject102100->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Span"_ostr, pS102100->GetValue()); + auto pKids102100 + = dynamic_cast(pObject102100->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids102100); + auto vKids102100 = pKids102100->GetElements(); + for (size_t i = 0; i < vKids102100.size(); ++i) + { + auto pKid = dynamic_cast(vKids102100[i]); + CPPUNIT_ASSERT(!pKid); + } + + auto pRefKid102101 = dynamic_cast(vKids10210[1]); + CPPUNIT_ASSERT(pRefKid102101); + auto pObject102101 = pRefKid102101->LookupObject(); + CPPUNIT_ASSERT(pObject102101); + auto pType102101 = dynamic_cast( + pObject102101->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType102101->GetValue()); + auto pS102101 + = dynamic_cast(pObject102101->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS102101->GetValue()); + auto pKids102101 + = dynamic_cast(pObject102101->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids102101); + auto vKids102101 = pKids102101->GetElements(); + auto nRef(0); + for (size_t i = 0; i < vKids102101.size(); ++i) + { + auto pKid = dynamic_cast(vKids102101[i]); + if (pKid) + { + ++nRef; // annotation + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + + auto pRefKid102102 = dynamic_cast(vKids10210[2]); + CPPUNIT_ASSERT(pRefKid102102); + auto pObject102102 = pRefKid102102->LookupObject(); + CPPUNIT_ASSERT(pObject102102); + auto pType102102 = dynamic_cast( + pObject102102->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType102102->GetValue()); + auto pS102102 + = dynamic_cast(pObject102102->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Span"_ostr, pS102102->GetValue()); + auto pKids102102 + = dynamic_cast(pObject102102->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids102102); + auto vKids102102 = pKids102102->GetElements(); + // there is a footnote + auto nFtn(0); + for (size_t i = 0; i < vKids102102.size(); ++i) + { + auto pKid = dynamic_cast(vKids102102[i]); + if (pKid) + { + auto pObject = pKid->LookupObject(); + CPPUNIT_ASSERT(pObject); + auto pType = dynamic_cast( + pObject->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType->GetValue()); + auto pS + = dynamic_cast(pObject->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS->GetValue()); + ++nFtn; + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nFtn); + + auto pRefKid103 = dynamic_cast(vKids10[3]); + CPPUNIT_ASSERT(pRefKid103); + auto pObject103 = pRefKid103->LookupObject(); + CPPUNIT_ASSERT(pObject103); + auto pType103 + = dynamic_cast(pObject103->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType103->GetValue()); + auto pS103 + = dynamic_cast(pObject103->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LI"_ostr, pS103->GetValue()); + + auto pKids103 + = dynamic_cast(pObject103->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids103); + // assume there are no MCID ref at this level + auto vKids103 = pKids103->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids103.size()); + + auto pRefKid1030 = dynamic_cast(vKids103[0]); + CPPUNIT_ASSERT(pRefKid1030); + auto pObject1030 = pRefKid1030->LookupObject(); + CPPUNIT_ASSERT(pObject1030); + auto pType1030 + = dynamic_cast(pObject1030->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1030->GetValue()); + auto pS1030 + = dynamic_cast(pObject1030->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS1030->GetValue()); + + auto pRefKid1031 = dynamic_cast(vKids103[1]); + CPPUNIT_ASSERT(pRefKid1031); + auto pObject1031 = pRefKid1031->LookupObject(); + CPPUNIT_ASSERT(pObject1031); + auto pType1031 + = dynamic_cast(pObject1031->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1031->GetValue()); + auto pS1031 + = dynamic_cast(pObject1031->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("LBody"_ostr, pS1031->GetValue()); + + auto pKids1031 + = dynamic_cast(pObject1031->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1031); + // assume there are no MCID ref at this level + auto vKids1031 = pKids1031->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1031.size()); + + auto pRefKid10310 = dynamic_cast(vKids1031[0]); + CPPUNIT_ASSERT(pRefKid10310); + auto pObject10310 = pRefKid10310->LookupObject(); + CPPUNIT_ASSERT(pObject10310); + auto pType10310 + = dynamic_cast(pObject10310->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType10310->GetValue()); + auto pS10310 + = dynamic_cast(pObject10310->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pS10310->GetValue()); + auto pKids10310 + = dynamic_cast(pObject10310->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids10310); + // assume there are no MCID ref at this level + auto vKids10310 = pKids10310->GetElements(); + // only one span, following a MCID for some strike-out gap + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids10310.size()); + + auto pRefKid103100 = dynamic_cast(vKids10310[0]); + CPPUNIT_ASSERT(!pRefKid103100); + + auto pRefKid103101 = dynamic_cast(vKids10310[1]); + CPPUNIT_ASSERT(pRefKid103101); + auto pObject103101 = pRefKid103101->LookupObject(); + CPPUNIT_ASSERT(pObject103101); + auto pType103101 = dynamic_cast( + pObject103101->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType103101->GetValue()); + auto pS103101 + = dynamic_cast(pObject103101->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Span"_ostr, pS103101->GetValue()); + auto pDictA103101 = dynamic_cast( + pObject103101->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pDictA103101 != nullptr); + CPPUNIT_ASSERT_EQUAL("Layout"_ostr, dynamic_cast( + pDictA103101->LookupElement("O"_ostr)) + ->GetValue()); + CPPUNIT_ASSERT_EQUAL("LineThrough"_ostr, + dynamic_cast( + pDictA103101->LookupElement("TextDecorationType"_ostr)) + ->GetValue()); + + // now the footnote container - following the list + auto pRefKid11 = dynamic_cast(vKids1[1]); + CPPUNIT_ASSERT(pRefKid11); + auto pObject11 = pRefKid11->LookupObject(); + CPPUNIT_ASSERT(pObject11); + auto pType11 + = dynamic_cast(pObject11->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType11->GetValue()); + auto pS11 = dynamic_cast(pObject11->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Div"_ostr, pS11->GetValue()); + + auto pKids11 + = dynamic_cast(pObject11->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids11); + // assume there are no MCID ref at this level + auto vKids11 = pKids11->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids11.size()); + + auto pRefKid110 = dynamic_cast(vKids11[0]); + CPPUNIT_ASSERT(pRefKid110); + auto pObject110 = pRefKid110->LookupObject(); + CPPUNIT_ASSERT(pObject110); + auto pType110 + = dynamic_cast(pObject110->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType110->GetValue()); + auto pS110 + = dynamic_cast(pObject110->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Note"_ostr, pS110->GetValue()); + + auto pKids110 + = dynamic_cast(pObject110->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids110); + // assume there are no MCID ref at this level + auto vKids110 = pKids110->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(2), vKids110.size()); + + auto pRefKid1100 = dynamic_cast(vKids110[0]); + CPPUNIT_ASSERT(pRefKid1100); + auto pObject1100 = pRefKid1100->LookupObject(); + CPPUNIT_ASSERT(pObject1100); + auto pType1100 + = dynamic_cast(pObject1100->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1100->GetValue()); + auto pS1100 + = dynamic_cast(pObject1100->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Lbl"_ostr, pS1100->GetValue()); + + auto pKids1100 + = dynamic_cast(pObject1100->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1100); + // assume there are no MCID ref at this level + auto vKids1100 = pKids1100->GetElements(); + CPPUNIT_ASSERT_EQUAL(size_t(1), vKids1100.size()); + + auto pRefKid11000 = dynamic_cast(vKids1100[0]); + CPPUNIT_ASSERT(pRefKid11000); + auto pObject11000 = pRefKid11000->LookupObject(); + CPPUNIT_ASSERT(pObject11000); + auto pType11000 + = dynamic_cast(pObject11000->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType11000->GetValue()); + auto pS11000 + = dynamic_cast(pObject11000->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS11000->GetValue()); + + auto pRefKid1101 = dynamic_cast(vKids110[1]); + CPPUNIT_ASSERT(pRefKid1101); + auto pObject1101 = pRefKid1101->LookupObject(); + CPPUNIT_ASSERT(pObject1101); + auto pType1101 + = dynamic_cast(pObject1101->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType1101->GetValue()); + auto pS1101 + = dynamic_cast(pObject1101->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Footnote"_ostr, pS1101->GetValue()); + + ++nDoc; + } + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nDoc); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157182) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + uno::Sequence aFilterData(comphelper::InitPropertySequence({ + { "PDFUACompliance", uno::Any(true) }, + // only happens with PDF/A-1 + { "SelectPdfVersion", uno::Any(static_cast(1)) }, + })); + aMediaDescriptor["FilterData"] <<= aFilterData; + + saveAsPDF(u"transparentshape.fodp"); + + // just check this does not crash or assert +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf57423) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"Description PDF Export test .odt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + int nFigure(0); + int nFormula(0); + int nDiv(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(rDocElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "Figure") + { + switch (nFigure) + { + case 2: + CPPUNIT_ASSERT_EQUAL(u"QR Code - Tells how to get to Mosegaard"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + case 0: + CPPUNIT_ASSERT_EQUAL(u"Title: Arrows - Description: Explains the " + u"different arrow appearances"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + case 1: + CPPUNIT_ASSERT_EQUAL( + u"My blue triangle - Does not need further description"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + } + ++nFigure; + } + if (pS && pS->GetValue() == "Formula") + { + CPPUNIT_ASSERT_EQUAL( + u"Equation 1 - Now we give the full description of eq 1 here"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + ++nFormula; + } + if (pS && pS->GetValue() == "Div") + { + switch (nDiv) + { + case 0: + CPPUNIT_ASSERT_EQUAL(u"This frame has a description"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + case 1: + // no properties set on this + CPPUNIT_ASSERT(!pObject->Lookup("Alt"_ostr)); + break; + case 2: + CPPUNIT_ASSERT_EQUAL(u"My textbox - Has a light background"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + case 3: + CPPUNIT_ASSERT_EQUAL(u"Hey! There is no alternate text for Frame " + u"// but maybe not needed?"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + } + ++nDiv; + } + } + } + CPPUNIT_ASSERT_EQUAL(int(3), nFigure); + CPPUNIT_ASSERT_EQUAL(int(1), nFormula); + CPPUNIT_ASSERT_EQUAL(int(4), nDiv); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf154982) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf154982.odt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + int nFigure(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(rDocElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "Figure") + { + switch (nFigure) + { + case 0: + CPPUNIT_ASSERT_EQUAL(u"Here comes the signature - Please sign here"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + case 1: + CPPUNIT_ASSERT_EQUAL(u"Home"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + } + + // the problem was that the figures in the hell layer were not + // below their anchor paragraphs in the structure tree + auto pParentRef + = dynamic_cast(pObject->Lookup("P"_ostr)); + CPPUNIT_ASSERT(pParentRef); + auto pParent(pParentRef->LookupObject()); + CPPUNIT_ASSERT(pParent); + auto pParentType + = dynamic_cast(pParent->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pParentType->GetValue()); + auto pParentS + = dynamic_cast(pParent->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pParentS->GetValue()); + + auto pPParentRef + = dynamic_cast(pParent->Lookup("P"_ostr)); + CPPUNIT_ASSERT(pPParentRef); + auto pPParent(pPParentRef->LookupObject()); + CPPUNIT_ASSERT(pPParent); + auto pPParentType + = dynamic_cast(pPParent->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pPParentType->GetValue()); + auto pPParentS + = dynamic_cast(pPParent->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Document"_ostr, pPParentS->GetValue()); + ++nFigure; + } + } + } + CPPUNIT_ASSERT_EQUAL(int(2), nFigure); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf157397) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"PDF_export_with_formcontrol.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + vcl::filter::PDFObjectElement* pDocument(nullptr); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Document") + { + pDocument = pObject1; + } + } + } + CPPUNIT_ASSERT(pDocument); + + auto pKids1 = dynamic_cast(pDocument->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1); + // assume there are no MCID ref at this level + auto pKids1v = pKids1->GetElements(); + auto pRefKid12 = dynamic_cast(pKids1v[2]); + CPPUNIT_ASSERT(pRefKid12); + auto pObject12 = pRefKid12->LookupObject(); + CPPUNIT_ASSERT(pObject12); + auto pType12 = dynamic_cast(pObject12->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType12->GetValue()); + auto pS12 = dynamic_cast(pObject12->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Text#20body"_ostr, pS12->GetValue()); + + auto pKids12 = dynamic_cast(pObject12->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids12); + // assume there are no MCID ref at this level + auto pKids12v = pKids12->GetElements(); + auto pRefKid120 = dynamic_cast(pKids12v[0]); + CPPUNIT_ASSERT(pRefKid120); + auto pObject120 = pRefKid120->LookupObject(); + CPPUNIT_ASSERT(pObject120); + auto pType120 = dynamic_cast(pObject120->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType120->GetValue()); + auto pS120 = dynamic_cast(pObject120->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS120->GetValue()); + + { + auto pKids = dynamic_cast(pObject120->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://klexikon.zum.de/wiki/Kläranlage"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAA + = dynamic_cast(pAnnot->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAA); + auto pAAType + = dynamic_cast(pAA->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Action"_ostr, pAAType->GetValue()); + auto pAAS + = dynamic_cast(pAA->LookupElement("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("URI"_ostr, pAAS->GetValue()); + auto pAAURI = dynamic_cast( + pAA->LookupElement("URI"_ostr)); + CPPUNIT_ASSERT_EQUAL("https://klexikon.zum.de/wiki/Kl%C3%A4ranlage"_ostr, + pAAURI->GetValue()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKid13 = dynamic_cast(pKids1v[3]); + CPPUNIT_ASSERT(pRefKid13); + auto pObject13 = pRefKid13->LookupObject(); + CPPUNIT_ASSERT(pObject13); + auto pType13 = dynamic_cast(pObject13->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType13->GetValue()); + auto pS13 = dynamic_cast(pObject13->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Text#20body"_ostr, pS13->GetValue()); + + auto pKids13 = dynamic_cast(pObject13->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids13); + // assume there are no MCID ref at this level + auto pKids13v = pKids13->GetElements(); + auto pRefKid130 = dynamic_cast(pKids13v[0]); + CPPUNIT_ASSERT(pRefKid130); + auto pObject130 = pRefKid130->LookupObject(); + CPPUNIT_ASSERT(pObject130); + auto pType130 = dynamic_cast(pObject130->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType130->GetValue()); + auto pS130 = dynamic_cast(pObject130->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS130->GetValue()); + + { + auto pKids = dynamic_cast(pObject130->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://de.wikipedia.org/wiki/Kläranlage#Mechanische_Vorreinigung"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAA + = dynamic_cast(pAnnot->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAA); + auto pAAType + = dynamic_cast(pAA->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Action"_ostr, pAAType->GetValue()); + auto pAAS + = dynamic_cast(pAA->LookupElement("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("URI"_ostr, pAAS->GetValue()); + auto pAAURI = dynamic_cast( + pAA->LookupElement("URI"_ostr)); + CPPUNIT_ASSERT_EQUAL( + "https://de.wikipedia.org/wiki/Kl%C3%A4ranlage#Mechanische_Vorreinigung"_ostr, + pAAURI->GetValue()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKid14 = dynamic_cast(pKids1v[4]); + CPPUNIT_ASSERT(pRefKid14); + auto pObject14 = pRefKid14->LookupObject(); + CPPUNIT_ASSERT(pObject14); + auto pType14 = dynamic_cast(pObject14->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType14->GetValue()); + auto pS14 = dynamic_cast(pObject14->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Text#20body"_ostr, pS14->GetValue()); + + auto pKids14 = dynamic_cast(pObject14->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids14); + // assume there are no MCID ref at this level + auto pKids14v = pKids14->GetElements(); + auto pRefKid140 = dynamic_cast(pKids14v[0]); + CPPUNIT_ASSERT(pRefKid140); + auto pObject140 = pRefKid140->LookupObject(); + CPPUNIT_ASSERT(pObject140); + auto pType140 = dynamic_cast(pObject140->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType140->GetValue()); + auto pS140 = dynamic_cast(pObject140->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS140->GetValue()); + + { + auto pKids = dynamic_cast(pObject140->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAContents = dynamic_cast( + pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL( + u"https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAContents)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pASubtype->GetValue()); + auto pAA + = dynamic_cast(pAnnot->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAA); + auto pAAType + = dynamic_cast(pAA->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Action"_ostr, pAAType->GetValue()); + auto pAAS + = dynamic_cast(pAA->LookupElement("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("URI"_ostr, pAAS->GetValue()); + auto pAAURI = dynamic_cast( + pAA->LookupElement("URI"_ostr)); + CPPUNIT_ASSERT_EQUAL( + "https://vr-easy.com/tour/usr/220113-virtuellerschulausflug/#pano=24"_ostr, + pAAURI->GetValue()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } + + auto pRefKid16 = dynamic_cast(pKids1v[6]); + CPPUNIT_ASSERT(pRefKid16); + auto pObject16 = pRefKid16->LookupObject(); + CPPUNIT_ASSERT(pObject16); + auto pType16 = dynamic_cast(pObject16->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType16->GetValue()); + auto pS16 = dynamic_cast(pObject16->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Text#20body"_ostr, pS16->GetValue()); + + auto pKids16 = dynamic_cast(pObject16->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids16); + // assume there are no MCID ref at this level + auto pKids16v = pKids16->GetElements(); + auto pRefKid160 = dynamic_cast(pKids16v[0]); + CPPUNIT_ASSERT(pRefKid160); + auto pObject160 = pRefKid160->LookupObject(); + CPPUNIT_ASSERT(pObject160); + auto pType160 = dynamic_cast(pObject160->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType160->GetValue()); + auto pS160 = dynamic_cast(pObject160->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pS160->GetValue()); + auto pA160Dict = dynamic_cast(pObject160->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pA160Dict); + auto pA160O = dynamic_cast(pA160Dict->LookupElement("O"_ostr)); + CPPUNIT_ASSERT(pA160O); + CPPUNIT_ASSERT_EQUAL("PrintField"_ostr, pA160O->GetValue()); + auto pA160Role + = dynamic_cast(pA160Dict->LookupElement("Role"_ostr)); + CPPUNIT_ASSERT(pA160Role); + CPPUNIT_ASSERT_EQUAL("tv"_ostr, pA160Role->GetValue()); + + { + auto pKids = dynamic_cast(pObject160->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef = dynamic_cast( + pObjR->LookupElement("Obj"_ostr)); + auto pAnnot = pAnnotRef->LookupObject(); + auto pAType + = dynamic_cast(pAnnot->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pAType->GetValue()); + auto pASubtype + = dynamic_cast(pAnnot->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT_EQUAL("Widget"_ostr, pASubtype->GetValue()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf135192) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"tdf135192-1.fodp"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + int nTable(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructElem") + { + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + if (pS1 && pS1->GetValue() == "Table") + { + int nTR(0); + auto pKids1 + = dynamic_cast(pObject1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1); + // there can be additional children, such as MCID ref + for (auto pKid1 : pKids1->GetElements()) + { + auto pRefKid1 = dynamic_cast(pKid1); + if (pRefKid1) + { + auto pObject2 = pRefKid1->LookupObject(); + if (pObject2) + { + auto pType2 = dynamic_cast( + pObject2->Lookup("Type"_ostr)); + if (pType2 && pType2->GetValue() == "StructElem") + { + auto pS2 = dynamic_cast( + pObject2->Lookup("S"_ostr)); + if (pS2 && pS2->GetValue() == "TR") + { + int nTD(0); + auto pKids2 = dynamic_cast( + pObject2->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids2); + for (auto pKid2 : pKids2->GetElements()) + { + auto pRefKid2 + = dynamic_cast( + pKid2); + if (pRefKid2) + { + auto pObject3 = pRefKid2->LookupObject(); + if (pObject3) + { + auto pType3 + = dynamic_cast( + pObject3->Lookup("Type"_ostr)); + if (pType3 && pType3->GetValue() == "StructElem") + { + auto pS3 = dynamic_cast< + vcl::filter::PDFNameElement*>( + pObject3->Lookup("S"_ostr)); + if (nTR == 0 && pS3 && pS3->GetValue() == "TH") + { + int nOTable(0); + auto pAttrs = dynamic_cast< + vcl::filter::PDFArrayElement*>( + pObject3->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAttrs != nullptr); + for (const auto& rAttrRef : + pAttrs->GetElements()) + { + auto pAttrDict = dynamic_cast< + vcl::filter::PDFDictionaryElement*>( + rAttrRef); + CPPUNIT_ASSERT(pAttrDict != nullptr); + auto pOwner = dynamic_cast< + vcl::filter::PDFNameElement*>( + pAttrDict->LookupElement("O"_ostr)); + CPPUNIT_ASSERT(pOwner != nullptr); + if (pOwner->GetValue() == "Table") + { + auto pScope = dynamic_cast< + vcl::filter::PDFNameElement*>( + pAttrDict->LookupElement( + "Scope"_ostr)); + CPPUNIT_ASSERT(pScope != nullptr); + CPPUNIT_ASSERT_EQUAL( + "Column"_ostr, + pScope->GetValue()); + ++nOTable; + } + } + CPPUNIT_ASSERT_EQUAL(int(1), nOTable); + ++nTD; + } + else if (nTR != 0 && pS3 + && pS3->GetValue() == "TD") + { + ++nTD; + } + } + } + } + } + CPPUNIT_ASSERT_EQUAL(int(3), nTD); + ++nTR; + } + } + } + } + } + CPPUNIT_ASSERT_EQUAL(int(2), nTR); + ++nTable; + } + } + } + CPPUNIT_ASSERT_EQUAL(int(1), nTable); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf154955) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + saveAsPDF(u"grouped-shape.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(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(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 (o3tl::starts_with(line, "/Artifact ")) + { + CPPUNIT_ASSERT_EQUAL_MESSAGE("unexpected nesting", Default, state); + state = Artifact; + ++nArtifacts; + } + else if (o3tl::starts_with(line, "/Figure< 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(2), nTagged); + CPPUNIT_ASSERT(nArtifacts >= 1); + + int nFigure(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(rDocElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "StructElem") + { + auto pS = dynamic_cast(pObject->Lookup("S"_ostr)); + if (pS && pS->GetValue() == "Figure") + { + switch (nFigure) + { + case 0: + CPPUNIT_ASSERT_EQUAL(u"Two rectangles - Grouped"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + case 1: + CPPUNIT_ASSERT_EQUAL(u"these ones are green"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pObject->Lookup("Alt"_ostr)))); + break; + } + + auto pParentRef + = dynamic_cast(pObject->Lookup("P"_ostr)); + CPPUNIT_ASSERT(pParentRef); + auto pParent(pParentRef->LookupObject()); + CPPUNIT_ASSERT(pParent); + auto pParentType + = dynamic_cast(pParent->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pParentType->GetValue()); + auto pParentS + = dynamic_cast(pParent->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Standard"_ostr, pParentS->GetValue()); + + ++nFigure; + } + } + } + // the problem was that there were 4 shapes (the sub-shapes of the 2 groups) + CPPUNIT_ASSERT_EQUAL(int(2), nFigure); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf155190) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + + saveAsPDF(u"tdf155190.odt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + auto nDiv(0); + auto nFigure(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + + auto pS1 = dynamic_cast(pObject1->Lookup("S"_ostr)); + // start with the text box + if (pType1 && pType1->GetValue() == "StructElem" && pS1 && pS1->GetValue() == "Div") + { + ++nDiv; + auto pKids1 = dynamic_cast(pObject1->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids1); + for (auto pKid1 : pKids1->GetElements()) + { + auto pRefKid1 = dynamic_cast(pKid1); + if (pRefKid1) + { + auto pObject2 = pRefKid1->LookupObject(); + CPPUNIT_ASSERT(pObject2); + auto pType2 + = dynamic_cast(pObject2->Lookup("Type"_ostr)); + CPPUNIT_ASSERT(pType2); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType2->GetValue()); + auto pS2 + = dynamic_cast(pObject2->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("FigureCaption"_ostr, pS2->GetValue()); + auto pKids2 + = dynamic_cast(pObject2->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids2); + // there are additional children, MCID ref + for (auto pKid2 : pKids2->GetElements()) + { + auto pRefKid2 = dynamic_cast(pKid2); + if (pRefKid2) + { + auto pObject3 = pRefKid2->LookupObject(); + CPPUNIT_ASSERT(pObject3); + auto pType3 = dynamic_cast( + pObject3->Lookup("Type"_ostr)); + if (pType3 && pType3->GetValue() == "StructElem") + { + auto pS3 = dynamic_cast( + pObject3->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Figure"_ostr, pS3->GetValue()); + auto pAlt = dynamic_cast( + pObject3->Lookup("Alt"_ostr)); + CPPUNIT_ASSERT_EQUAL( + OUString("Picture of apples"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAlt)); + auto pKids3 = dynamic_cast( + pObject3->Lookup("K"_ostr)); + CPPUNIT_ASSERT(pKids3); + // the problem was that this didn't reference an MCID + CPPUNIT_ASSERT(!pKids3->GetElements().empty()); + ++nFigure; + } + } + } + } + } + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nDiv); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nFigure); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testMediaShapeAnnot) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + + saveAsPDF(u"vid.odt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + + // There should be one annotation + CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnnots->GetElements().size()); + auto pAnnotReference + = dynamic_cast(pAnnots->GetElements()[0]); + CPPUNIT_ASSERT(pAnnotReference); + // check /Annot - produced by sw + vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + CPPUNIT_ASSERT_EQUAL( + "Annot"_ostr, + static_cast(pAnnot->Lookup("Type"_ostr))->GetValue()); + CPPUNIT_ASSERT_EQUAL( + "Screen"_ostr, + static_cast(pAnnot->Lookup("Subtype"_ostr))->GetValue()); + + auto pA = dynamic_cast(pAnnot->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pA); + auto pR = dynamic_cast(pA->LookupElement("R"_ostr)); + CPPUNIT_ASSERT(pR); + auto pC = dynamic_cast(pR->LookupElement("C"_ostr)); + CPPUNIT_ASSERT(pC); + auto pCT = dynamic_cast(pC->LookupElement("CT"_ostr)); + CPPUNIT_ASSERT_EQUAL("video/webm"_ostr, pCT->GetValue()); + auto pD = dynamic_cast(pC->LookupElement("D"_ostr)); + CPPUNIT_ASSERT(pD); + auto pDesc = dynamic_cast(pD->LookupElement("Desc"_ostr)); + CPPUNIT_ASSERT(pDesc); + CPPUNIT_ASSERT_EQUAL(OUString("alternativloser text\nand some description"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pDesc)); + auto pAlt = dynamic_cast(pC->LookupElement("Alt"_ostr)); + CPPUNIT_ASSERT(pAlt); + auto pLang = dynamic_cast(pAlt->GetElement(0)); + CPPUNIT_ASSERT_EQUAL(""_ostr, pLang->GetValue()); + auto pAltText = dynamic_cast(pAlt->GetElement(1)); + CPPUNIT_ASSERT_EQUAL(OUString("alternativloser text\nand some description"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAltText)); + + auto pStructParent + = dynamic_cast(pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); + + vcl::filter::PDFReferenceElement* pStructElemRef(nullptr); + + // check ParentTree to find StructElem + auto nRoots(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructTreeRoot") + { + ++nRoots; + auto pParentTree = dynamic_cast( + pObject1->Lookup("ParentTree"_ostr)); + CPPUNIT_ASSERT(pParentTree); + auto pNumTree = pParentTree->LookupObject(); + CPPUNIT_ASSERT(pNumTree); + auto pNums = dynamic_cast(pNumTree->Lookup("Nums"_ostr)); + CPPUNIT_ASSERT(pNums); + auto nFound(0); + for (size_t i = 0; i < pNums->GetElements().size(); i += 2) + { + auto pI = dynamic_cast(pNums->GetElement(i)); + if (pI->GetValue() == pStructParent->GetValue()) + { + ++nFound; + CPPUNIT_ASSERT(i < pNums->GetElements().size() - 1); + pStructElemRef + = dynamic_cast(pNums->GetElement(i + 1)); + CPPUNIT_ASSERT(pStructElemRef); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nFound); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRoots); + + // check /StructElem - produced by drawinglayer + CPPUNIT_ASSERT(pStructElemRef); + auto pStructElem(pStructElemRef->LookupObject()); + CPPUNIT_ASSERT(pStructElem); + + auto pType = dynamic_cast(pStructElem->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType->GetValue()); + auto pS = dynamic_cast(pStructElem->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Annot"_ostr, pS->GetValue()); + auto pSEAlt = dynamic_cast(pStructElem->Lookup("Alt"_ostr)); + CPPUNIT_ASSERT_EQUAL(OUString("alternativloser text - and some description"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pSEAlt)); + auto pKids = dynamic_cast(pStructElem->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef + = dynamic_cast(pObjR->LookupElement("Obj"_ostr)); + CPPUNIT_ASSERT_EQUAL(pAnnot, pAnnotRef->LookupObject()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFlyFrameHyperlinkAnnot) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + + saveAsPDF(u"image-hyperlink-alttext.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + + // There should be one annotation + CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnnots->GetElements().size()); + auto pAnnotReference + = dynamic_cast(pAnnots->GetElements()[0]); + CPPUNIT_ASSERT(pAnnotReference); + // check /Annot - produced by sw + vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + CPPUNIT_ASSERT_EQUAL( + "Annot"_ostr, + static_cast(pAnnot->Lookup("Type"_ostr))->GetValue()); + CPPUNIT_ASSERT_EQUAL( + "Link"_ostr, + static_cast(pAnnot->Lookup("Subtype"_ostr))->GetValue()); + + auto pContents + = dynamic_cast(pAnnot->Lookup("Contents"_ostr)); + CPPUNIT_ASSERT_EQUAL(OUString("Image2"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pContents)); + + auto pStructParent + = dynamic_cast(pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); + + vcl::filter::PDFReferenceElement* pStructElemRef(nullptr); + + // check ParentTree to find StructElem + auto nRoots(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructTreeRoot") + { + ++nRoots; + auto pParentTree = dynamic_cast( + pObject1->Lookup("ParentTree"_ostr)); + CPPUNIT_ASSERT(pParentTree); + auto pNumTree = pParentTree->LookupObject(); + CPPUNIT_ASSERT(pNumTree); + auto pNums = dynamic_cast(pNumTree->Lookup("Nums"_ostr)); + CPPUNIT_ASSERT(pNums); + auto nFound(0); + for (size_t i = 0; i < pNums->GetElements().size(); i += 2) + { + auto pI = dynamic_cast(pNums->GetElement(i)); + if (pI->GetValue() == pStructParent->GetValue()) + { + ++nFound; + CPPUNIT_ASSERT(i < pNums->GetElements().size() - 1); + pStructElemRef + = dynamic_cast(pNums->GetElement(i + 1)); + CPPUNIT_ASSERT(pStructElemRef); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nFound); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRoots); + + // check /StructElem - produced by sw painting code + CPPUNIT_ASSERT(pStructElemRef); + auto pStructElem(pStructElemRef->LookupObject()); + CPPUNIT_ASSERT(pStructElem); + + auto pType = dynamic_cast(pStructElem->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType->GetValue()); + auto pS = dynamic_cast(pStructElem->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Link"_ostr, pS->GetValue()); + auto pKids = dynamic_cast(pStructElem->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef + = dynamic_cast(pObjR->LookupElement("Obj"_ostr)); + CPPUNIT_ASSERT_EQUAL(pAnnot, pAnnotRef->LookupObject()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); + + // the Link is inside a Figure + auto pParentRef + = dynamic_cast(pStructElem->Lookup("P"_ostr)); + CPPUNIT_ASSERT(pParentRef); + auto pParent(pParentRef->LookupObject()); + CPPUNIT_ASSERT(pParent); + auto pParentType = dynamic_cast(pParent->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pParentType->GetValue()); + auto pParentS = dynamic_cast(pParent->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Figure"_ostr, pParentS->GetValue()); + auto pAlt = dynamic_cast(pParent->Lookup("Alt"_ostr)); + CPPUNIT_ASSERT_EQUAL(OUString("Ship drawing - Very cute"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAlt)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testFormControlAnnot) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable PDF/UA + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "PDFUACompliance", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + + saveAsPDF(u"formcontrol.fodt"); + + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + + // There should be one annotation + CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnnots->GetElements().size()); + auto pAnnotReference + = dynamic_cast(pAnnots->GetElements()[0]); + CPPUNIT_ASSERT(pAnnotReference); + // check /Annot + vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + CPPUNIT_ASSERT_EQUAL( + "Annot"_ostr, + static_cast(pAnnot->Lookup("Type"_ostr))->GetValue()); + CPPUNIT_ASSERT_EQUAL( + "Widget"_ostr, + static_cast(pAnnot->Lookup("Subtype"_ostr))->GetValue()); + auto pT = dynamic_cast(pAnnot->Lookup("T"_ostr)); + CPPUNIT_ASSERT(pT); + CPPUNIT_ASSERT_EQUAL("Check Box 1"_ostr, pT->GetValue()); + auto pTU = dynamic_cast(pAnnot->Lookup("TU"_ostr)); + CPPUNIT_ASSERT(pTU); + CPPUNIT_ASSERT_EQUAL(OUString("helpful text"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pTU)); + + auto pStructParent + = dynamic_cast(pAnnot->Lookup("StructParent"_ostr)); + CPPUNIT_ASSERT(pStructParent); + + vcl::filter::PDFReferenceElement* pStructElemRef(nullptr); + + // check ParentTree to find StructElem + auto nRoots(0); + for (const auto& rDocElement : aDocument.GetElements()) + { + auto pObject1 = dynamic_cast(rDocElement.get()); + if (!pObject1) + continue; + auto pType1 = dynamic_cast(pObject1->Lookup("Type"_ostr)); + if (pType1 && pType1->GetValue() == "StructTreeRoot") + { + ++nRoots; + auto pParentTree = dynamic_cast( + pObject1->Lookup("ParentTree"_ostr)); + CPPUNIT_ASSERT(pParentTree); + auto pNumTree = pParentTree->LookupObject(); + CPPUNIT_ASSERT(pNumTree); + auto pNums = dynamic_cast(pNumTree->Lookup("Nums"_ostr)); + CPPUNIT_ASSERT(pNums); + auto nFound(0); + for (size_t i = 0; i < pNums->GetElements().size(); i += 2) + { + auto pI = dynamic_cast(pNums->GetElement(i)); + if (pI->GetValue() == pStructParent->GetValue()) + { + ++nFound; + CPPUNIT_ASSERT(i < pNums->GetElements().size() - 1); + pStructElemRef + = dynamic_cast(pNums->GetElement(i + 1)); + CPPUNIT_ASSERT(pStructElemRef); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nFound); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRoots); + + // check /StructElem + CPPUNIT_ASSERT(pStructElemRef); + auto pStructElem(pStructElemRef->LookupObject()); + CPPUNIT_ASSERT(pStructElem); + + auto pType = dynamic_cast(pStructElem->Lookup("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("StructElem"_ostr, pType->GetValue()); + auto pS = dynamic_cast(pStructElem->Lookup("S"_ostr)); + CPPUNIT_ASSERT_EQUAL("Form"_ostr, pS->GetValue()); + auto pAlt = dynamic_cast(pStructElem->Lookup("Alt"_ostr)); + CPPUNIT_ASSERT_EQUAL(OUString("textuelle alternative - a box to check"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE(*pAlt)); + auto pA = dynamic_cast(pStructElem->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pA); + auto pO = dynamic_cast(pA->LookupElement("O"_ostr)); + CPPUNIT_ASSERT(pO); + CPPUNIT_ASSERT_EQUAL("PrintField"_ostr, pO->GetValue()); + auto pRole = dynamic_cast(pA->LookupElement("Role"_ostr)); + CPPUNIT_ASSERT(pRole); + CPPUNIT_ASSERT_EQUAL("cb"_ostr, pRole->GetValue()); + auto pKids = dynamic_cast(pStructElem->Lookup("K"_ostr)); + auto nMCID(0); + auto nRef(0); + for (size_t i = 0; i < pKids->GetElements().size(); ++i) + { + auto pNum = dynamic_cast(pKids->GetElement(i)); + auto pObjR = dynamic_cast(pKids->GetElement(i)); + if (pNum) + { + ++nMCID; + } + if (pObjR) + { + ++nRef; + auto pOType + = dynamic_cast(pObjR->LookupElement("Type"_ostr)); + CPPUNIT_ASSERT_EQUAL("OBJR"_ostr, pOType->GetValue()); + auto pAnnotRef + = dynamic_cast(pObjR->LookupElement("Obj"_ostr)); + CPPUNIT_ASSERT_EQUAL(pAnnot, pAnnotRef->LookupObject()); + } + } + CPPUNIT_ASSERT_EQUAL(static_cast(1), nMCID); + CPPUNIT_ASSERT_EQUAL(static_cast(1), nRef); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf142129) +{ + loadFromFile(u"master.odm"); + + // update linked section + dispatchCommand(mxComponent, ".uno:UpdateAllLinks", {}); + + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // Enable Outlines export + uno::Sequence aFilterData( + comphelper::InitPropertySequence({ { "ExportBookmarks", uno::Any(true) } })); + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + auto* pCatalog = aDocument.GetCatalog(); + CPPUNIT_ASSERT(pCatalog); + auto* pCatalogDictionary = pCatalog->GetDictionary(); + CPPUNIT_ASSERT(pCatalogDictionary); + auto* pOutlinesObject = pCatalogDictionary->LookupObject("Outlines"_ostr); + CPPUNIT_ASSERT(pOutlinesObject); + auto* pOutlinesDictionary = pOutlinesObject->GetDictionary(); +#if 0 + // Type isn't actually written currently + auto* pType + = dynamic_cast(pOutlinesDictionary->LookupElement("Type")); + CPPUNIT_ASSERT(pType); + CPPUNIT_ASSERT_EQUAL(OString("Outlines"), pType->GetValue()); +#endif + + auto* pFirst = dynamic_cast( + pOutlinesDictionary->LookupElement("First"_ostr)); + CPPUNIT_ASSERT(pFirst); + auto* pFirstD = pFirst->LookupObject()->GetDictionary(); + CPPUNIT_ASSERT(pFirstD); + //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast(pFirstD->LookupElement("Type"))->GetValue()); + CPPUNIT_ASSERT_EQUAL(u"Preface"_ustr, ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pFirstD->LookupElement("Title"_ostr)))); + + auto* pFirst1 + = dynamic_cast(pFirstD->LookupElement("First"_ostr)); + CPPUNIT_ASSERT(pFirst1); + auto* pFirst1D = pFirst1->LookupObject()->GetDictionary(); + CPPUNIT_ASSERT(pFirst1D); + // here is a hidden section with headings "Copyright" etc.; check that + // there are no outline entries for it + //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast(pFirst1D->LookupElement("Type"))->GetValue()); + CPPUNIT_ASSERT_EQUAL(u"Who is this book for?"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pFirst1D->LookupElement("Title"_ostr)))); + + auto* pFirst2 + = dynamic_cast(pFirst1D->LookupElement("Next"_ostr)); + auto* pFirst2D = pFirst2->LookupObject()->GetDictionary(); + CPPUNIT_ASSERT(pFirst2D); + //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast(pFirst2D->LookupElement("Type"))->GetValue()); + CPPUNIT_ASSERT_EQUAL(u"What\u2019s in this book?"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pFirst2D->LookupElement("Title"_ostr)))); + + auto* pFirst3 + = dynamic_cast(pFirst2D->LookupElement("Next"_ostr)); + auto* pFirst3D = pFirst3->LookupObject()->GetDictionary(); + CPPUNIT_ASSERT(pFirst3D); + //CPPUNIT_ASSERT_EQUAL(OString("Outlines"), dynamic_cast(pFirst3D->LookupElement("Type"))->GetValue()); + CPPUNIT_ASSERT_EQUAL(u"Minimum requirements for using LibreOffice"_ustr, + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast( + pFirst3D->LookupElement("Title"_ostr)))); + + CPPUNIT_ASSERT_EQUAL(static_cast(nullptr), + pFirst3D->LookupElement("Next"_ostr)); + CPPUNIT_ASSERT_EQUAL(static_cast(nullptr), + pFirstD->LookupElement("Next"_ostr)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfImageRotate180) +{ + // Create an empty document. + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xText = xTextDocument->getText(); + uno::Reference xCursor = xText->createTextCursor(); + + // Insert the PDF image. + uno::Reference xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference xGraphicObject( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + OUString aURL = createFileURL(u"pdf-image-rotate-180.pdf"); + xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL)); + uno::Reference xShape(xGraphicObject, uno::UNO_QUERY); + xShape->setSize(awt::Size(1000, 1000)); + uno::Reference xTextContent(xGraphicObject, uno::UNO_QUERY); + xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false); + + // Save as PDF. + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + // Make sure that the page -> form -> form has a child image. + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + std::unique_ptr pPageObject = pPdfPage->getObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType()); + // 2: white background and the actual object. + CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount()); + std::unique_ptr pFormObject = pPageObject->getFormObject(1); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pFormObject->getType()); + CPPUNIT_ASSERT_EQUAL(1, pFormObject->getFormObjectCount()); + + // Check if the inner form object (original page object in the pdf image) has the correct + // rotation. + std::unique_ptr pInnerFormObject = pFormObject->getFormObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pInnerFormObject->getType()); + CPPUNIT_ASSERT_EQUAL(1, pInnerFormObject->getFormObjectCount()); + std::unique_ptr pImage = pInnerFormObject->getFormObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Image, pImage->getType()); + basegfx::B2DHomMatrix aMat = pInnerFormObject->getMatrix(); + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate = 0; + double fShearX = 0; + aMat.decompose(aScale, aTranslate, fRotate, fShearX); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: -1 + // - Actual : 1 + // i.e. the 180 degrees rotation didn't happen (via a combination of horizontal + vertical + // flip). + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1.0, aScale.getX(), 0.01); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf144222) +{ +// Assume Windows has the font for U+4E2D +#ifdef _WIN32 + aMediaDescriptor["FilterName"] <<= OUString("calc_pdf_Export"); + saveAsPDF(u"tdf144222.ods"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + std::unique_ptr pTextPage = pPdfPage->getTextPage(); + CPPUNIT_ASSERT(pTextPage); + + int nPageObjectCount = pPdfPage->getObjectCount(); + const OUString sChar = u"\u4E2D"_ustr; + basegfx::B2DRectangle aRect1, aRect2; + int nCount = 0; + + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPdfPageObject = pPdfPage->getObject(i); + if (pPdfPageObject->getType() == vcl::pdf::PDFPageObjectType::Text) + { + ++nCount; + OUString sText = pPdfPageObject->getText(pTextPage); + if (sText == sChar) + aRect1 = pPdfPageObject->getBounds(); + else + aRect2 = pPdfPageObject->getBounds(); + } + } + + CPPUNIT_ASSERT_EQUAL(2, nCount); + CPPUNIT_ASSERT(!aRect1.isEmpty()); + CPPUNIT_ASSERT(!aRect2.isEmpty()); + CPPUNIT_ASSERT(!aRect1.overlaps(aRect2)); +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf145873) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("impress_pdf_Export"); + saveAsPDF(u"tdf145873.pptx"); + + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + int nPageObjectCount = pPdfPage->getObjectCount(); + + // tdf#145873: Without the fix #1 in place, this test would have failed with + // - Expected: 66 + // - Actual : 3 + CPPUNIT_ASSERT_EQUAL(66, nPageObjectCount); + + auto pObject = pPdfPage->getObject(4); + CPPUNIT_ASSERT_MESSAGE("no object", pObject != nullptr); + + // tdf#145873: Without the fix #2 in place, this test would have failed with + // - Expected: 13.40 + // - Actual : 3.57... + // - Delta : 0.1 + CPPUNIT_ASSERT_DOUBLES_EQUAL(13.40, pObject->getBounds().getWidth(), 0.1); + // - Expected: 13.79 + // - Actual : 3.74... + // - Delta : 0.1 + CPPUNIT_ASSERT_DOUBLES_EQUAL(13.79, pObject->getBounds().getHeight(), 0.1); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfImageHyperlink) +{ + // Given a Draw file, containing a PDF image, which has a hyperlink in it: + aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export"); + + // When saving to PDF: + saveAsPDF(u"pdf-image-hyperlink.odg"); + + // Then make sure that link is preserved: + std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + // Without the accompanying fix in place, this test would have failed, the hyperlink of the PDF + // image was lost. + CPPUNIT_ASSERT(pPdfPage->hasLinks()); + + // Also test the precision of the form XObject. + // Given a full-page form XObject, page height is 27.94 cm (792 points): + // When writing the reciprocal of the object height to PDF: + std::unique_ptr pFormObject; + for (int i = 0; i < pPdfPage->getObjectCount(); ++i) + { + std::unique_ptr pObject = pPdfPage->getObject(i); + if (pObject->getType() == vcl::pdf::PDFPageObjectType::Form) + { + pFormObject = std::move(pObject); + break; + } + } + CPPUNIT_ASSERT(pFormObject); + std::unique_ptr pInnerFormObject; + for (int i = 0; i < pFormObject->getFormObjectCount(); ++i) + { + std::unique_ptr pObject = pFormObject->getFormObject(i); + if (pObject->getType() == vcl::pdf::PDFPageObjectType::Form) + { + pInnerFormObject = std::move(pObject); + break; + } + } + CPPUNIT_ASSERT(pInnerFormObject); + // Then make sure that enough digits are used, so the point size is unchanged: + basegfx::B2DHomMatrix aMatrix = pInnerFormObject->getMatrix(); + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate{}; + double fShearX{}; + aMatrix.decompose(aScale, aTranslate, fRotate, fShearX); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 0.0012626264 + // - Actual : 0.00126 + // i.e. the rounded reciprocal was 794 points, not the original 792. + CPPUNIT_ASSERT_EQUAL(0.0012626264, rtl::math::round(aScale.getY(), 10)); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testURIs) +{ + struct + { + OUString in; + OString out; + bool relativeFsys; + } URIs[] = { { + "http://example.com/", + "http://example.com/"_ostr, + true, + }, + { + "file://localfile.odt/", + "file://localfile.odt/"_ostr, + true, + }, + { + // tdf 143216 + "http://username:password@example.com", + "http://username:password@example.com"_ostr, + true, + }, + { + "git://git.example.org/project/example", + "git://git.example.org/project/example"_ostr, + true, + }, + { + // The odt/pdf gets substituted due to 'ConvertOOoTargetToPDFTarget' + "filebypath.odt", + "filebypath.pdf"_ostr, + true, + }, + { + // The odt/pdf gets substituted due to 'ConvertOOoTargetToPDFTarget' + // but this time with ExportLinksRelativeFsys off the path is added + "filebypath.odt", + OUStringToOString(utl::GetTempNameBaseDirectory(), RTL_TEXTENCODING_UTF8) + + "filebypath.pdf", + false, + }, + { + // This also gets made relative due to 'ExportLinksRelativeFsys' + utl::GetTempNameBaseDirectory() + "fileintempdir.odt", + "fileintempdir.pdf"_ostr, + true, + } }; + + // Create an empty document. + // Note: The test harness gets very upset if we try and create multiple + // documents, or recreate it; so reuse one instance for all the links + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xText = xTextDocument->getText(); + uno::Reference xCursor = xText->createTextCursor(); + xText->insertString(xCursor, "Test pdf", /*bAbsorb=*/false); + + // Set the name so it can do relative name replacement + uno::Reference xModel(mxComponent, uno::UNO_QUERY); + xModel->attachResource(maTempFile.GetURL(), xModel->getArgs()); + + for (unsigned int i = 0; i < (sizeof(URIs) / sizeof(URIs[0])); i++) + { + // Test the filename rewriting + uno::Sequence aFilterData(comphelper::InitPropertySequence({ + { "ExportLinksRelativeFsys", uno::Any(URIs[i].relativeFsys) }, + { "ConvertOOoTargetToPDFTarget", uno::Any(true) }, + })); + aMediaDescriptor["FilterData"] <<= aFilterData; + + // Add a link (based on testNestedHyperlink in rtfexport3) + xCursor->gotoStart(/*bExpand=*/false); + xCursor->gotoEnd(/*bExpand=*/true); + uno::Reference xCursorProps(xCursor, uno::UNO_QUERY); + xCursorProps->setPropertyValue("HyperLinkURL", uno::Any(URIs[i].in)); + + // Save as PDF. + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Use the filter rather than the pdfium route, as per the tdf105093 test, it's + // easier to parse the annotations + vcl::filter::PDFDocument aDocument; + + // Parse the export result. + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + auto pAnnots + = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + + // There should be one annotation + CPPUNIT_ASSERT_EQUAL(static_cast(1), pAnnots->GetElements().size()); + auto pAnnotReference + = dynamic_cast(pAnnots->GetElements()[0]); + CPPUNIT_ASSERT(pAnnotReference); + vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + // We're expecting something like /Type /Annot /A << /Type /Action /S /URI /URI (path) + CPPUNIT_ASSERT_EQUAL( + "Annot"_ostr, + static_cast(pAnnot->Lookup("Type"_ostr))->GetValue()); + CPPUNIT_ASSERT_EQUAL( + "Link"_ostr, + static_cast(pAnnot->Lookup("Subtype"_ostr))->GetValue()); + auto pAction = dynamic_cast(pAnnot->Lookup("A"_ostr)); + CPPUNIT_ASSERT(pAction); + auto pURIElem = dynamic_cast( + pAction->LookupElement("URI"_ostr)); + CPPUNIT_ASSERT(pURIElem); + // Check it matches + CPPUNIT_ASSERT_EQUAL(URIs[i].out, pURIElem->GetValue()); + // tdf#148934 check a11y + CPPUNIT_ASSERT_EQUAL( + OUString("Test pdf"), + ::vcl::filter::PDFDocument::DecodeHexStringUTF16BE( + *dynamic_cast(pAnnot->Lookup("Contents"_ostr)))); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfImageAnnots) +{ + // Given a document with a PDF image that has 2 comments (popup, text) and a hyperlink: + aMediaDescriptor["FilterName"] <<= OUString("draw_pdf_Export"); + + // When saving to PDF: + saveAsPDF(u"pdf-image-annots.odg"); + + // Then make sure only the hyperlink is kept, since Draw itself has its own comments: + std::unique_ptr pPdfDocument = parsePDFExport(); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 3 + // i.e. not only the hyperlink but also the 2 comments were exported, leading to duplication. + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getAnnotationCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testPdfImageEncryption) +{ + // Given an empty document, with an inserted PDF image: + mxComponent = loadFromDesktop("private:factory/swriter"); + uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference xText = xTextDocument->getText(); + uno::Reference xCursor = xText->createTextCursor(); + uno::Reference xFactory(mxComponent, uno::UNO_QUERY); + uno::Reference xGraphicObject( + xFactory->createInstance("com.sun.star.text.TextGraphicObject"), uno::UNO_QUERY); + OUString aURL = createFileURL(u"rectangles.pdf"); + xGraphicObject->setPropertyValue("GraphicURL", uno::Any(aURL)); + uno::Reference xShape(xGraphicObject, uno::UNO_QUERY); + xShape->setSize(awt::Size(1000, 1000)); + uno::Reference xTextContent(xGraphicObject, uno::UNO_QUERY); + xText->insertTextContent(xCursor->getStart(), xTextContent, /*bAbsorb=*/false); + + // When saving as encrypted PDF: + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + uno::Sequence aFilterData = { + comphelper::makePropertyValue("EncryptFile", true), + comphelper::makePropertyValue("DocumentOpenPassword", OUString("secret")), + }; + aMediaDescriptor["FilterData"] <<= aFilterData; + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Then make sure that the image is not lost: + std::unique_ptr pPdfDocument = parsePDFExport("secret"_ostr); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + std::unique_ptr pPageObject = pPdfPage->getObject(0); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Form, pPageObject->getType()); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2 + // - Actual : 0 + // i.e. instead of the white background and the actual form child, the image was lost due to + // missing encryption. + CPPUNIT_ASSERT_EQUAL(2, pPageObject->getFormObjectCount()); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testBitmapScaledown) +{ + // FIXME: the DPI check should be removed when either (1) the test is fixed to work with + // non-default DPI; or (2) unit tests on Windows are made to use svp VCL plugin. + if (!IsDefaultDPI()) + return; + + // Given a document with an upscaled and rotated barcode bitmap in it: + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + + // When saving as PDF: + saveAsPDF(u"bitmap-scaledown.odt"); + + // Then verify that the bitmap is not downscaled: + std::unique_ptr pPdfDocument = parsePDFExport(); + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + int nPageObjectCount = pPdfPage->getObjectCount(); + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPdfPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Image) + continue; + + std::unique_ptr pBitmap = pPageObject->getImageBitmap(); + CPPUNIT_ASSERT(pBitmap); + // In-file sizes: good is 2631x380, bad is 1565x14. + int nWidth = pBitmap->getWidth(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 2616 + // - Actual : 1565 + // i.e. the bitmap in the pdf result was small enough to be blurry. + CPPUNIT_ASSERT_EQUAL(2616, nWidth); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf139627) +{ +#if HAVE_MORE_FONTS + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"justified-arabic-kashida.odt"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has one page. + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + std::unique_ptr pPdfPage = pPdfDocument->openPage(/*nIndex=*/0); + CPPUNIT_ASSERT(pPdfPage); + + // 7 objects, 3 text, others are path + int nPageObjectCount = pPdfPage->getObjectCount(); + CPPUNIT_ASSERT_EQUAL(7, nPageObjectCount); + + // 3 text objects + OUString sText[3]; + + /* With "Noto Sans Arabic" font, these are the X ranges on Linux: + 0: ( 61.75 - 415.94) + 1: (479.70 - 422.40) + 2: (209.40 - 453.2) + */ + basegfx::B2DRectangle aRect[3]; + + std::unique_ptr pTextPage = pPdfPage->getTextPage(); + std::unique_ptr pPageObject; + + int nTextObjectCount = 0; + for (int i = 0; i < nPageObjectCount; ++i) + { + pPageObject = pPdfPage->getObject(i); + CPPUNIT_ASSERT_MESSAGE("no object", pPageObject != nullptr); + if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Text) + { + sText[nTextObjectCount] = pPageObject->getText(pTextPage); + aRect[nTextObjectCount] = pPageObject->getBounds(); + ++nTextObjectCount; + } + } + CPPUNIT_ASSERT_EQUAL(3, nTextObjectCount); + + // Text: جِـرم (which means "mass" in Persian) + // Rendered as (left to right): "reh + mim" - "kasreh" - "jeh + tatweel" + int rehmim = 0, kasreh = 1, jehtatweel = 2; + + CPPUNIT_ASSERT_EQUAL(u"رم"_ustr, sText[rehmim].trim()); + CPPUNIT_ASSERT_EQUAL(u""_ustr, sText[kasreh].trim()); + CPPUNIT_ASSERT_EQUAL(u""_ustr, sText[jehtatweel].trim()); + + // "Kasreh" should be within "jeh" character + CPPUNIT_ASSERT_GREATER(aRect[jehtatweel].getMinX(), aRect[kasreh].getMinX()); + CPPUNIT_ASSERT_LESS(aRect[jehtatweel].getMaxX(), aRect[kasreh].getMaxX()); + + // "Tatweel" should cover "jeh" and "reh"+"mim" to avoid gap + // Checking right gap + //CPPUNIT_ASSERT_GREATER(aRect[jehtatweel].getMinX(), aRect[tatweel].getMaxX()); + // Checking left gap + // Kashida fails to reach to rehmim before the series of patches starting + // with 3901e029bd39575f700e69a73818565d62226a23. The visible symptom is + // a gap in the left of Kashida. + CPPUNIT_ASSERT_LESS(aRect[rehmim].getMaxX(), aRect[jehtatweel].getMinX()); + + // Overlappings of Kashida and surrounding characters is ~9% of the width + // of the "jeh" character, while using "Noto Arabic Sans" font in this + // specific example. + // We set the hard limit of 10% here. + CPPUNIT_ASSERT_LESS(0.1, fabs(aRect[rehmim].getMaxX() - aRect[jehtatweel].getMinX()) + / aRect[jehtatweel].getWidth()); +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testRexportRefToKids) +{ + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, OUString("1").pData); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"ref-to-kids.pdf", aDocument); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size()); + + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"_ostr); + CPPUNIT_ASSERT(pResources); + + auto pXObjects + = dynamic_cast(pResources->Lookup("XObject"_ostr)); + CPPUNIT_ASSERT(pXObjects); + + // Without the fix LookupObject for all /Im's will fail. + for (auto const& rPair : pXObjects->GetItems()) + { + if (rPair.first.startsWith("Im")) + CPPUNIT_ASSERT(pXObjects->LookupObject(rPair.first)); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testRexportFilterSingletonArray) +{ + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, OUString("1").pData); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + // Loading fails with tagged PDF enabled + load(u"ref-to-kids.pdf", aDocument, false); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size()); + + // Directly go to the inner XObject Im5 that contains the rectangle drawings. + auto pInnerIm = aDocument.LookupObject(5); + CPPUNIT_ASSERT(pInnerIm); + + auto pFilter = dynamic_cast(pInnerIm->Lookup("Filter"_ostr)); + CPPUNIT_ASSERT(pFilter); + CPPUNIT_ASSERT_EQUAL_MESSAGE("Filter must be FlateDecode", "FlateDecode"_ostr, + pFilter->GetValue()); + + vcl::filter::PDFStreamElement* pStream = pInnerIm->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()); + + // Without the fix, the stream is doubly compressed, + // hence one decompression will not yield the "re" expressions. + auto pStart = static_cast(aUncompressed.GetData()); + const char* pEnd = pStart + aUncompressed.GetSize(); + OString aImage = "100 0 30 50 re B*\n70 67 50 30 re B*\n"_ostr; + auto it = std::search(pStart, pEnd, aImage.getStr(), aImage.getStr() + aImage.getLength()); + CPPUNIT_ASSERT(it != pEnd); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testRexportMediaBoxOrigin) +{ + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, OUString("1").pData); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"ref-to-kids.pdf", aDocument); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size()); + + // Directly go to the inner XObject Im12 that contains the rectangle drawings in page 2. + auto pInnerIm = aDocument.LookupObject(12); + CPPUNIT_ASSERT(pInnerIm); + + constexpr sal_Int32 aOrigin[2] = { -800, -600 }; + sal_Int32 aSize[2] = { 0, 0 }; + + auto pBBox = dynamic_cast(pInnerIm->Lookup("BBox"_ostr)); + CPPUNIT_ASSERT(pBBox); + const auto& rElements2 = pBBox->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements2.size()); + for (sal_Int32 nIdx = 0; nIdx < 4; ++nIdx) + { + const auto* pNumElement = dynamic_cast(rElements2[nIdx]); + CPPUNIT_ASSERT(pNumElement); + if (nIdx < 2) + CPPUNIT_ASSERT_EQUAL(aOrigin[nIdx], static_cast(pNumElement->GetValue())); + else + aSize[nIdx - 2] = static_cast(pNumElement->GetValue()) - aOrigin[nIdx - 2]; + } + + auto pMatrix = dynamic_cast(pInnerIm->Lookup("Matrix"_ostr)); + CPPUNIT_ASSERT(pMatrix); + const auto& rElements = pMatrix->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(6), rElements.size()); + sal_Int32 aMatTranslate[6] + = { // Rotation by $\theta$ $cos(\theta), sin(\theta), -sin(\theta), cos(\theta)$ + 0, -1, 1, 0, + // Translate x,y + -aOrigin[1] - aSize[1] / 2 + aSize[0] / 2, aOrigin[0] + aSize[0] / 2 + aSize[1] / 2 + }; + + for (sal_Int32 nIdx = 0; nIdx < 6; ++nIdx) + { + const auto* pNumElement = dynamic_cast(rElements[nIdx]); + CPPUNIT_ASSERT(pNumElement); + CPPUNIT_ASSERT_EQUAL(aMatTranslate[nIdx], static_cast(pNumElement->GetValue())); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testRexportResourceItemReference) +{ + // We need to enable PDFium import (and make sure to disable after the test) + bool bResetEnvVar = false; + if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr) + { + bResetEnvVar = true; + osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, OUString("1").pData); + } + comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() { + if (bResetEnvVar) + osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData); + }); + + // Load the PDF and save as PDF + vcl::filter::PDFDocument aDocument; + load(u"ref-to-kids.pdf", aDocument); + + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size()); + + // Directly go to the inner XObject Im12 that has reference to Font in page 2. + auto pInnerIm = aDocument.LookupObject(12); + CPPUNIT_ASSERT(pInnerIm); + + auto pResources + = dynamic_cast(pInnerIm->Lookup("Resources"_ostr)); + CPPUNIT_ASSERT(pResources); + auto pFontsReference + = dynamic_cast(pResources->LookupElement("Font"_ostr)); + CPPUNIT_ASSERT(pFontsReference); + + auto pFontsObject = pFontsReference->LookupObject(); + CPPUNIT_ASSERT(pFontsObject); + + auto pFontDict + = dynamic_cast(pFontsObject->Lookup("FF132"_ostr)); + CPPUNIT_ASSERT(pFontDict); + + auto pFontDescriptor = pFontDict->LookupObject("FontDescriptor"_ostr); + CPPUNIT_ASSERT(pFontDescriptor); + + auto pFontWidths = pFontDict->LookupObject("Widths"_ostr); + CPPUNIT_ASSERT(pFontWidths); +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf152246) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"content-control-rtl.docx"); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(maTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Position array + constexpr double aPos[5][4] = { { 56.699, 707.701, 131.401, 721.499 }, + { 198.499, 707.701, 273.201, 721.499 }, + { 303.349, 680.101, 378.051, 693.899 }, + { 480.599, 680.101, 555.301, 693.899 }, + { 56.699, 652.501, 131.401, 666.299 } }; + + // Get page annotations. + auto pAnnots = dynamic_cast(aPages[0]->Lookup("Annots"_ostr)); + CPPUNIT_ASSERT(pAnnots); + CPPUNIT_ASSERT_EQUAL(static_cast(5), pAnnots->GetElements().size()); + for (sal_Int32 i = 0; i < 5; ++i) + { + auto pAnnotReference + = dynamic_cast(pAnnots->GetElements()[i]); + CPPUNIT_ASSERT(pAnnotReference); + vcl::filter::PDFObjectElement* pAnnot = pAnnotReference->LookupObject(); + CPPUNIT_ASSERT(pAnnot); + CPPUNIT_ASSERT_EQUAL( + "Annot"_ostr, + static_cast(pAnnot->Lookup("Type"_ostr))->GetValue()); + CPPUNIT_ASSERT_EQUAL( + "Widget"_ostr, + static_cast(pAnnot->Lookup("Subtype"_ostr))->GetValue()); + + auto pRect = dynamic_cast(pAnnot->Lookup("Rect"_ostr)); + CPPUNIT_ASSERT(pRect); + const auto& rElements = pRect->GetElements(); + CPPUNIT_ASSERT_EQUAL(static_cast(4), rElements.size()); + for (sal_Int32 nIdx = 0; nIdx < 4; ++nIdx) + { + const auto* pNumElement = dynamic_cast(rElements[nIdx]); + CPPUNIT_ASSERT(pNumElement); + CPPUNIT_ASSERT_DOUBLES_EQUAL(aPos[i][nIdx], pNumElement->GetValue(), 1e-6); + } + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf155161) +{ +// TODO: We seem to get a fallback font on Windows +#ifndef _WIN32 + vcl::filter::PDFDocument aDocument; + load(u"tdf155161.odt", aDocument); + + // Check that all fonts in the document are Type 3 fonts + int nFonts = 0; + for (const auto& aElement : aDocument.GetElements()) + { + auto pObject = dynamic_cast(aElement.get()); + if (!pObject) + continue; + auto pType = dynamic_cast(pObject->Lookup("Type"_ostr)); + if (pType && pType->GetValue() == "Font") + { + auto pSubtype + = dynamic_cast(pObject->Lookup("Subtype"_ostr)); + CPPUNIT_ASSERT(pSubtype); + CPPUNIT_ASSERT_EQUAL("Type3"_ostr, pSubtype->GetValue()); + + auto pName = dynamic_cast(pObject->Lookup("Name"_ostr)); + CPPUNIT_ASSERT(pName); + CPPUNIT_ASSERT_EQUAL("Cantarell-Regular"_ostr, pName->GetValue()); + + nFonts++; + } + } + +#ifdef MACOSX + // There must be two fonts + CPPUNIT_ASSERT_EQUAL(2, nFonts); +#else + // But it seems that embedded variable fonts don’t register all supported + // styles on Linux, so the bold and regular text use the same regular font. + CPPUNIT_ASSERT(nFonts); +#endif +#endif +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf48707_1) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf48707-1.fodt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + auto pPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT(pPage); + + int nPageObjectCount = pPage->getObjectCount(); + + CPPUNIT_ASSERT_EQUAL(6, nPageObjectCount); + + auto pTextPage = pPage->getTextPage(); + + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPage->getObject(i); + // The text and path objects (underline and overline) should all be red. + if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Text) + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, pPageObject->getFillColor()); + else + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, pPageObject->getStrokeColor()); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf48707_2) +{ + // Import the bugdoc and export as PDF. + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"tdf48707-2.fodt"); + + // Parse the export result with pdfium. + std::unique_ptr pPdfDocument = parsePDFExport(); + + CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount()); + + auto pPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT(pPage); + + int nPageObjectCount = pPage->getObjectCount(); + + CPPUNIT_ASSERT_EQUAL(13, nPageObjectCount); + + auto pTextPage = pPage->getTextPage(); + + for (int i = 0; i < nPageObjectCount; ++i) + { + std::unique_ptr pPageObject = pPage->getObject(i); + if (pPageObject->getType() != vcl::pdf::PDFPageObjectType::Path) + continue; + + // The table-like paths should be red, underline and overline should be black. + if (i >= 8) + CPPUNIT_ASSERT_EQUAL(COL_BLACK, pPageObject->getStrokeColor()); + else + CPPUNIT_ASSERT_EQUAL(COL_LIGHTRED, pPageObject->getStrokeColor()); + } +} + +CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf156528) +{ + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + saveAsPDF(u"wide_page1.fodt"); + std::unique_ptr pPdfDocument = parsePDFExport(); + + // The document has two pages + CPPUNIT_ASSERT_EQUAL(2, pPdfDocument->getPageCount()); + + // 1st page (5100 mm width x 210 mm high, UserUnit = 2) + auto pPdfPage = pPdfDocument->openPage(0); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(5100.0 / 2, o3tl::Length::mm, o3tl::Length::pt), + pPdfPage->getWidth(), 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(210.0 / 2, o3tl::Length::mm, o3tl::Length::pt), + pPdfPage->getHeight(), 1); + + // 1 object (rectangle 5060 mm width x 170 mm high, UserUnit = 2) + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + auto pRect = pPdfPage->getObject(0); + CPPUNIT_ASSERT(pRect); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Path, pRect->getType()); + auto bounds = pRect->getBounds(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(5060.0 / 2, o3tl::Length::mm, o3tl::Length::pt), + bounds.getWidth(), 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(170.0 / 2, o3tl::Length::mm, o3tl::Length::pt), + bounds.getHeight(), 1); + + // 2nd page (210 mm width x 297 mm high, UserUnit = 1) + pPdfPage = pPdfDocument->openPage(1); + CPPUNIT_ASSERT(pPdfPage); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(210.0, o3tl::Length::mm, o3tl::Length::pt), + pPdfPage->getWidth(), 1); + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(297.0, o3tl::Length::mm, o3tl::Length::pt), + pPdfPage->getHeight(), 1); + + // 1 object (rectangle 170 mm width x 257 mm high, UserUnit = 1) + CPPUNIT_ASSERT_EQUAL(1, pPdfPage->getObjectCount()); + pRect = pPdfPage->getObject(0); + CPPUNIT_ASSERT(pRect); + CPPUNIT_ASSERT_EQUAL(vcl::pdf::PDFPageObjectType::Path, pRect->getType()); + bounds = pRect->getBounds(); + // Without the fix, this would fail with + // - Expected: 481.889763779528 + // - Actual : 241.925001144409 + // - Delta : 1 + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(170.0, o3tl::Length::mm, o3tl::Length::pt), + bounds.getWidth(), 1); + // + // - Expected: 728.503937007874 + // - Actual : 365.25 + // - Delta : 1 + CPPUNIT_ASSERT_DOUBLES_EQUAL(o3tl::convert(257.0, o3tl::Length::mm, o3tl::Length::pt), + bounds.getHeight(), 1); +} + +} // end anonymous namespace + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3